赞
踩
(1)redis挂掉了,请求全部走数据库。
(2)对缓存数据设置相同的过期时间,导致某段时间内缓存失效,请求全部走数据库。
(3)缓存雪崩如果发生了,很可能就把我们的数据库搞垮,导致整个服务瘫痪!
(1)在缓存的时候给过期时间加上一个随机值,这样就会大幅度的减少缓存在同一时间过期。
(2)对于“Redis挂掉了,请求全部走数据库”这种情况,我们可以有以下的思路:
事发前:实现Redis的高可用(主从架构+Sentinel(哨兵) 或者Redis Cluster(集群)),尽量避免 Redis挂掉这种情况发生。
事发中:万一Redis真的挂了,我们可以设置本地缓存(ehcache)+限流(hystrix),尽量避免我们的 数据库被干掉(起码能保证我们的服务还是能正常工作的)
事发后:redis持久化,重启后自动从磁盘上加载数据,快速恢复缓存数据。
(1)请求的数据在缓存大量不命中,导致请求走数据库。
(2)缓存穿透如果发生了,也可能把我们的数据库搞垮,导致整个服务瘫痪!
(1)由于请求的参数是不合法的(每次都请求不存在的参数),于是我们可以使用布隆过滤器或者压缩filter提前拦截,不合法就不让这个请求到数据库层!学习BloomFilter点这里
(2)当我们从数据库找不到的时候,我们也将这个空对象设置到缓存里边去。下次再请求的时候,就可以从缓存里边获取了。这种情况我们一般会将空对象设置一个较短的过期时间。
缓存击穿,就是说某个 key 非常热点,访问非常频繁,处于集中式高并发访问的情况,当这个 key 在失效的瞬间,大量的请求就击穿了缓存,直接请求数据库
(1)设置key永不过期,或者快过期时,通过另一个异步线程重新设置key;
(2)使用互斥锁的方式;
- static Lock reenLock = new ReentrantLock();
-
- public List<String> getData04() throws InterruptedException {
- List<String> result = new ArrayList<String>();
- // 从缓存读取数据
- result = getDataFromCache();
- if (result.isEmpty()) {
- if (reenLock.tryLock()) {
- try {
- System.out.println("我拿到锁了,从DB获取数据库后写入缓存");
- // 从数据库查询数据
- result = getDataFromDB();
- // 将查询到的数据写入缓存
- setDataToCache(result);
- } finally {
- reenLock.unlock();// 释放锁
- }
-
- } else {
- result = getDataFromCache();// 先查一下缓存
- if (result.isEmpty()) {
- System.out.println("我没拿到锁,缓存也没数据,先小憩一下");
- Thread.sleep(100);// 小憩一会儿
- return getData04();// 重试
- }
- }
- }
- return result;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。