Redis学记笔记 —— (13)复制
在分布式系统中,为了解决单点问题,通常会把数据复制多个副本部署到其他机器上,满足故障恢复和负载均衡等需求。Redis当中也提供了复制功能,可以实现相同数据的Redis副本。
1. 配置复制
1.1 建立复制
参与复制的Redis实例分为主节点master和从节点slave,默认情况下,Redis都是主节点,每个从节点只有一个主节点,而主节点可以同事具有多个从节点,复制的数据流是单向的,只能由主节点复制到从节点。
复制方式有三种:
- 在配置文件中加入 slaveof(masterHost) {masterPort} ,随Redis启动生效
- 在redis-server启动命令后加入 --slaveof(masterHost) {masterPort} 生效
- 世界使用命令:slaveof(masterHost) {masterPort} 。
1.2 断开复制
slaveof命令不但可以建立复制,还可以在从节点执行slaveof no one 来断开和主节点复制关系。
如果 127.0.0.1:6380节点复制的是127.0.0.1:6379,再6380端口对应的节点上执行slaveof no one 就可以断开复制。
1.2.1断开复制的主要流程
- 断开与主节点复制关系
- 从节点晋升为主节点
从阶段断开复制后并不会抛弃原有数据,只是无法再获取主节点上的数据变化。
通过slaveof命令还可以实现切主操作,所谓切主是指把当前节点对主节点的复制切换到另一个节点上。执行slaveof {newMasterIp} {newMasterPort} 命令即可。
1.2.2切主操作流程
- 断开与主节点复制关系
- 与新节点建立复制关系
- 删除从节点当前所有数据
- 对主节点进行复制操作
2. 复制的拓扑结构
Redis的复制拓扑结构可以支持单层或多层复制关系,可以分为三种:一主一从,一主多从,树状主从结构。
2.1 一主一从结构
当应用写命令并发量较高且需要持久化时, 可以只在从节点上开启AOF, 这样既保证数据安全性同时也避免了持久化对主节点的性能干扰。但需要注意的是, 当主节点关闭持久化功能时,如果主节点脱机要避免自动重启操作。 因为主节点之前没有开启持久化功能自动重启后数据集为空, 这时从节点如果继续复制主节点会导致从节点数据也被清空的情况, 丧失了持久化的意义。 安全的做法是在从节点上执行slaveof no one断开与主节点的复制关系, 再重启主节点从而避免这一问题。
2.2 一主多从结构
一主多从结构使得应用端可以利用多个从节点实现读写分离,对于读占比较大的场景,可以把读命令发送到从节点来分担主节点压力,同时再日常开发中如果需要执行一些比较耗时的读命令,例如Keys、sort等,可以在其中的一个节点上执行,防止慢查询对主节点造成阻塞而影响线上服务的稳定性,对于写并法量较高的场景,多个从节点会导致主节点写明了的多次发送从而过度消耗网络带宽,同时也加重了主节点的负载影响服务稳定性。
2.3树状主从结构
树状主从结构(又称为树状拓扑结构) 使得从节点不但可以复制主节点数据, 同时可以作为其他从节点的主节点继续向下层复制。 通过引入复制中间层, 可以有效降低主节点负载和需要传送给从节点的数据量。数据实现了一层一层的向下复制。 当主节点需要挂载多个从节点时为了避免对主节点的性能干扰, 可以采用树状主从结构降低主节点压力。
3.开发与运维
##### 3.1 读写分离
在读占比比较高的场景,可以通过把一部分读流量分摊到从节点来减轻主节点的压力,同时需要注意永远只对主节点执行写操作。
当使用从节点响应读请求时,业务端可能会遇到如下问题:
3.1.1 复制数据延迟
Redis复制数据的延迟由于是异步特性,因此无法避免,延迟取决于网路带宽和命令阻塞情况,比如杠在主节点写入数据后立刻在从节点上读取可能获取不到。
需要业务场景允许短时间内的数据延迟,由于无法容忍大量延迟场景,可以编写外部监控程序监听主节点的复制偏移量,当延迟较大时触发报警或者通知客户端避免读取延迟过高的从节点。
分为三步:
- 监控程序定期检查主从节点的偏移量
- 延迟字节过高时,监控程序触发报警并通知客户端从节点延迟过高,可以采用Zookeeper的监听回调机制实现客户端通知
- 客户端接到延迟通知后,修改读命令路由到其他从节点或者主节点上,当延迟恢复正常后再切换该结点的读操作。
3.1.2 读到过期数据
当主节点存储到大量设置超时的数据时,Redis内部需要维护过期数据删除策略,删除策略主要又两种,分为惰性删除和定时删除。
- 惰性删除
主节点每次处理读取命令时,都会检查键是否超时,如果超时则执行del命令,之后的del命令也会异步发给从节点,需要注意的时,为了保证复制的一致性,总结点自身永远不会主动删除超时数据。
- 定时删除
Redis主节点再内部定时任务会循环采样一定数量的键,当发现采样的键过期时,执行del命令,再同步给从节点。
3.1.3 从节点故障
对于从节点故障问题,需要再客户端维护可用从节点列表,当从节点故障时立刻切换到其他从节点或主节点上。
3.2 规避全局复制
全局复制是一个非常消耗资源的操作,如果避免全局复制十分重要
- 第一次建立复制
由于是第一次建立复制,从节点不包含任何主节点数据,因此必须进行全局复制才能完成数据同步,对于这种情况全量复制无法避免,当数据量较大且流量较高的主节点添加从节点时,建议再低峰时操作,或者尽量避免使用大数据量的Redis节点。
- 节点运行ID不匹配
当主从复制关系建立后,从节点会保存主节点的运行ID,如果此时主节点因故障重启,那么它的运行ID会改变,从节点发现主节点运行ID不匹配时,会认为自己复制的是一个新的主节点从而进行全量复制,对于这种情况应该从架构上避免,例如提供故障转移功能,当主节点发生故障后,手动提升从节点为主节点,或者采用支持自动故障转移的哨兵或集群方案。
3.3 规避复制风暴
复制风暴是指大量从节点对同一主节点或者对同一台机器的多个从节点短时间内发起全量复制的过程,复制风暴对发起复制的主节点或者机器造成大量开销,导致CPU、内存、带宽消耗。
可以通过 减少主节点挂载从节点的数量,或采用树状复制结构,加入中间层从节点用来保护主节点。
可以通过 尽量把主节点分散再多台机器上,避免再单台机器上部署过多的主节点,当主节点所在机器故障后提供故障转移机制,避免机器恢复后进行密集的全局复制。