Redis分布式基石——主从复制技术详述

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: Redis分布式基石——主从复制技术详述

本文已收录于专栏


❤️《Redis精通系列》❤️


上千人点赞收藏,全套Redis学习资料,大厂必备技能!


目录


1、简介


2、主从复制的演进


2.1 版本2.8以前


2.1.1 同步


2.1.2 命令传播


2.1.3 缺陷


2.2 版本2.8-4.0


2.2.1 改进点


2.2.2 psync如何实现


2.2.3 完整的psync


2.3 版本4.0


1、简介

主从复制是Redis分布式的基石,也是Redis高可用的保障。在Redis中,被复制的服务器称为主服务器(Master),对主服务器进行复制的服务器称为从服务器(Slave)。

image.png主从复制的配置非常简单,有三种方式(其中IP-主服务器IP地址/PORT-主服务器Redis服务端口):


配置文件——redis.conf文件中,配置slaveof ip port

命令——进入Redis客户端执行slaveof ip port

启动参数—— ./redis-server --slaveof ip port

2、主从复制的演进

Redis的主从复制机制,并不是一开始就像6.x版本一样完善,而是一个版本一个版本迭代而来的。它大体上经过三个版本的迭代:


2.8以前

2.8~4.0

4.0以后

随着版本的增长,Redis主从复制机制逐渐完善;但是他们的本质都是围绕同步(sync)和命令传播(command propagate)两个操作展开:


同步(sync):指的是将从服务器的数据状态更新至主服务器当前的数据状态,主要发生在初始化或后续的全量同步。

命令传播(command propagate):当主服务器的数据状态被修改(写/删除等),主从之间的数据状态不一致时,主服务将发生数据改变的命令传播给从服务器,让主从服务器之间的状态重回一致。

2.1 版本2.8以前

2.1.1 同步

2.8以前的版本,从服务器对主服务器的同步需要从服务器向主服务器发生sync命令来完成:

image.png从服务器接收到客户端发送的slaveof ip prot命令,从服务器根据ip:port向主服务器创建套接字连接

套接字成功连接到主服务器后,从服务器会为这个套接字连接关联一个专门用于处理复制工作的文件事件处理器,处理后续的主服务器发送的RDB文件和传播的命令

开始进行复制,从服务器向主服务器发送sync命令

主服务器接收到sync命令后,执行bgsave命令,主服务器主进程fork的子进程会生成一个RDB文件,同时将RDB快照产生后的所有写操作记录在缓冲区中

bgsave命令执行完成后,主服务器将生成的RDB文件发送给从服务器,从服务器接收到RDB文件后,首先会清除本身的全部数据,然后载入RDB文件,将自己的数据状态更新成主服务器的RDB文件的数据状态

主服务器将缓冲区的写命令发送给从服务器,从服务器接收命令,并执行。

主从复制同步步骤完成

2.1.2 命令传播

当同步工作完成之后,主从之间需要通过命令传播来维持数据状态的一致性。

如下图,当前主从服务器之间完成同步工作之后,主服务接收客户端的DEL K6指令后删除了K6,此时从服务器仍然存在K6,主从数据状态并不一致。为了维持主从服务器状态一致,主服务器会将导致自己数据状态发生改变的命令传播到从服务器执行,当从服务器也执行了相同的命令之后,主从服务器之间的数据状态将会保持一致。

image.png2.1.3 缺陷

从上面看不出2.8以前版本的主从复制有什么缺陷,这是因为我们还没有考虑网络波动的情况。了解分布式的兄弟们肯定听说过CAP理论,CAP理论是分布式存储系统的基石,在CAP理论中P(partition网络分区)必然存在,Redis主从复制也不例外。当主从服务器之间出现网络故障,导致一段时间内从服务器与主服务器之间无法通信,当从服务器重新连接上主服务器时,如果主服务器在这段时间内数据状态发生了改变,那么主从服务器之间将出现数据状态不一致。

在Redis 2.8以前的主从复制版本中,解决这种数据状态不一致的方式是通过重新发送sync命令来实现。虽然sync能保证主从服务器数据状态一致,但是很明显sync是一个非常消耗资源的操作。


sync命令执行,主从服务器需要占用的资源:


主服务器执行BGSAVE生成RDB文件,会占用大量CPU、磁盘I/O和内存资源

主服务器将生成的RDB文件发送给从服务器,会占用大量网络带宽,

从服务器接收RDB文件并载入,会导致从服务器阻塞,无法提供服务

从上面三点可以看出,sync命令不仅会导致主服务器的响应能力下降,也会导致从服务器在此期间拒绝对外提供服务。


2.2 版本2.8-4.0

2.2.1 改进点

针对2.8以前的版本,Redis在2.8之后对从服务器重连后的数据状态同步进行了改进。改进的方向是减少全量同步(full resynchronizaztion)的发生,尽可能使用增量同步(partial resynchronization)。在2.8版本之后使用psync命令代替了sync命令来执行同步操作,psync命令同时具备全量同步和增量同步的功能:


全量同步与上一版本(sync)一致

增量同步中对于断线重连后的复制,会根据情况采取不同措施;如果条件允许,仍然只发送从服务缺失的部分数据。

2.2.2 psync如何实现

Redis为了实现从服务器断线重连后的增量同步,增加了三个辅助参数:


复制偏移量(replication offset)

积压缓冲区(replication backlog)

服务器运行id(run id)

2.2.2.1 复制偏移量


在主服务器和从服务器内都会维护一个复制偏移量


主服务器向从服务发送数据,传播N个字节的数据,主服务的复制偏移量增加N

从服务器接收主服务器发送的数据,接收N个字节的数据,从服务器的复制偏移量增加N

正常同步的情况如下:

image.png很明显有了复制偏移量之后,从服务器C断线重连后,主服务器只需要发送从服务器缺少的100字节数据即可。但是主服务器又是如何知道从服务器缺少的是那些数据呢?


2.2.2.2 复制积压缓冲区


复制积压缓冲区是一个固定长度的队列,默认为1MB大小。当主服务器数据状态发生改变,主服务器将数据同步给从服务器的同时会另存一份到复制积压缓冲区中。

image.png当从服务器断线重连后,从服务器通过psync命令将自己的复制偏移量(offset)发送给主服务器,主服务器便可通过这个偏移量来判断进行增量传播还是全量同步。


如果偏移量offset+1的数据仍然在复制积压缓冲区中,那么进行增量同步操作

反之进行全量同步操作,与sync一致

Redis的复制积压缓冲区的大小默认为1MB,如果需要自定义应该如何设置呢?

很明显,我们希望能尽可能的使用增量同步,但是又不希望缓冲区占用过多的内存空间。那么我们可以通过预估Redis从服务断线后重连的时间T,Redis主服务器每秒接收的写命令的内存大小M,来设置复制积压缓冲区的大小S。


S = 2 * M * T


注意这里扩大2倍是为了留有一定的余地,保证绝大部分的断线重连都能采用增量同步。


2.2.2.3 服务器运行 ID


看到这里是不是再想上面已经可以实现断线重连的增量同步了,还要运行ID干嘛?其实还有一种情况没考虑,就是当主服务器宕机后,某台从服务器被选举成为新的主服务器,这种情况我们就通过比较运行ID来区分。


运行ID(run id)是服务器启动时自动生成的40个随机的十六进制字符串,主服务和从服务器均会生成运行ID

当从服务器首次同步主服务器的数据时,主服务器会发送自己的运行ID给从服务器,从服务器会保存在RDB文件中

当从服务器断线重连后,从服务器会向主服务器发送之前保存的主服务器运行ID,如果服务器运行ID匹配,则证明主服务器未发生更改,可以尝试进行增量同步

如果服务器运行ID不匹配,则进行全量同步

2.2.3 完整的psync

完整的psync过程非常的复杂,在2.8-4.0的主从复制版本中已经做到了非常完善。psync命令发送的参数如下:


psync <runid> <offset>


当从服务器没有复制过任何主服务器(并不是主从第一次复制,因为主服务器可能会变化,而是从服务器第一次全量同步),从服务器将会发送:


psync ? -1image.pngimage.png从服务器接收到SLAVEOF 127.0.0.1 6379命令

从服务器返回OK给命令发起方(这里是异步操作,先返回OK,再保存地址和端口信息)

从服务器将IP地址和端口信息保存到Master Host和Master Port中

从服务器根据Master Host和Master Port主动向主服务器发起套接字连接,同时从服务将会未这个套接字连接关联一个专门用于文件复制工作的文件事件处理器,用于后续的RDB文件复制等工作

主服务器接收到从服务器的套接字连接请求,为该请求创建对应的套接字连接之后,并将从服务器看着一个客户端(在主从复制中,主服务器和从服务器之间其实互为客户端和服务端)

套接字连接建立完成,从服务器主动向主服务发送PING命令,如果在指定的超时时间内主服务器返回PONG,则证明套接字连接可用,否则断开重连

如果主服务器设置了密码(masterauth),那么从服务器向主服务器发送AUTH masterauth命令,进行身份验证。注意,如果从服务器发送了密码,主服务并未设置密码,此时主服务会发送no password is set错误;如果主服务器需要密码,而从服务器未发送密码,此时主服务器会发送NOAUTH错误;如果密码不匹配,主服务器会发送invalid password错误。

从服务器向主服务器发送REPLCONF listening-port xxxx(xxxx表示从服务器的端口)。主服务器接收到该命令后会将数据保存起来,当客户端使用INFO replication查询主从信息时能够返回数据

从服务器发送psync命令,此步骤请查看上图psync的两种情况

主服务器与从服务器之间互为客户端,进行数据的请求/响应

主服务器与从服务器之间通过心跳包机制,判断连接是否断开。从服务器每个1秒向主服务器发送命令,REPLCONF ACL offset(从服务器的复制偏移量),该机制可以保证主从之间数据的正确同步,如果偏移量不相等,主服务器将会采取增量/全量同步措施来保证主从之间数据状态一致(增量/全量的选择取决于,offset+1的数据是否仍在复制积压缓冲区中)

2.3 版本4.0

Redis 2.8-4.0版本仍然有一些改进的空间,当主服务器切换时,是否也能进行增量同步呢?因此Redis 4.0版本针对这个问题做了优化处理,psync升级为psync2.0。

psync2.0 抛弃了服务器运行ID,采用了replid和replid2来代替,其中replid存储的是当前主服务器的运行ID,replid2保存的是上一个主服务器运行ID。


复制偏移量(replication offset)

积压缓冲区(replication backlog)

主服务器运行id(replid)

上个主服务器运行id(replid2)

通过replid和replid2我们可以解决主服务器切换时,增量同步的问题:


如果replid等于当前主服务器的运行id,那么判断同步方式增量/全量同步

如果replid不相等,则判断replid2是否相等(是否同属于上一个主服务器的从服务器),如果相等,仍然可以选择增量/全量同步,如果不相等则只能进行全量同步。

本文阅读参考了黄健宏老师著作《Redis设计与实现》、老钱著作《Redis深度历险》等资料


image.png

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
14天前
|
分布式计算 Hadoop 大数据
大数据技术与Python:结合Spark和Hadoop进行分布式计算
【4月更文挑战第12天】本文介绍了大数据技术及其4V特性,阐述了Hadoop和Spark在大数据处理中的作用。Hadoop提供分布式文件系统和MapReduce,Spark则为内存计算提供快速处理能力。通过Python结合Spark和Hadoop,可在分布式环境中进行数据处理和分析。文章详细讲解了如何配置Python环境、安装Spark和Hadoop,以及使用Python编写和提交代码到集群进行计算。掌握这些技能有助于应对大数据挑战。
|
28天前
|
设计模式 安全 Java
【分布式技术专题】「Tomcat技术专题」 探索Tomcat技术架构设计模式的奥秘(Server和Service组件原理分析)
【分布式技术专题】「Tomcat技术专题」 探索Tomcat技术架构设计模式的奥秘(Server和Service组件原理分析)
32 0
|
28天前
|
存储 NoSQL 算法
【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)(二)
【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)
44 0
|
28天前
|
NoSQL 数据处理 调度
【Redis深度专题】「踩坑技术提升」探索Redis 6.0为何必须启用多线程以提升性能与效率
【Redis深度专题】「踩坑技术提升」探索Redis 6.0为何必须启用多线程以提升性能与效率
192 0
|
2天前
|
存储 缓存 运维
软件体系结构 - 缓存技术(5)Redis Cluster
【4月更文挑战第20天】软件体系结构 - 缓存技术(5)Redis Cluster
136 10
|
17天前
|
监控 NoSQL Redis
redis主从复制
redis主从复制
|
27天前
|
存储 监控 安全
金石推荐 | 【分布式技术专题】「单点登录技术架构」一文带领你好好认识以下Saml协议的运作机制和流程模式
金石推荐 | 【分布式技术专题】「单点登录技术架构」一文带领你好好认识以下Saml协议的运作机制和流程模式
63 1
|
28天前
|
存储 NoSQL Redis
作者推荐 |【Redis技术进阶之路】「原理系列开篇」揭秘高效存储模型与数据结构底层实现(SDS)(三)
作者推荐 |【Redis技术进阶之路】「原理系列开篇」揭秘高效存储模型与数据结构底层实现(SDS)
29 0
|
28天前
|
存储 Java 应用服务中间件
【分布式技术专题】「架构实践于案例分析」盘点互联网应用服务中常用分布式事务(刚性事务和柔性事务)的原理和方案
【分布式技术专题】「架构实践于案例分析」盘点互联网应用服务中常用分布式事务(刚性事务和柔性事务)的原理和方案
51 0
|
28天前
|
canal 消息中间件 关系型数据库
【分布式技术专题】「分布式技术架构」MySQL数据同步到Elasticsearch之N种方案解析,实现高效数据同步
【分布式技术专题】「分布式技术架构」MySQL数据同步到Elasticsearch之N种方案解析,实现高效数据同步
78 0

热门文章

最新文章