redis主从复制
redis的高并发有一种实现方式就是主从架构,一个master节点,多个slave节点,可以很好的实现slave节点的水平扩容;主从架构再加上读写分离,master节点负责写操作,slave节点负责读操作,使得redis可以很好的做一个高并发的处理。有人就会疑惑了:slave节点上的数据怎么来的了?所以我们就来说一说redis主从复制的相关原理。
当我们启动一个slave节点的时候,它就会去ping下master节点,发送PSYNC命令,当两者建立连接以后,master节点发现slave节点是第一次连接我,就会触发一次full resynchronization,master启动一个后台线程,生成一份RDB快照,那生成快照期间新的命令怎么办,master会把这些命令缓存到内存中;而RDB文件生成以后,master会把这个文件发送给slave,slave节点会把这个文件先写入磁盘,然后再从磁盘读取到内存中;当这些操作执行完以后,master会将内存中缓存的命令发送给slave节点,slave节点再同步这些数据。如果slave节点不是第一次连接master节点了?那master节点仅仅只会复制缺少的那部分数据。
那如果主从复制的过程中,网断掉了怎么办?岂不是又要头进行复制。这里就要提到从redis2.8开始的主从复制的断点续传,master node中有一个backlog,master和slave都保存了一个replica offset和master id,offset保存早backlog中,如果网络连接断了,从新连接后,就会找到这个offset,从这个offset的位置继续进行复制,当然,如果没有找到这个offset,那么就会进行一次full resynchronization
前面提到的master生成RDB文件是有落地master磁盘这么一个操作的,那么还有一种就是无磁盘化复制,不会在落地master节点的磁盘,直接在内存中生成RDB文件,然后发送给slave节点。
还需要提一下的就是,如果master节点中的key过期或者被淘汰了怎么办?这个时候,master节点会发送一条del命令给slave节点,slave节点执行这条del命令来删除这个过期的key
前面说的都是复制的大致流程及相关概念。那么还有一些疑问?slave节点怎么去找的master节点:slave节点的redis.conf文件中会存储master的host和ip;而且slave节点内部会有一个定时任务,它定期的查看是否有新的master节点需要连接和复制,如果有,就和这个新节点建立socket连接;还有一点就是如果master节点设置了requirepass那么salve node必须发送masterauth的口令过去进行认证,建立连接后,就可以执行我们前面说的复制操作。
其实复制的过程中有一些细节:
前面说到master和slave节点都有维护一个offset,而slave每秒都会上报自己的offset给master,同时master也会保存每个slave的offset,master和slave都要知道各自的数据的offset,才能知道互相之间的数据不一致的情况
master node有一个backlog,默认是1MB大小,master node给slave node复制数据时,也会将数据在backlog中同步写一份,backlog主要是用来做全量复制中断候的增量复制的
master run id也就是前面说的master id,如果根据host+ip定位master node,是不靠谱的,如果master node重启或者数据出现了变化,那么slave node应该根据不同的run id区分,run id不同就做全量复制,如果需要不更改run id重启redis,可以使用redis-cli debug reload命令
还有psync,从节点使用psync从master node进行复制,psync runid offset,master node会根据自身的情况返回响应信息,可能是FULLRESYNC runid offset触发全量复制,可能是CONTINUE触发增量复制
全量复制
(1)master执行bgsave,在本地生成一份rdb快照文件
(2)master node将rdb快照文件发送给salve node,如果rdb复制时间超过60秒(repl-timeout),那么slave node就会认为复制失败,可以适当调节大这个参数
(3)对于千兆网卡的机器,一般每秒传输100MB,6G文件,很可能超过60s
(4)master node在生成rdb时,会将所有新的写命令缓存在内存中,在salve node保存了rdb之后,再将新的写命令复制给salve node
(5)client-output-buffer-limit slave 256MB 64MB 60,如果在复制期间,内存缓冲区持续消耗超过64MB,或者一次性超过256MB,那么停止复制,复制失败
(6)slave node接收到rdb之后,清空自己的旧数据,然后重新加载rdb到自己的内存中,同时基于旧的数据版本对外提供服务
(7)如果slave node开启了AOF,那么会立即执行BGREWRITEAOF,重写AOF
rdb生成、rdb通过网络拷贝、slave旧数据的清理、slave aof rewrite,很耗费时间
如果复制的数据量在4G~6G之间,那么很可能全量复制时间消耗到1分半到2分钟
增量复制
(1)如果全量复制过程中,master-slave网络连接断掉,那么salve重新连接master时,会触发增量复制
(2)master直接从自己的backlog中获取部分丢失的数据,发送给slave node,默认backlog就是1MB
(3)msater就是根据slave发送的psync中的offset来从backlog中获取数据的
heartbeat
主从节点互相都会发送heartbeat信息
master默认每隔10秒发送一次heartbeat,salve node每隔1秒发送一个heartbeat
异步复制
master每次接收到写命令之后,现在内部写入数据,然后异步发送给slave node