当缓存里的热点数据过期或者被删除后,大量的请求同时访问数据库,导致数据库服务器宕机。业界的解决方案的使用 mutex。

    何谓 mutex?
    互斥锁(英语:Mutual exclusion,缩写 Mutex)是一种用于多线程编程中,防止两条线程同时对同一公共资源(比如全局变量)进行读写的机制。

    A Mutex is a mutually exclusive flag. It acts as a gate keeper to a section of code allowing one thread in and blocking access to all others. This ensures that the code being controled will only be hit by a single thread at a time. Just be sure to release the mutex when you are done. :)

    在缓存过期后,先判空,不立即去 load db,而是使用缓存工具的某些带成功操作的(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,设置成功了再去load db ,设置缓存,否则重试整个获取缓存的方法。SETNX,是「SET if Not Exists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果。

    1. public String get(key) {
    2. String value = redis.get(key);
    3. if (value == null) { //代表缓存值过期
    4. //设置3min的超时,防止del操作失败的时候,下次缓存过期一直不能load db
    5. if (redis.setnx(key_mutex, 1, 3 * 60) == 1) { //代表设置成功
    6. value = db.get(key);
    7. redis.set(key, value, expire_secs);
    8. redis.del(key_mutex);
    9. } else { //这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可
    10. sleep(50);
    11. get(key); //重试
    12. }
    13. } else {
    14. return value;
    15. }
    16. }