redis 主从复制
主从复制原理
- 副本库通过slaveof 主从IP 6379命令,连接主库,并发送SYNC给主库
- 主库收到SYNC,会立即触发BGSAVE,后台保存RDB,发送给副本库,副本库接收后会立即应用RDB快照
- 主库会陆续将中间产生的新的操作,保存并发送给副本库
- 复制集就ok了,只要主库发生新的操作,都会以命令的形式自动发送给副本库
- 所有复制的相关信息,都可以通过info信息查到,即使重启他们的主从关系依然都存在
- 如果发生主从关系断开时,从库数据没有任何损坏,下次重连后从库发送PSYNC给主库
- 主库只会将从库缺失部分的数据同步给从库应用,达到快速回复主从的目的
部分同步的原理
- 服务器端为复制流维护一个内存缓冲区(in-memory backlog)。
- 主从服务器都维护一个复制偏移量(replication offset)和master run id,
- 当连接断开时,从服务器会重新连接上主服务器,然后请求继续复制,
- 假如主从服务器的两个master run id相同,并且指定的偏移量在内存缓冲区中还有效,复制就会从上次中断的点开始继续。
- 如果其中一个条件不满足,就会进行完全重新同步(在2.8版本之前就是直接进行完全重新同步)。
- 因为主运行id不保存在磁盘中,如果从服务器重启了的话就只能进行完全同步了。
主从复制功能的详细步骤
设置主节点的地址和端口
建立套接字连接
发送PING命令
权限验证
同步
命令传播
实验步骤:
下载redis
环境:
主机名 | IP地址 | 软件 |
---|---|---|
redis-01(master) | 192.168.42.1 | redis-5.0.7.tar.gz |
redis-02 (slave) | 192.168.42.2 | redis-5.0.7.tar.gz |
redis-03 (slave) | 192.168.42.3 | redis-5.0.7.tar.gz |
1.设置redis登录密码(123)
redis-01
cat >> /opt/redis_cluster/redis/redis.conf << EOF
requirepass 123
masterauth 123
EOF
redis-02
cat >> /opt/redis_cluster/redis/redis.conf << EOF
requirepass 123
masterauth 123
EOF
redis-03
cat >> /opt/redis_cluster/redis/redis.conf << EOF
requirepass 123
masterauth 123
EOF
2.设置主服务器的地址和端口
首先是在从服务器设置需要同步的主服务器信息,包括机器IP, 端口。
(1). 从节点开启主从复制
redis-02
a. 配置文件加入
echo "slaveof 192.168.42.1 6379" >> /opt/redis_cluster/redis/redis.conf
b. 启动命令
redis-server /opt/redis_cluster/redis/redis.conf ----slaveof 192.168.42.1 6379
c. 客户端命令
redis-cli -p 6379 -a 123 SLAVEOF 192.168.42.1 6379
redis-03
a. 配置文件加入
echo "slaveof 192.168.42.1 6379" >> /opt/redis_cluster/redis/redis.conf
b. 启动命令
redis-server /opt/redis_cluster/redis/redis.conf ----slaveof 192.168.42.1 6379
c. 客户端命令
redis-cli -p 6379 -a 123 SLAVEOF 192.168.42.1 6379
使用info Replication命令查看从服务器和主服务器的主从信息
3. 建立套接字连接
执行slaveof命令之后,从服务器根据设置的IP和端口,向主服务器发一个socket连接
执行info Replication命令,可以查看服务器的角色究竟是从还是主
4.发送ping命令
节点成为从节点以后,会发送ping进行首次请求
目的: 检查socket连接是否可用,以及主节点当前是否能够处理请求。
可能会出现三种情况
(1)返回pong:说明socket连接正常,且主节点当前可以处理请求,复制过程继续。
(2)超时:一定时间后从节点仍未收到主节点的回复,说明socket连接不可用,则从节点断开socket连接,并重连。
(3)返回pong以外的结果:如果主节点返回其他结果,如正在处理超时运行的脚本,说明主节点当前无法处理命令,则从节点断开socket连接,并重连。
5.同步
同步就是将从节点的数据库状态更新成主节点当前的数据库状态。执行过程:从节点向主节点发送psync命令,开始同步。
数据同步阶段是主从复制最核心的阶段,根据主从节点当前状态的不同,可以分为
全量复制
和部分复制
6.命令传播
此时主从的数据库状态其实已经一致了,但这种一致的状态的并不是一成不变的。
在完成同步之后,也许主服务器马上就接受到了新的写命令,执行完该命令后,主从的数据库状态又不一致。
数据同步阶段完成后,主从节点进入命令传播阶段;在这个阶段主节点将自己执行的写命令发送给从节点,从节点接收命令并执行,从而保证主从节点数据的一致性。
延迟与不一致
和心跳机制
延迟与不一致
需要注意的是,命令传播是异步的过程,即主节点发送写命令后并不会等待从节点的回复;因此实际上主从节点之间很难保持实时的一致性,延迟在所难免。数据不一致的程度,与主从节点之间的网络状况、主节点写命令的执行频率、以及主节点中的
repl-disable-tcp-nodelay
配置等有关。
repl-disable-tcp-nodelay
配置如下:
- 假如设置成yes,则redis会合并小的TCP包从而节省带宽,但会增加同步延迟(40ms),造成master与slave数据不一致
- 假如设置成no,则redis master会立即发送同步数据,没有延迟
全量复制
master服务器会开启一个后台进程用于将redis中的数据生成一个rdb文件,与此同时,服务器会缓存所有接收到的来自客户端的写命令(包含增、删、改),当后台保存进程处理完毕后,会将该rdb文件传递给slave服务器,而slave服务器会将rdb文件保存在磁盘并通过读取该文件将数据加载到内存,在此之后master服务器会将在此期间缓存的命令通过redis传输协议发送给slave服务器,然后slave服务器将这些命令依次作用于自己本地的数据集上最终达到数据的一致性。
部分复制
从redis 2.8版本以前,并不支持部分同步,当主从服务器之间的连接断掉之后,master服务器和slave服务器之间都是进行全量数据同步,
从redis 2.8开始,即使主从连接中途断掉,也不需要进行全量同步,因为从这个版本开始融入了部分同步的概念。
部分同步的实现依赖于在master服务器内存中给每个slave服务器维护了一份同步日志和同步标识,
每个slave服务器在跟master服务器进行同步时都会携带自己的同步标识和上次同步的最后位置。
当主从连接断掉之后,slave服务器隔断时间(默认1s)主动尝试和master服务器进行连接,
如果从服务器携带的偏移量标识还在master服务器上的同步备份日志中,那么就从slave发送的偏移量开始继续上次的同步操作,
如果slave发送的偏移量已经不再master的同步备份日志中(可能由于主从之间断掉的时间比较长或者在断掉的短暂时间内master服务器接收到大量的写操作),则必须进行一次全量更新。
在部分同步过程中,master会将本地记录的同步备份日志中记录的指令依次发送给slave服务器从而达到数据一致。