大家好呀,我是 31 岁的小米,一个喜欢折腾后端技术、也喜欢在深夜写代码到掐点吃烤冷面的程序员。这篇文章我准备讲一个发生在我身上的真实故事。
如果你正准备跳槽、面 Java、用到 Redis,那你最好拿杯奶茶坐稳。因为这篇文章会把你从“Redis 面试背八股文的苦哈哈选手”,升级成“能把面试官聊到点头称赞的爽文主角”。
而主角的第一关,就是这个经典又狠的面试题:
Redis 集群会有写操作丢失吗?为什么?
别急,我们慢慢来。
故事从一次“自信满满”的面试开始事情发生在我换工作的那一年。当时我已经有五六年的 Java 经验,自认为 Redis 玩得挺溜,什么五大数据结构、跳表、AOF、RDB、哨兵、集群,这不都懂嘛。
面试那天,我坐在工位对面的玻璃房里,喝着面试官递来的保温杯热水,心想:今天这场,应该稳了。
然而,面试官抬头,看了我一眼,直接来了一句:
“你说说,Redis 集群会有写丢失吗?”
我心里咯噔一下。这问题……不是能不能的问题,而是面试官到底想我从哪儿回答?
因为 Redis 集群的写丢失,取决于:
你说的数据复制?
你说的故障恢复?
你说的 client 端重试?
还是你说的槽迁移?
我灵魂深处那只小猫猫瞬间炸毛。但面试官没给我继续纠结的机会,又补了一句:“从节点切换和网络复制机制两个角度,说说。”
他又补:“如果你觉得不同场景结果不一样,你也可以都讲讲。”
没办法,只能硬着头皮上。于是我告诉他:Redis 集群确实会有写丢失的情况,而且不止一种。
面试官点点头,让我继续说。后来我才知道:
如果我那天回答得再浅一点,估计这面就凉了。
Redis:你以为它不丢,其实它悄悄丢要回答这个问题,我们得先把 Redis 集群的关键机制捋清,Redis 集群的核心逻辑:
主节点负责写
从节点异步复制
主节点挂了,从节点可能提升为主节点
节点间通过 Gossip 协议感知状态
关键在于这条:Redis 的复制是“异步复制”。
异步就意味着:
主节点写成功了
但还没把写同步到从节点
主节点就挂了
从节点被提升为主节点
此时?数据丢了。
而且 Redis 官方文档一直坦诚地写着:
Redis Cluster 在故障切换期间可能会发生数据丢失。
我第一次看到时甚至愣住三秒:“你居然……承认了???”
但后来我越研究越觉得:
异步复制天生就存在风险,不丢也才奇怪。
下面我们进入正题,把所有“会丢”的场景讲个透。这也是面试最容易加分的地方。
场景一:主从异步复制导致写丢失(最常见,也是必考点)这是最基础的丢失场景。只要你说出“异步复制”,面试官就知道你至少没从入门群里来。让我们看一下实际发生了什么。
场景步骤:
客户端向 Master 写入 key:set user:1 xm
Master 接收成功,返回 OK
Master 正要把数据复制到 Slave
命运发动——Master 宕机
Redis 集群投票,让 Slave 升级为 Master
新的 Master 中没有这条数据(因为复制没来得及同步)
结果?write lost. 就这么丢了。我们称这种情况为:Replica Lag(复制延迟引发的数据丢失)
这类丢失属于淘宝级别常见,甚至你重试也救不回来。面试官一般希望你讲到:
Redis 的复制无“强一致保障”
不会等待从节点确认
Redis 集群不是 CP,而是 AP(偏可用性)
如果你再补一句:
Redis 这么做是为了保证高吞吐和低延迟,所以牺牲了数据一致性。
面试官会非常满意。
场景二:网络分区导致写丢失(脑裂)这个场景更有“故事性”。所谓脑裂,就是:
主节点和部分集群通信正常,但在另一部分节点看来,它已经“死了”。
结果:
一部分节点认为 Master 活着
另一部分节点认为 Master 挂了,于是把 Slave 晋升为 Master
此时会产生两个 Master,并接受写入。当网络恢复后,只能保留一个 Master。另一个 Master 上的所有写,全丢。
你可以把这个场景理解为:
Redis 集群在脑裂恢复后,会丢掉被隔离分区上产生的所有写。
为什么?
因为 Redis 的故障恢复依赖多节点投票,当你处于小分区(被少数节点看到),你的写,在大多数节点看来是“无效写”。
这就叫:大多数原则导致的小分区写丢失。
面试官非常喜欢这个点。
场景三:槽迁移时写丢(slot migration)这个很容易被忽略。当 Redis 集群进行水平扩容或缩容时,会迁移槽(slot)。迁移过程中:
旧节点仍然处理写入
新节点也可能接收到写请求
数据在迁移前后短暂出现不一致
迁移过程中如果节点宕机,中间状态的 key 可能丢失
实际开发中,如果不是专业团队,很可能不小心就把数据弄丢了。
Redis 官方也建议:
槽迁移时,不要有写操作,或做好强制重试机制
否则你真的可能在生产看到:“诶?我的 key 呢?昨天还在的啊!”
场景四:客户端重试机制导致“伪写丢失”这个场景可能不是真丢,但行为上“看起来像丢”。例如:
客户端发起写请求
网络波动导致客户端以为写失败
实际上服务端已经写成功
客户端重试写另一个节点
数据出现覆盖或冲突
表面上看丢了,其实是客户端逻辑出了问题。但面试官也会认为你把业务层面考虑得很细。
这通常属于加分项。
总结:Redis 集群会不会丢写?——会,而且不止一种方式面试时最完美的回答结构如下:
Redis 集群确实会出现写丢失,主要原因包含四类:
异步复制引发的数据丢失(最核心原因):Master 写成功后未及时复制到 Slave,主节点宕机导致写丢失。
网络分区导致的脑裂:多个 Master 同时接受写,恢复后弱分区数据被回滚。
槽迁移过程产生的不一致:slot migration 中出现异常导致部分 key 丢失。
客户端重试造成的“伪写丢失”:写成功但客户端误以为失败,导致覆盖或逻辑错误。
然后补一句更高级的:
Redis Cluster 属于 AP 系统,它优先保证可用性,所以一致性不是完全保证的。
最后总结一句灵魂式的:
只要复制不是强同步,就一定存在写丢失风险。
面试官听到这里基本会心一笑。你就知道,这题稳了。

你可以在面试中额外补一句(超加分):
因为强一致复制会带来巨大的性能开销。
这是必然的。想象一下:
Master 每写入一次
都要等待多个 Slave 回复 ack
每次写都阻塞
集群吞吐量会雪崩
延迟至少成倍增加
Redis 的哲学是:
99% 的人更需要高性能,而不是强一致。
如果你真的要强一致,可以使用:
KeyDB(支持多主同步)
Redis 事务(不解决复制一致性)
Raft 协议实现版 Redis(社区版)
但生产场景里,只要你的写请求不是银行级别强一致要求,Redis 的 AP 设计已经够用。
我最后问了面试官一句:你们线上丢过吗?他笑着点头:
“当然丢过,但系统做了补偿。能承受就没问题。”
那一刻我明白了:
不是所有系统都需要绝对不丢,关键在于业务能不能兜得住。

如果你能讲清楚:
redis 为什么会丢?
哪些场景会丢?
为什么官方选择异步?
业务如何容忍?
恭喜你,你已经从“背八股文的应试模式”,进阶到了“能和面试官深入对话的工程师模式”。