文章目录1.redis缓存双写一致性问题1. 常见的2种思路是2. 延时双删 (Delayed Double Delete)3.在强一致性场景用锁4.基于 Binlog 的异步更新2.redis持久化问题3.redis数据过期策略4.redis数据淘汰策略1.redis缓存双写一致性问题redis和mysql的数据需要达成一致确保系统在任何时刻都能提供“正确”且“符合逻辑”的数据。1. 常见的2种思路是先删缓存数据再更新数据库数据正常情况A线程先删缓存数据再更新数据库数据B线程查缓存为空去数据库找数据更新缓存。而当A线程删缓存数据在更新数据库前被B线程查缓存为空然后立马找数据库数据旧数据最后A线程再更新数据库导致缓存为旧数据数据库为新数据。先更新数据库再去删缓存数据正常情况A线程更新数据库数据后删除缓存数据B线程查缓存为空去数据库找新数据更新缓存。而当B线程先查缓存数据旧数据然后A线程更新数据库新数据然后删除缓存B线程操作缓存更新之前的旧数据。为什么是“删除”而不是“更新”缓存性能开销 如果缓存结构复杂比如一个大的 JSON每次改数据库都要重新计算并写入缓存代价太高。并发安全 两个写操作并发时如果更新缓存可能会因为网络延迟导致旧值覆盖新值而“删除”操作是幂等的能有效避免脏数据。不论是操作顺序都可能因为线程操作导致不一致此时引入延迟双删2. 延时双删 (Delayed Double Delete)在“先更新数据库再删除缓存”的情况下如果在删除缓存前有一个读请求进来了它会把旧数据重新写回 Redis。为了解决这个极短时间窗口内的不一致可以使用延时双删。先删除 Redis 缓存。再更新 MySQL 数据库。休眠一小段时间比如 500ms。MySQL主从同步需要时间再次删除 Redis 缓存。痛点 休眠时间很难确定且会降低接口的响应速度除非异步删除。3.在强一致性场景用锁使用redisson自带的读写锁共享锁ReadLock)共享读和排他锁WriteLock阻塞读写避免脏数据。4.基于 Binlog 的异步更新原理 应用只负责更新 MySQL。通过一个中间件如 Canal伪装成 MySQL 的从节点监听 MySQL 的 Binlog。流程MySQL 发生变更。Canal 监听到变更把数据发到消息队列如 Kafka/RocketMQ。专门的缓存服务消费消息更新/删除 Redis。优点 业务代码干净不需关心缓存逻辑即使 Redis 宕机消息队列也能保证最终能更新成功2.redis持久化问题RDB (快照模式)RDB 是在指定的时间间隔内将内存中的数据集快照写入磁盘。它就像是给数据“拍张照片”。工作原理 Redis 会 fork 一个子进程由子进程将内存数据写入一个临时的二进制文件.rdb完成后替换旧文件。优点文件紧凑 RDB 文件是压缩后的二进制文件非常适合备份和全量同步。恢复极快 相比 AOF加载 RDB 文件的速度要快得多。缺点数据丢失风险 如果两次快照之间宕机会丢失最后一次快照后的所有数据。性能开销 fork 进程在数据量巨大时可能会导致服务器瞬间卡顿。AOF (追加日志模式)AOF 以日志的形式记录每一个写操作指令。它不记录数据本身而是记录**“怎么操作数据的”**。工作原理 所有的写命令都会追加到 aof_buf 缓冲区中然后根据配置策略刷写到磁盘.aof 文件。刷盘策略 (appendfsync)always每次写操作都同步最安全但性能最差。everysec默认每秒同步一次兼顾性能和安全最多丢 1 秒数据。no交给操作系统决定何时同步性能最好但最不安全。AOF 重写 (Rewrite) 随着时间推移AOF 文件会变得很大。Redis 会自动执行重写剔除冗余命令比如对同一个 Key 的多次修改简化为最后一次结果从而减小体积。RDB是一个快照文件它把数据写到磁盘当redis宕机要恢复数据可以注解从RDB 文件恢复。AOF是追加文件记录了操作命令redis宕机恢复可以通过这个文件再一次执行命令。RDB是二进制文件体积小恢复快但是容易丢数据每隔一段时间才快照AOF慢一些丢数据风险小混合持久化它修改了 AOF 的格式让 AOF 文件的开头是一段 RDB 格式的二进制数据普通快照结尾是增量的 AOF 命令在快照生成期间产生的最新指令。它先正常快照然后后面补新指令。优点 重启恢复速度极快像 RDB同时数据又非常全像 AOF。3.redis数据过期策略1.惰性删除设置该key过期时间后不管等需要该key时再检查是否过期如果过期就删除反之返回该key.优点对cpu友好用到再检查缺点对内存不友好key过期没有用一直在内存里面。2.定期删除每隔一段时间对一些key(一定数量随机key最后会遍历完所有key检查删除过期key.SLOW模式是定时任务执行频率默认10hz每次不超过25msFAST模式执行频率不固定间隔不低于2ms耗时不超过1ms4.redis数据淘汰策略当redis内存不够此时向redis添加新keyredis会按照某一种规则将内存数据删掉。8种淘汰策略noevictioneviction驱逐不淘汰任何key内存满不允许写新数据默认策略allkeys-lru(所有key里淘汰最近最少使用的keyallkeys-lfu淘汰访问频率最低的keyallkeys-random随机淘汰keyvolatile-lruvolatile:易变的在设置了TTL的key淘汰最近最少使用的keyvolatile-lfu淘汰访问频率最低的keyvolatile-random随机淘汰keyvolatile-ttl淘汰最快过期的keyLRU (Least Recently Used) —— 最近最少使用核心逻辑 记录每个 Key 最后一次被访问的时间戳。谁很久没被摸过了就踢谁。缺点 无法应对“突发流量”。如果一个 Key 一年没用刚刚被点了一下它就不会被淘汰而一个非常火热的 Key 如果刚好 1 秒没被点可能会被误杀。LFU (Least Frequently Used) —— 最不经常使用核心逻辑 给每个 Key 带个“计数器”。访问次数越少越容易被踢。优点 真正保留了“高频”数据。即使一个 Key 刚才没被点只要它历史点击率极高依然能存活。