这是我参与8月更文挑战的第11天,活动详情查看:8月更文挑战
五、持久化
- AOF(Append Only File)写入日志文件;
- RDB(Redis Database)定期生成快照;
- 执行方式:fork 出一个新进程完成文件重写;
四、单线程设计
为什么常说 Redis 是单线程而不是多线程的?
- 通常瓶颈下来不在于CPU,而是内存和网络IO;
- 简化数据结构和算法实现,减少多线程/锁控制逻辑;
六、实战场景
1. 缓存雪崩
- 场景:大批 key 同时过期。
- 优化方案:(1)设置 key 过期时间+ 随机数(2)互斥锁;
2. 缓存击穿
- 场景:经常访问不存在的键值。
- 优化方案:(1)异步更新,缓存预热(2)完备的拦截机制,如布隆过滤器(3)互斥锁;
3. 缓存并发竞争
- 场景:同时读写一个键值。
- 优化方案:(1)互斥锁;
4. 缓存与数据库保证双写一致性
- 场景:需要保持缓存和数据库的数据一致性。
- 优化方案:由业务代码进行保证,注意读写缓存与读写数据库的操作顺序。
七、集群模式
1. 主从复制同步策略
- 增量复制:将指定存入环状队列;缺点是队列满载会被覆盖;
- 全量复制/快照同步:处理时间长;
2. 哨兵模式(Sentinel)
- 多个哨兵(独立进程)同时监控 Redis 节点,负责故障转移(切换主从角色);
3. 解决方案
(1) Twemproxy
- 单点,代理分片机制(Twitter 开源),按照路由规则进行转发。
- 缺点:无法平滑地扩缩容,运维不友好。
(2) Codis
- Codis = Proxy + Dashboard + Server + ZooKeeper/Etcd。
- 预先分片机制:如划分成 1024 个 slots(CRC32选槽位),可支持 1024 个 Redis Server 实例。
- 引入 Group 概念:相当于小集群,内部可自由进行主备切换。
- 缺点:不支持事务、部分命令如 keys/msetnx。
八、清理策略
- 被动:定时轮询;
- 主动:再次访问时达到TTL,或者内存不足;
- LRU:针对已设置 TTL 的键 volatile-lru / allkeys-lru;
- Random:同上 volatile-random / allkeys-random;
- 执行:随机检测20个带 TTL 标志的键,删除所有过期的键。如果超过 25% 的键过期了,则再次检测&排查&删除。
九、事务支持
- 可用 Lua 脚本 代替;