摘要
redis缓存设计与性能优化
redis缓存设计与性能优化
1. Redis缓存穿透,缓存击穿,缓存雪崩
2. 热点缓存key重建问题
3. 缓存与数据库双写不一致问题
定义:查询一个根本不存在的数据, 缓存层和存储层都不会命中
结果:导致不存在的数据每次请求都要到存储层去查询, 失去了缓存保护后端存储的意义。高并发情况下造成服务崩溃。
解决方案:
1. 缓存空对象
if productid不存在,set key null缓存;
思考:若后期上架了productid一样的产品,会有什么结果?
Answer:可能会导致后上架的产品一直查不到数据
方案:缓存空对象时,设置超时时间
2. 布隆过滤器
布隆过滤器:实现了一种bitMap的过滤器,对于不存在的key数据布隆过滤器一般都能够过滤掉,不让请求再往后端发送。(当布隆过滤器说某个值存在时,这个值可能不存在;当它说不存在时,那就肯定不存在)
这种方法适用于数据命中不高、 数据相对固定、 实时性低(通常是数据集较大) 的应用场景, 代码维护较为 复杂, 但是缓存空间占用很少。
布隆过滤器不能修改其中的数据,例如key删除以后,布隆过滤器中数据还在。优化:定期重建布隆过滤器。
实现 redisson
定义:由于大批量缓存在同一时间失效可能导致大量请求同时穿透缓存直达数据库
结果:会造成数据库瞬间压力过大甚至挂掉
解决方案:在批量增加缓存时最好将这一批数据的缓存过期时间设置为一个时间段内的不同时间(random)
定义:是缓存层支撑不住或宕掉后,流量会打向后端存储层(原因:大并发访问,redis设计不合理)
结果:存储层的调用量会暴增,造成存储层也会级联宕机
解决方案:
1. 改良Redis缓存设计:保证缓存层服务高可用性,比如使用Redis Sentinel或Redis Cluster
2. 在服务中使用隔离组件为后端服务限流/熔断并降级(微服务相关内容Spring Cloud),比如使用Sentinel或Hystrix限流降级组件
例如:非核心数据查询:产品标签,收藏数等,采用服务降级,返回预设定信息或空值或错误提示;暂停从缓存中查询这些数据
核心数据查询:产品库存,价格等,允许查询缓存,如果缓存缺失,也可以继续通过数据库读取
3. 组织进行故障演练,测试环境/生产环境。关键:流量预估,预案设定
定义:在缓存失效的瞬间, 有大量线程来重建缓存(例如:京东抢购板蓝根,“板蓝根”无缓存/缓存失效。冷数据->热点数据:热点数据的缓存重建)
结果:造成后端负载加大, 甚至可能会让应用崩溃
原因:
1. 访问并发量非常大
2. 重建缓存不能在短时间完成, 可能是一个复杂计算,例如复杂的SQL、多次IO、多个依赖等。
解决方案:要避免大量线程同时重建缓存
设置“互斥锁”,同一时间只允许1个线程进行缓存重建,其他线程等待
定义:在大并发下,同时操作数据库与缓存会存在数据不一致性问题
例如:1. 在update产品时,都会更新缓存;并发情况下,由于执行过程不一致卡顿等原因,导致缓存时效性有问题
解决方案:根据具体的场景进行优化,读写不一致较难优化到理想
对于读多写多,又对一致性要求较高的场景,不要使用redis,直接读写数据库(eg: mysql从库用来读,mysql主库用来写)
放入缓存的数据应该是对实时性、一致性要求不是很高的数据。切记不要为了用缓存,同时又要保证绝对的一致性做大量的过度设计和控制,增加系统复杂性!