redis灵魂拷问:聊一聊主从复制缓冲区

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: redis灵魂拷问:聊一聊主从复制缓冲区

在我之前《redis灵魂拷问:怎样搭建一个哨兵主从集群》搭建的集群主从哨兵集群,有1个主节点和2个从节点环境如下表:

服务

角色

192.168.59.132:6379

主节点

192.168.59.141:6379

从节点1

192.168.59.141:6389

从节点2

主节点启动成功后,我们启动一个从节点。从节点启动成功后,会向主节点发送一个数据同步的命令,格式如下:


psync $master_runid $slave_offset

注意:runid是主库redis实例的一个唯一标识id,是redis实例创建的时候自动生成的。offset是指从节点的复制偏移量。


从库第一次向主节点发送请求时,并不知道主库的runid,也没有偏移量,因为需要全量同步。这时的命令如下:

psync ? -1

主库收到这个请求后,回复一个下面命令,把自己的runid和offset发送给从库:


FULLRESYNC $master_runid $master_offset

之后主库会fork一个bgsave子进程生成一个RDB快照文件发送给从库,由从库完成加载。



上面就是一个全量同步的流程,我用下面的图表示:

微信图片_20221212161246.png

上面的流程图我们只是考虑了RDB文件的全量同步,我们没有考虑RDB同步给从库的这段时间内主库接收到的写请求,我们也没考虑全量同步完成后增量同步。


下面我们聊一聊主从同步过程中的2个重要的缓存区。


replication buffer


上面的主从全量同步过程中,主库是不会阻塞的,这个时候还会继续接收新的写请求。但是从库加载RDB文件完成后怎么处理这段时间内的增量数据呢


这就用到了replication buffer,redis server会为每一个连接到自己的客户端创建一个replication buffer,用来缓存主库执行的命令。等从库加载完成RDB文件后,主库就会把缓存的命令发送给从库,这样就同步完成了。


但是,如果replication buffer写满了怎么办呢?replication buffer是为每个客户端分配的,如果写满了,无论客户端是普通客户端还是从库,只能断开跟这个客户端的连接了。这样从库全量同步失败,只能再次尝试全量同步。


那怎么避免这种情况呢?我们可以在redis.config文件中配置如下参数:

#
# client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>
#
# A client is immediately disconnected once the hard limit is reached, or if
# the soft limit is reached and remains reached for the specified number of
# seconds (continuously).
# So for instance if the hard limit is 32 megabytes and the soft limit is
# 16 megabytes / 10 seconds, the client will get disconnected immediately
# if the size of the output buffers reach 32 megabytes, but will also get
# disconnected if the client reaches 16 megabytes and continuously overcomes
# the limit for 10 seconds.
#
# By default normal clients are not limited because they don't receive data
# without asking (in a push way), but just after a request, so only
# asynchronous clients may create a scenario where data is requested faster
# than it can read.
#
# Instead there is a default limit for pubsub and replica clients, since
# subscribers and replicas receive data in a push fashion.
#
# Both the hard or the soft limit can be disabled by setting them to zero.
client-output-buffer-limit slave 32mb 8mb 60

上面参数中的slave表示这个缓冲区是主从复制缓存区,32mb表示缓冲区最大是32mb,8mb 60表示如果60s内写入量超过8mb,缓冲就会溢出。

可见,把缓冲区最大值调大,或者把每秒允许的写入量增加,可以减小replication buffer溢出的概率。当然,我们也可以控制主节点的写命令接收速率。


repl_backlog_buffer


redis从库加载完成RDB文件后,就会继续同步从库的增量写命令。但是如果同步增量写命令的过程中,主从连接断开了,怎么办呢?重新连接后需要再次进行全量同步吗?


不一定,这时候就要依赖repl_backlog_buffer这个缓冲区了。主库的写命令,除了传给从库后,还会写入repl_backlog_buffer,当主从断开后,重新建立连接,从库会发送之前的那个命令:


psync $master_runid $slave_offset

这个时候,主库就会在repl_backlog_buffer中找到offset的位置,把之后的写命令写入replication buffer同步给从库。


这里要注意,主库不会给每个从库分配一个repl_backlog_buffer,而是所有从库共享一个。


repl_backlog_buffer的结构是一个环形区域,结构如下图:

微信图片_20221212161417.png

如上图,主库按照顺时针方向写命令,从库建立连接后,还有key3和key4这2个命令没有同步,主库只要把这2个命令同步给从库就行了。主库也会记录一个自己的offset,主库offset和从库offset直接的命令就是需要同步的增量命令,这里就是key3和key4。


但是如果环形缓冲区写满了,继续写入就会覆盖之前的命令,如果从库读取慢,从库发送的offset就找不到了,只能进行一次全量同步。怎样避免repl_backlog_buffer写满呢


我们可以根据主库写入的速率和主从同步传输的速率差值来适当调大repl_backlog_buffer的配置,比如配置这个值为差值的2倍以上。对于高并发的情况,我们也可以设置的更大,或者采用切片集群来分散写请求。


配置也在redis.conf文件,如下:

# Set the replication backlog size. The backlog is a buffer that accumulates
# replica data when replicas are disconnected for some time, so that when a
# replica wants to reconnect again, often a full resync is not needed, but a
# partial resync is enough, just passing the portion of data the replica
# missed while disconnected.
#
# The bigger the replication backlog, the longer the time the replica can be
# disconnected and later be able to perform a partial resynchronization.
#
# The backlog is only allocated once there is at least a replica connected.
#
# repl-backlog-size 1mb

总结


1.主从第一次全量同步依赖于RDB文件,主库发送RDB文件给从库,从库清空现有数据并加载RDB文件。

2.主库会为每一个从库建立一个replication buffer,用来发送增量写命令,一旦replication buffer写满了,主从就需要断开,重新进行全量同步。

3.增量数据同步时,为了让主从断开后再次连接后不用全量同步,就需要用到offsetrepl_backlog_buffer,这个缓冲区是所有从库共用的,每个从库记录自己的上次断开的offset,再次连接后发给主库就可以继续接收数据了。

4.offsetrepl_backlog_buffer是一个环形的缓冲区,如果从库断开时间太长导致自己的offset被覆盖了,就只能再次全量同步了。

相关实践学习
基于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
相关文章
|
7月前
|
存储 负载均衡 NoSQL
Redis之主从复制
【1月更文挑战第8天】主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(masterleader),后者称为从节点(slave/follower);数据的复制是单向的,只能由主节点到从节点。Master以写为主,Slave以读为主。 默认情况下,每台Redis服务器都是主节点; 且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
220 8
|
7月前
|
NoSQL 关系型数据库 MySQL
Redis高可用之主从复制架构(第一部分)
Redis高可用之主从复制架构(第一部分)
|
7月前
|
监控 NoSQL 容灾
【Redis】主从复制
【Redis】主从复制
|
5月前
|
存储 缓存 NoSQL
Redis常见面试题(二):redis分布式锁、redisson、主从一致性、Redlock红锁;Redis集群、主从复制,哨兵模式,分片集群;Redis为什么这么快,I/O多路复用模型
redis分布式锁、redisson、可重入、主从一致性、WatchDog、Redlock红锁、zookeeper;Redis集群、主从复制,全量同步、增量同步;哨兵,分片集群,Redis为什么这么快,I/O多路复用模型——用户空间和内核空间、阻塞IO、非阻塞IO、IO多路复用,Redis网络模型
Redis常见面试题(二):redis分布式锁、redisson、主从一致性、Redlock红锁;Redis集群、主从复制,哨兵模式,分片集群;Redis为什么这么快,I/O多路复用模型
|
2月前
|
存储 NoSQL 大数据
大数据-51 Redis 高可用方案CAP-AP 主从复制 一主一从 全量和增量同步 哨兵模式 docker-compose测试
大数据-51 Redis 高可用方案CAP-AP 主从复制 一主一从 全量和增量同步 哨兵模式 docker-compose测试
45 3
|
7月前
|
存储 监控 负载均衡
redis 集群 (主从复制 哨兵模式 cluster)
redis 集群 (主从复制 哨兵模式 cluster)
|
3月前
|
NoSQL 网络协议 Redis
Redis的主从复制和哨兵模式
本文详细介绍了Redis的主从复制配置、原理(包括全量复制和增量复制)以及如何搭建一主二从的Redis集群,同时还探讨了Redis哨兵模式的概念、配置文件、以及如何配置一主二从三哨兵的Redis哨兵模式,以实现高可用性。
|
4月前
|
消息中间件 存储 缓存
深入理解Redis集群主从复制原理
该文章主要探讨了Redis集群中的主从复制原理,包括为何需要主从复制、配置方法、复制流程以及一些高级特性。
深入理解Redis集群主从复制原理
|
5月前
|
NoSQL Redis
Redis 主从复制架构配置及原理
Redis 主从复制架构配置及原理
73 5
|
6月前
|
存储 NoSQL 网络协议
主从复制,Could not connect to Redis at 127.0.0.1:6380: Connection refusednot connected> exit,1.主从模式如何指
主从复制,Could not connect to Redis at 127.0.0.1:6380: Connection refusednot connected> exit,1.主从模式如何指