Redis 缓存优化
# 一、基本介绍
- Redis 作为内存型 key-value 数据库,常常可以用作其他数据库或服务的缓存,能够有效地加速应用的读写速度,同时也可以降低后端负载,但同时也需要解决数据一致性、代码维护等问题;
- 缓存中的数据通常都是有生命周期的,需要在指定时间后被删除或更新,这样可以保证缓存空间在一个可控的范围,同时也需要通过一些策略对数据进行更新保证数据的一致性,常用的更新策略有:LRU/LFU/FIFO算法剔除、超时剔除、主动更新等;
# 二、穿透优化
# 1,现象及原因
- 缓存穿透是指查询一个根本不存在的数据,缓存层和存储层都不会命中;
- 通常出于容错的考虑,如果从存储层查不到数据则不写入缓存层,将会导致不存在的数据每次请求都要到存储层去查询,失去了缓存保护后端存储的意义;
- 通常可以在程序中分别统计总调用数、缓存层命中数、存储层命中数,如果发现大量存储层空命中,可能就是出现了缓存穿透问题;
- 自身业务代码或者数据出现问题,以及一些恶意攻击、爬虫等造成大量中空命;
# 2,解决方式
- 缓存空对象
- 空值做了缓存,意味着缓存层中存了更多的键,需要更多的内存空间需要设置一个较短的过期时间让其自动剔除;
- 缓存层和存储层的数据会有一段时间窗口的不一致,可能会对业务有一定影响;
- 布隆过滤器
- 在访问缓存层和存储层之前,将存在的key用布隆过滤器提前保存起来,做第一层拦截;
- 如果布隆过滤器认为不存在,那么就不会访问缓存层,在一定程度保护了存储层;
# 三、无底洞优化
# 1,现象及原因
- 无底洞就是说投入越多不一定产出越多,对于分布式部署的 Redis,更多的节点不代表更高的性能;
- key-value 数据库通常采用哈希函数将 key 映射到各个节点上,造成 key 的分布与业务无关,当需要添加大量节点做水平扩容时,会导致键值分布到更多的节点上;
- Redis 的分布式部署时,批量操作通常需要从不同节点上获取,相比于单机批量操作只涉及一次网络操作,分布式批量操作会涉及多次网络时间,耗时会不断增大,即节点增多但是性能下降;
# 2,解决方式
- 并行请求,将对多个节点的请求改为并行请求,耗时变为最长的那个节点的耗时;
- 一致性哈希,节点扩容时,不会导致键出现更大范围的扩算,批量操作的次数不会增长过大;
# 四、雪崩优化
# 1,现象及原因
- 由于缓存层承载着大量请求,有效地保护了存储层,但是如果缓存层由于某些原因不能提供服务,所有的请求都会达到存储层,造成存储层也会级联宕机的情况;
# 2,解决方式
- 保证缓存层服务高可用性,多节点多机器多机房部署缓存服务;
- 隔离组件为后端限流并降级,当请求量激增时,后端服务直接丢弃或是返回默认值,避免服务崩溃;
# 五、热点 key 优化
# 1,现象及原因
- 当某个 key 是热点 key,请求量非常大,当 key 过期瞬间有大量线程来重建缓存,造成后端负载大,可能会让服务崩溃;
- 重建缓存也不会在一瞬间完成,在重建缓存期间,也会出现数据不一致的问题;
# 2,解决方式
- 添加分布式锁,在某个时刻只允许一个线程重建缓存,其他线程等待重建缓存的线程执行完,重新从缓存获取数据即可,存在死锁和阻塞的风险;
- 不在 Redis 中设置过期时间,但在其 value中 设置一个逻辑过期时间,当发现超过逻辑过期时间后,会使用单独的线程去构建缓存,不保证一致性;
编辑 (opens new window)
上次更新: 2024/09/24, 14:39:25