Redis6为啥引入多线程
- 网络IO瓶颈
- 提升带宽利用率
- 降低延迟
- 充分利用多核CPU
- 略微改变工作模型:多线程主要处理请求的网络IO,执行命令还是单线程
缓存热key问题怎么解决
- 本地缓存:代码中实现本地缓存
- 请求分摊:请求压力非常大,redis节点都承受不住的情况。把热key数据拆分为多个key,集群模式下可以分散在不同的redis节点
- 限流
- 监控报警:接入热key探测系统
缓存大key问题
一般单个key超过10kb被认为是大key,可能会导致
- 网络延迟增大
- 阻塞redis性能
- 内存不足导致OOM
我们可以
- 拆分大key:分段存储数据
- 压缩数据
规范上:
- 更新删除大key时开启惰性删除:避免阻塞整个redis
- SCAN代替KEYS:一批一批遍历数据
缓存与数据库双写不一致问题
首先,对实时性要求非常高的场景不建议使用缓存,使用了缓存就会牺牲一定的实时性。以下方式都是缓解问题
- 利用过期时间,在下一次读取数据时候自动更新(性能高,实时性差)
- 在更新数据库的时候,把缓存删了下一次读取数据时候自动更新(一般与第一种结合使用,性能高,实时性差)
- 使用canal中间键监听binlog异步更新缓存(监听数据更新缓存的过程也有可能不一致)
- 同第二个,不过加一把分布式读写锁(实时性高,性能低,读写串行)
1、2可以加一个更新的分布式锁,防止大量线程在缓存失效时导致数据库压力大
Redis过期key的删除策略
-
惰性删除
当客户端访问一个key时检查key是否过期,过期就会删除。如果有大量过期key没有被再次访问,就会浪费大量空间
-
定期删除
周期性随机抽部分设置了过期时间的key检查是否过期,并删除已过期的key
-
定时删除
创建一个定时器,当key设置有过期时间,且过期时间到达时,由定时器任务立即执行对键的删除操作。CPU压力很大
Key和Value的设计原则
key原则
- 简短精炼:节省内存,命名易理解
- 统一命名规范:例如用:分隔,业务名和id(或者表名和id)
- 避免热Key:负载均衡,集群模式下让key分布均匀到不同的节点
- key唯一性
value设计原则
- 选择合适的数据结构
- 单个value不要过大
- 利用压缩
- TTL设置