
🚀 欢迎来到我的CSDN博客:Optimistic _ chen
✨ 一名热爱技术与分享的全栈开发者,在这里记录成长,专注分享编程技术与实战经验,助力你的技术成长之路,与你共同进步!
🚀我的专栏推荐:
| 专栏 | 内容特色 | 适合人群 |
|---|---|---|
| 🔥C语言从入门到精通 | 系统讲解基础语法、指针、内存管理、项目实战 | 零基础新手、考研党、复习 |
| 🔥Java基础语法 | 系统解释了基础语法、类与对象、继承 | Java初学者 |
| 🔥Java核心技术 | 面向对象、集合框架、多线程、网络编程、新特性解析 | 有一定语法基础的开发者 |
| 🔥Java EE 进阶实战 | Servlet、JSP、SpringBoot、MyBatis、项目案例拆解 | 想快速入门Java Web开发的同学 |
| 🔥Java数据结构与算法 | 图解数据结构、LeetCode刷题解析、大厂面试算法题 | 面试备战、算法爱好者、计算机专业学生 |
| 🔥Redis系列 | 从数据类型到核心特性解析 | 项目必备 |
🚀我的承诺:
✅ 文章配套代码:每篇技术文章都提供完整的可运行代码示例
✅ 持续更新:专栏内容定期更新,紧跟技术趋势
✅ 答疑交流:欢迎在文章评论区留言讨论,我会及时回复(支持互粉)
🚀 关注我,解锁更多技术干货!
⏳ 每天进步一点点,未来惊艳所有人!✍️ 持续更新中,记得⭐收藏关注⭐不迷路 ✨
📌 标签:#技术博客 #编程学习 #Java #C语言 #算法 #程序员
文章目录
单点问题
分布式系统面临一个核心挑战:单点故障问题。当服务器程序仅部署在单一节点时,不仅可能因服务器宕机导致服务中断,还会制约系统性能的提升空间。
为解决这一问题,分布式系统通常采用数据多副本部署策略,将数据复制到多台服务器。这种做法既能实现故障快速恢复,又能有效进行负载均衡 。Redis同样遵循这一原则,通过内置的复制功能,创建多个包含相同数据的Redis副本来确保系统可靠性。
主从复制
复制原因
参与复制的若干个Redis节点划分为主节点和从节点,每个从节点只能有一个主节点,而一个主节点可以有多个从节点。从节点数据要和主节点数据保持一致,这意味着从节点要以主节点的数据为准。
所以复制的数据流只能由主节点到从节点 ,那么如果从节点的数据发生变化要怎么同步数据呢?其实从节点的数据根本不允许写数据。 更准确的是,主从复制主要是针对"读操作",进行并发量&可用性的提高。而写操作的话,无论是可用性还是并发性,都是非常依赖主节点。
启动多个redis服务
启动多个redis-server,但是要注意,新启动的redis-server端口不能和默认端口(6379)冲突。我们有几种方式来指定redis-server的端口:
- 在配置文件中加入slaveof{masterHost}{masterPort}随Redis启动生效
- 在redis-server启动命令时加入:--slaveof{masterHost}{masterPort}生效
- 直接使用redis命令:slaveof{masterHost}{masterPort}生效
在配置文件中设置端口号 ,首先先复制两个配置文件



使用命令启动redis服务:
powershell
redis-server ./slave1.conf
redis-server ./slave2.conf

但是目前三个节点并没有构成主从结构,三个节点想要相互联系、构成主从结构,还需要进行进一步配置!
构造主从结构
配置复制的⽅式有以下三种(修改配置文件一直生效):
- 在配置文件中加入slaveof{masterHost} {masterPort} 随redis启动生效
- 在redis-server启动命令时加入,--slaveof{masterHost} {masterPort} 开始生效
- 直接使用redis命令,slaveof{masterHost} {masterPort} 生效
设置6379为主节点,6380和6381为从节点

注意,修改完redis配置文件后需要重新启动才会生效。
通过netstat -anp|grep redis-serve命令查找所有redis服务,去kill -9 -portredis进程,最后直接启动即可。

启动后就实现了主从结构了。

完成主从复制配置。

通过info replication命令查看节点相关信息

断开复制
slaveof命令不仅可以建立复制,还可以在从节点执行 slaveof no one来断开与主节点的主从复制关系。
注意:当前的修改是临时性的,如果重启redis服务器,仍然会按照配置文件中设置的内容建立主从关系
从节点断开复制后并不会抛弃原有数据,只是无法再从主节点上获取数据变化。通过slaveof命令还可以实现切主操作,将当前从节点的数据源切换到另⼀个主节点。执⾏slaveof {newMasterIp} {newMasterPort} 命令即可.
- 断开与旧主节点的复制关系
- 与新主节点建立复制关系
- 删除从节点当前所有数据
- 从新主节点进行复制操作
主从节点一般由TCP连接 ,那么网络延迟就是要考虑的问题,Redis为我们提供了repl-disable-tcp-nodelay 参数⽤于控制是否关闭TCP_NODELAY,默认为no,即开启tcp-nodelay 功能.
- 关闭tcp-nodelay时,主节点产⽣的命令数据⽆论⼤⼩都会及时地发送给从节点,这样主从之间延迟会变⼩,但增加了⽹络带宽的消耗
- 开启tcp-nodelay时,主节点会合并较⼩的TCP数据包从⽽节省带宽。默认发送时间间隔取决于Linux的内核,⼀般默认为40毫秒。这种配置节省了带宽但增⼤主从之间的延迟
拓扑结构
Redis 的复制拓扑结构可以⽀持单层或多层复制关系:
- 一主一从结构:⼀主⼀从结构是最简单的复制拓扑结构,⽤于主节点出现宕机时从节点提供故障转移⽀持。当应⽤写命令并发量较⾼且需要持久化时,可以只在从节点上开启AOF,这样既可以保证数据安全性同时也避免了持久化对主节点的性能⼲扰
- 一主多从结构:使得应⽤端可以利⽤多个从节点实现读写分离,对于读⽐重较⼤的场景,可以把读命令负载均衡到不同的从节点上来分担压⼒
- 树型主从结构:使得从节点不但可以复制主节点数据,同时可以作为其他从节点的主节点继续向下层复制
复制原理

数据同步psync
Redis 使⽤psync命令完成主从数据同步
powershell
psync replicationid offset
- replicationid(复制ID) :主节点生成的唯一标识,用于标识数据集的特定历史版本。主节点启动时生成一个replicationid ;如果replicationid 设为 ? 并且offset设为 -1 此时就是在尝试进⾏全量复制,若设为具体的数值,尝试进⾏部分复制。
- offset:一个自增的64位整数,记录主节点向从节点发送的字节数 。主节点每发送一个字节数据,offset 加1;记录复制进度,用于确定需要同步的数据范围。如果两个节点,他们的replid和offset都相同,则这两个节点上持有的数据,就⼀定相同。

- 从节点发送psync命令给主节点
- 主节点根据psync参数和自身情况响应结果:
- 如果回复+FULLRESYNC replid offset,则从节点需要进⾏全量复制流程
- 如果回复+CONTINEU,从节点进⾏部分复制流程
- 如果回复-ERR,说明Redis主节点版本过低,不⽀持psync命令。从节点可以使⽤sync命令进⾏全量复制(psync Redis会在主从复制模式下⾃动调⽤执⾏; sync会阻塞redis-server处理其他请求.psync则不会)
全量复制
⼀般⽤于初次复制场景,Redis早期⽀持的复制功能只有全量复制,它会把主节点全部数据⼀次性发送给从节点。
- 从节点发送psync命令给主节点进主节点行数据同步,由于第一次进行复制 ,从节点没有主节点的replicationid和offset,所以发送psync ? -1
- 主节点根据命令,解析出要进⾏全量复制 ,回复 +FULLRESYNC 响应
- 从节点接收主节点的运⾏信息进⾏保存
- 主节点执行
bgsave进行RDB文件持久化 - 从节点发送RDB⽂件给从节点,从节点保存RDB数据到本地硬盘
- 主节点将从⽣成RDB到接收完成期间执⾏的写命令,写⼊缓冲区中,等从节点保存完RDB⽂件后,主节点再将缓冲区内的数据补发给从节点
- 从节点清空⾃⾝原有旧数据
- 从节点加载RDB⽂件得到与主节点⼀致的数据
- 如果从节点加载RDB完成之后,并且开启了AOF持久化功能,它会进⾏bgrewrite操作,得到最近的AOF⽂件

部分复制
⽤于处理在主从复制中因⽹络闪断等原因造成的数据丢失场景,当从节点再次连上主节点后,如果条件允许,主节点会补发数据给从节点。
- 当主从节点之间出现⽹络中断时,如果超过
repl-timeout时间,主节点会认为从节点故障并终端复制连接 - 主从连接中断期间主节点依然响应命令 ,但这些复制命令都因⽹络中断⽆法及时发送给从节点,所以暂时将这些命令滞留在复制积压缓冲区中。
- 当主从节点⽹络恢复后,从节点再次连上主节点
- 从节点将之前保存的
replicationId和offset作为psync的参数发送给主节点,请求进⾏部分复制 - 主节点接到psync请求后,进⾏必要的验证。随后根据offset去复制积压缓冲区查找合适的数据,并响应+CONTINUE给从节点
- 主节点将需要从节点同步的数据发送给从节点,最终完成⼀致性

复制积压缓存区
复制积压缓冲区是保存在主节点上的⼀个固定⻓度的队列,默认⼤⼩为1MB。当主节点(master)连接有从节点(slave)时,若主节点执行写操作,不仅会将该命令同步至从节点,同时还会将其写入复制积压缓冲区。

由于缓冲区本质上是先进先出的定⻓队列,所以能实现保存最近已复制数据的功能,⽤于部分复制和复制命令丢失的数据补救 。相关信息可以通过主节点info replication中:

实时复制
主从节点在建立复制连接后,主节点会把自己收到的修改操作,通过tcp长连接的方式,源源不断的传输给从节点。从节点就会根据这些请求来同时修改自身数据,从而保持和主节点数据的一致性。
另外,tcp连接需要通过心跳包的方式维护连接:
- 主从节点彼此都有心跳检测机制,各自模拟成对方的客户端进行通信
- 主节点默认每隔10秒对从节点发送ping命令,判断从节点的存活性和连接状态
- 从节点默认每隔1秒向主节点发送
replconf ack {offset}命令,给主节点上报自身当前的复制偏移量
如果主节点发现从节点通信延迟超过repl-timeout配置的值,则判断从节点下线,断开复制客户端连接。从节点恢复连接后,心跳机制继续进行。
完结撒花!🎉

如果这篇博客对你有帮助,不妨点个赞支持一下吧!👍
你的鼓励是我创作的最大动力~
✨ 想获取更多干货? 欢迎关注我的专栏 → optimistic_chen
📌 收藏本文,下次需要时不迷路!
我们下期再见!💫 持续更新中......
悄悄说:点击主页有更多精彩内容哦~ 😊
