最新消息:

Redis的主从同步原理和参数调优

Linux ipcpu 817浏览

Redis的主从同步原理和参数调优.md

一、概述

如同MySQL的主从数据库或者Mongo的副本集,Redis也存在主从同步来保障数据的可用性。

在主从复制中,数据库分为两类,一类是主库(Master),另一类是同步主库数据的从库(Slave)。主库可以进行读写操作,当写操作导致数据变化时会自动同步到从库。而从库一般是只读的(特定情况也可以写,通过参数slave-read-only指定),并接受来自主库的数据。一个主库可拥有多个从库,而一个从库只能有一个主库。这样就使得redis的主从架构有了两种模式:一类是一主多从, 另一类类是“链式主从复制” 主->从->从。

二、全量复制

Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。具体步骤如下(Redis2.8+):

1)从服务器连接主服务器MASTER,发送PSYNC? -1命令;
2 ) 主服务器MASTER判断出从服务第一次连接,属于全量复制,发送runid 和偏移量;
3 ) 从服务器SLAVE保存收到的runid 和偏移量信息 ;
4)主服务器MASTER始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令;
5、6)主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
7、8)从服务器SLAVE收到快照文件后丢弃所有旧数据,载入收到的快照;
9)主服务器MASTER快照发送完毕后开始向从服务器发送缓冲区中的写命令;
10)从服务器SLAVE完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;

三、部分复制

在Redis 2.8 之前的版本,一旦主从之间断开,就会进行全量同步,和上面的步骤类似,只是没有传输runid 和偏移量。这样的情况下主服务器执行BGSAVE命令会陷入卡顿的情况,影响业务使用。因此官方推出了PSYNC,PSYNC可以使主从临时断开重连的情况下,进行部分复制,节省资源,步骤如下

1 )当网络发生抖动以后,从服务器SLAVE和主服务器MASTER断开连接
2 )主服务器MASTER正常写命令时,会写将命令同时存放在缓冲区
3、4 )当从服务器SLAVE再次连接主服务器MASTER时 ,会传递命令 PSYNC {offset} {runid} ,告诉主服务器MASTER自己当前的偏移量是多少
5、6 )主服务器MASTER会向从服务器SLAVE返回CONTINUE ,并且把缺失的内容传递过去。

runid和offset怎么查看看?

# redis-cli -p 6379 info server | grep run
run_id:cfd88f83b3ba7cde1f51fc5c1bb68ce13c6726cc
# redis-cli -p 6379 info replication |grep offset
slave_repl_offset:8318743

缓冲区太小怎么办?

这里就会存在一个问题,缓存区如果太小,而从服务器SLAVE与主服务器MASTER中断时间太长,跟不上缓冲区了怎么办?

当然是执行全量复制了,要不然呢。

可是全量复制是很耗费资源的,会对线上业务有影响的,因此缓冲区要设置一个合理的值。

四、主从复制相关参数调优

4.1 client-output-buffer-limit

output buffer是Redis为client分配的缓冲区(这里的”client”可能是真正的client,也可能是slave或monitor),若为某个客户端分配的output buffer超过了预留大小,Redis可能会根据配置策略关闭与该端的连接。

client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>

class : 客户端种类,normal(普通的客户端)、slave(从库的复制客户端和MONITOR)、pubsub(发布与订阅的客户端)。
:若output buffer大小超过该值,Redis会立即关闭与对应client的连接
:若output buffer大小超过soft limit且这种情况的持续时间超过soft seconds,则Redis会关闭与对应client的连接。
默认的配置如下:
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60

其实对于主从复制来说,SLAVE种类的client-output-buffer存放的数据是下面三个时间内所有的master数据更新操作。

1)master执行rdb bgsave产生snapshot的时间
2)master发送rdb到slave网络传输时间
3)slave load rdb文件把数据恢复到内存的时间

因此业务比较繁忙(QPS高)的情况需要考虑调大该值。

4.2 repl-backlog-size和repl-backlog-ttl

repl-backlog-size默认值 1M , repl-backlog-ttl默认值3600秒
复制缓冲区大小,这是一个环形复制缓冲区,用来保存最新复制的命令。这样在slave离线的时候,不需要完全复制master的数据,如果可以执行部分同步,只需要把缓冲区的部分数据复制给slave,就能恢复正常复制状态。缓冲区的大小越大,slave离线的时间可以更长,复制缓冲区只有在有slave连接的时候才分配内存。没有slave的一段时间,内存会被释放出来。

业务比较繁忙(QPS高)的redis,可以适当调大此值。

4.3 repl-timeout

默认值60秒

三种情况认为复制超时:
1)slave角度,如果在repl-timeout时间内没有收到master SYNC传输的rdb snapshot数据,
2)slave角度,在repl-timeout没有收到master发送的数据包或者ping。
3)master角度,在repl-timeout时间没有收到REPCONF ACK确认信息。

对于内存数据量比较大的系统,可以增大repl-timeout参数。

4.4 repl-ping-slave-period

默认值10秒

redis slave会定期从master发送ping命令,时间间隔repl-ping-slave-period指定。
因而,设置参数时,repl-timeout > repl-ping-slave-period。

五、Redis4.0对PSYNC的优化

在 2.8 版本之前 redis 没有增量同步的功能,主从只要重连就必须全量同步数据。如果实例数据量比较大的情况下,网络轻轻一抖就会把主从的网卡跑满从而影响正常服务。2.8 为了解决这个问题引入了 PSYNC (partial sync)功能,顾名思义就是增量同步。

从库尝试发送 PSYNC 命令到主库,而不是直接使用 SYNC命令进行全量同步
主库判断是否满足 PSYNC 条件, 满足就返回 +CONTINUE 进行增量同步, 否则返回 +FULLRESYNC runid offfset进行全量同步。

redis 判断是否允许 psync 有两个条件:

条件一: psync 命令携带的 runid 需要和主库的 runid 一致才可以进行增量同步,否则需要全量同步。
条件二: psync 命令携带的 offset 是否超过缓冲区(repl-backlog-size,默认1M)。如果超过则需要全量同步,否则就进行增量同步。

虽然 2.8 引入的 psync 可以解决短时间主从同步断掉重连问题,但以下几个场景仍然是需要全量同步:

主从断开时间过长,超出了缓冲区覆盖范围(这个可以通过修改参数规避)
主库/从库有重启过。因为 runnid 重启后就会丢失,所以当前机制无法做增量同步。
从库提升为主库。其他从库切到新主库全部要全量不同数据,因为新主库的 runnid 跟老的主库是不一样的。

为了解决主从角色切换导致的重新全量同步,redis 4.0 引入多另外一个变量 replid2 来存放同步过的主库的 replid,同时 replid 在不同角色意义也有写变化。

主库判断条件相比之前版本多了一个 replid2 的判断。如果之前这两个曾经属于同一个主库(多级也允许), 那么新主库的 replid2 就是之前主库的 replid。只要之前是同一主库且新主库的同步进度比这个从库还快就允许增量同步。当然前提也是新主从的写入落后不能超过 backlog 大小。

举个栗子,假设 A <- B <- C 这种部署结构来说, A 是 B 的主库,B 是 C 的主库。如果把 C 提成新的主库,C <- A 以及 C <- B 都可以增量同步,因为切换后 C 的 replid2 其实就是 A。

在另外一方面,在做 rdb 备份的时候 replid 和 offset 会被持久化到 rdb 文件,也就是说甚至是服务重启了也可以进行增量同步,具体见 rdbSaveInfoAuxFields 函数实现。

六、参考资料

https://www.kancloud.cn/mayan0718/php/515287
http://www.hulkdev.com/posts/redis_new_psync
http://mdba.cn/2015/03/18/redis%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6%EF%BC%883%EF%BC%89-%E5%A4%8D%E5%88%B6%E8%B6%85%E6%97%B6/
http://weizijun.cn/2015/12/11/redis%E9%85%8D%E7%BD%AE%E8%AF%A6%E8%A7%A3/
https://www.cnblogs.com/wdliu/p/9407179.html

转载请注明:IPCPU-网络之路 » Redis的主从同步原理和参数调优