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。

流程:

  1. MySQL 发生变更。
  2. Canal 监听到变更,把数据发到消息队列(如 Kafka/RocketMQ)。
  3. 专门的缓存服务消费消息,更新/删除 Redis。
    优点: 业务代码干净,不需关心缓存逻辑;即使 Redis 宕机,消息队列也能保证最终能更新成功

2.redis持久化问题

  1. RDB (快照模式)
    RDB 是在指定的时间间隔内,将内存中的数据集快照写入磁盘。它就像是给数据"拍张照片"。
    工作原理: Redis 会 fork 一个子进程,由子进程将内存数据写入一个临时的二进制文件(.rdb),完成后替换旧文件。
    优点:
    文件紧凑: RDB 文件是压缩后的二进制文件,非常适合备份和全量同步。
    恢复极快: 相比 AOF,加载 RDB 文件的速度要快得多。
    缺点:
    数据丢失风险: 如果两次快照之间宕机,会丢失最后一次快照后的所有数据。
    性能开销: fork 进程在数据量巨大时可能会导致服务器瞬间卡顿。
  2. 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每次不超过25ms

FAST模式执行频率不固定,间隔不低于2ms耗时不超过1ms

4.redis数据淘汰策略

当redis内存不够,此时向redis添加新key,redis会按照某一种规则将内存数据删掉。

8种淘汰策略:

noeviction(eviction:驱逐):不淘汰任何key,内存满不允许写新数据,默认策略

allkeys-lru(所有key里):淘汰最近最少使用的key

allkeys-lfu:淘汰访问频率最低的key

allkeys-random:随机淘汰key

volatile-lru(volatile:易变的,在设置了TTL的key):淘汰最近最少使用的key

volatile-lfu:淘汰访问频率最低的key

volatile-random:随机淘汰key

volatile-ttl:淘汰最快过期的key

  • LRU (Least Recently Used) ------ 最近最少使用
    核心逻辑: 记录每个 Key 最后一次被访问的时间戳。谁很久没被摸过了,就踢谁。
    缺点: 无法应对"突发流量"。如果一个 Key 一年没用,刚刚被点了一下,它就不会被淘汰;而一个非常火热的 Key 如果刚好 1 秒没被点,可能会被误杀。
  • LFU (Least Frequently Used) ------ 最不经常使用
    核心逻辑: 给每个 Key 带个"计数器"。访问次数越少,越容易被踢。
    优点: 真正保留了"高频"数据。即使一个 Key 刚才没被点,只要它历史点击率极高,依然能存活。
相关推荐
Omics Pro1 分钟前
上海AI Lab孙思琦×高张阳:虚拟细胞代码库智能体
数据库·人工智能·算法·机器学习·自然语言处理
Anastasiozzzz12 分钟前
重新定义 Agent 基建:Redis 在现代 AI 与智能体系统中的工程实践
java·人工智能·redis·ai
旺仔不是程序员22 分钟前
相关子查询与性能优化:PostgreSQL 逐行执行的代价与 JOIN 重写
数据库·后端·sql
YangYang9YangYan1 小时前
2026 电商数据运营校招 JD 梳理|岗位任务、技能与面试考点汇总
大数据·数据库·数据分析
Sun 32851 小时前
读懂集中式主备的集群状态与节点角色
数据库·opengauss·集群·节点角色·磐维数据库·运行状态
溪语流沙1 小时前
Django + Vue电商项目第001讲:开篇|注册登录加增删改查,那不是电商
redis·python·mysql·docker·typescript·django·vue
努力努力再努力wz1 小时前
【Redis进阶系列】:从主从复制到 Sentinel,一文建立故障检测、Leader 选举与 Failover 的完整心智模型
数据库·redis·缓存
达梦数据2 小时前
DMDRS搭建部署简介与运行环境
数据库
Omics Pro2 小时前
1个月2轮融资!长寿虚拟细胞
数据库·人工智能·算法·机器学习·自然语言处理
zcn1262 小时前
row_number()函数与group by性能比较
数据库·sql优化改写