redis Replication 概述
和MySQL主从复制的原因一样,Redis虽然读取写入的速度都特别快,但是也会产生读压力特别大的情况。为了分担读压力,Redis支持主从复制,Redis的主从结构可以采用一主多从或者级联结构,下图为级联结构
其重要特性:
- 一个master可以拥有多个slave
- 一个slave也可以接受其它slave
- 复制过程master不会因此阻塞
- Slave如果发生断连,重启后自动重连
一、主从复制解决的问题
- 读写分离
- 避免单点
二、术语描述
积压空间
积压空间中,记录变更的记录。积压空间中的数据变更记录是什么时间点
在执行一个 redis 命令的时候,如果存在数据的修改(写),那么就会把变更记录传播。redis 源码中是这么实现的:call()->propagate()->replicationFeedSlaves()为什么把数据添加入积压空间,又把数据分发给所有的从机?为什么不仅仅将数据分发给所有从机呢?
因为有一些从机会因特殊情况(???)与主机断开连接,注意从机断开前有暂存主机的状态信息,因此这些断开的从机就没有及时收到更新的数据。redis 为了让断开的从机在下次连接后能够获取更新数据,将更新数据加入了积压空间。从 replicationFeedSlaves() 实现来看,在线的 slave 能马上收到数据更新记录;因某些原因暂时断开连接的 slave,需要从积压空间中找回断开期间的数据更新记录。如果断开的时间足够长,master 会拒绝 slave 的部分同步请求,从而 slave 只能进行全同步
三、主从复制原理
Redis主从同步策略
主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。全量过程
- Slave首先向master发生sync命令
- Master收到sync命令后,通过正常的持久化流程产生一个rdb文件,并将所有更新命令保证至特定的内存缓冲区
- Rdb创建完成后,master将此文件发送给slave
- Slave加载master的rdb文件后,master发送缓冲区保存的写命令
增量过程
- 从机连接主机后,会主动发起 PSYNC 命令,从机会提供 master_runid 和 offset,
- 主机验证 master_runid 和 offset 是否有效?
- 验证通过则,进行增量同步:主机返回 +CONTINUE(从机接收后会注册积压数据接收事件),接着发送积压空间数据。否则执行sync流程(全量同步)
四、主从复制操作步骤
设置原则:从配主不配
==主从的配置有2种方法==
- 在redis.conf中设置 slaveof
- 使用redis-cli客户端连接到Redis服务中,执行slaveof命令,这种方式在重启之后就会失去主从复制关系
五、查看主从复制相关命令
- info replication
- slaveof ip 端口
六、缺点
- 当主机出现故障时,slave 不会自动切换为master
==解决方法请参考 redis 哨兵模式== - 主从同步是通过RDB来同步数据, 即使禁用了RDB也没有用,也会产生IO问题,在这个复制过程可能就会出现瓶颈
==解决办法 将Redis 升级到2.8.18版本或者更高版本(Redis在2.8.18版本开始实现了无磁盘复制功能)==
# redis.conf
# repl-diskless-sync 默认是 no
repl-diskless-sync yes
七、当主服务器不进行持久化时复制的安全性
在进行主从复制设置时,强烈建议在主服务器上开启持久化,当不能这么做时,比如考虑到延迟的问题,应该将实例配置为避免自动重启。
==为什么不持久化的主服务器自动重启非常危险呢?==
为了更好的理解这个问题,看下面这个失败的例子,其中主服务器和从服务器中数据库都被删除了。
设置节点A为主服务器,关闭持久化,节点B和C从节点A复制数据。
这时出现了一个崩溃,但Redis具有自动重启系统,重启了进程,因为关闭了持久化,节点重启后只有一个空的数据集。
节点B和C从节点A进行复制,现在节点A是空的,所以节点B和C上的复制数据也会被删除。当在高可用系统中使用Redis Sentinel,关闭了主服务器的持久化,并且允许自动重启,这种情况是很危险的。
比如主服务器可能在很短的时间就完成了重启,以至于Sentinel都无法检测到这次失败,那么上面说的这种失败的情况就发生了。