Redis.7.5 集群读写分离
1.只读连接
集群模式下从节点不接受任何读写请求,发送过来的键命令会重定向到负责槽的主节点上(其中包括它的主节点)。当需要使用从节点分担主节点读压力时,可以使用readonly 命令打开客户端连接只读状态。之前的复制配置 slave-read-only 在集群模式
下无效。当开启只读状态时,从节点接收读命令处理流程变为:如果对应的槽属于自己正在复制的主节点则直接执行读命令,否则返回重定向信息。命令如下:
代码语言:javascript复制1. // 默认连接状态为普通客户端:flags=N
127.0.0.1:6382> client list
3. id=3 addr=127.0.0.1:56499 fd=6 name= age=130 idle=0 flags=N db=0 sub=0 psub=
0 multi=-1
4. qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client
5. // 命令重定向到主节点
6. 127.0.0.1:6382> get key:test:3130
7. (error) MOVED 12944 127.0.0.1:6379
8. // 打开当前连接只读状态
9. 127.0.0.1:6382> readonly
10. OK
11. // 客户端状态变为只读:flags=r
12. 127.0.0.1:6382> client list
13. id=3 addr=127.0.0.1:56499 fd=6 name= age=154 idle=0 flags=r db=0 sub=0 psub=
0 multi=-1
14. qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client
15. // 从节点响应读命令
16. 127.0.0.1:6382> get key:test:3130
17. "value:3130"
readonly 命令是连接级别生效,因此每次新建连接时都需要执行 readonly 开启只读状态。执行 readwrite 命令可以关闭连接只读状态。
2.读写分离
集群模式下的读写分离,同样会遇到:复制延迟,读取过期数据,从节点故障等问题,具体细节见 6.5 复制运维小节。针对从节点故障问题,客户端需要维护可用节点列表,集群提供了 cluster slaves{nodeId}命令,返回 nodeId 对应主节点下所有从节点信息,数据格式同 cluster nodes,命令如下:
代码语言:javascript复制// 返回 6379 节点下所有从节点
127.0.0.1:6382> cluster slaves cfb28ef1deee4e0fa78da86abe5d24566744411e
1) "40622f9e7adc8ebd77fca0de9edfe691cb8a74fb 127.0.0.1:6382 myself,slave cfb28e
f1deee4e0fa78da86abe5d24566744411e 0 0 3 connected"
2) "2e7cf7539d076a1217a408bb897727e5349bcfcf 127.0.0.1:6384 slave,fail cfb28ef1
deee4e0fa78da86abe5d24566744411e 1473047627396 1473047622557 13
disconnected"
解析以上从节点列表信息,排除 fail 状态节点,这样客户端对从节点的故障判定可以委托给集群处理,简化维护可用从节点列表难度。
开发提示集群模式下读写分离涉及对客户端修改如下:
维护每个主节点可用从节点列表。
2)针对读命令维护请求节点路由。
3)从节点新建连接开启 readonly 状态。
集群模式下读写分离成本比较高,可以直接扩展主节点数量提高集群性能,一般不建议集群模式下做读写分离。
集群读写分离有时用于特殊业务场景如:
1)利用复制的最终一致性使用多个从节点做跨机房部署降低读命令网络延迟。
2)主节点故障转移时间过长,业务端把读请求路由给从节点保证读操作可用。
以上场景也可以在不同机房独立部署 Redis 集群解决,通过客户端多写来维护,读命令直接请求到最近机房的 Redis 集群,或者当一个集群节点故障时客户端转向另一个集群。
10.7.6 手动故障转移
Redis 集群提供了手动故障转移功能:指定从节点发起转移流程,主从节点角色进行切换,从节点变为新的主节点对外提供服务,旧的主节点变为它的从节点,如图。
在从节点上执行 cluster failover 命令发起转移流程,默认情况下转移期间客户端请求会有短暂的阻塞,但不会丢失数据,流程如下:
1)从节点通知主节点停止处理所有客户端请求。
2)主节点发送对应从节点延迟复制的数据。
3)从节点接收处理复制延迟的数据,直到主从复制偏移量一致为止,保证复制数据不丢失。
4)从节点立刻发起投票选举(这里不需要延迟触发选举)。选举成功后断开复制变为新的主节点,之后向集群广播主节点 pong 消息,故障转移细节见 10.6 故障恢复部分。
5)旧主节点接受到消息后更新自身配置变为从节点,解除所有客户端请求阻塞,这些请求会被重定向到新主节点上执行。
6)旧主节点变为从节点后,向新的主节点发起全量复制流程。
运维提示主从节点转移后,新的从节点由于之前没有缓存主节点信息无法使用部分复制功能,所以会发起全量复制,当节点包含大量数据时会严重消耗 CPU 和网络资源,线上不要频繁操作。
手动故障转移的应用场景主要如下:
1)主节点迁移:运维 Redis 集群过程中经常遇到调整节点部署的问题,如节点所在的老机器替换到新机器等。由于从节点默认不响应请求可以安全下线关闭,但直接下线主节点会导致故障自动转移期间主节点无法对外提供服务,影响线上业务的稳定性。这时可以使用手动故障转移,把要下线的主节点安全的替换为从节点后,再做下线操作操作,如图所示。
2)强制故障转移。当自动故障转移失败时,只要故障的主节点有存活的从节点就可以通过手动转移故障强制让从节点替换故障的主节点,保证集群的可用性。自动故障转移失败的场景有:
·主节点和它的所有从节点同时故障。这个问题需要通过调整节点机器部署拓
扑做规避,保证主从节点不在同一机器/机架上。除非机房内大面积故障,否则两台机器/机架同时故障概率很低。
·所有从节点与主节点复制断线时间超过 cluster-slave-validity-factor*clusternode-tineout repl-ping-slave-period,导致从节点被判定为没有故障转移资格,手动故障转移从节点不做中断超时检查。
·由于网络不稳定等问题,故障发现或故障选举时间无法在 cluster-node-timeout*2 内完成,流程会不断重试,最终从节点复制中断时间超时,失去故障转移资格无法完成转移。
·集群内超过一半以上的主节点同时故障。
根据以上情况,cluster failover 命令提供了两个参数 force/takeover 提供支持:
·cluster failover force——用于当主节点宕机且无法自动完成故障转移情况。
·cluster failover takeover——用于集群内超过一半以上主节点故障的场景,因为从节
点无法收到半数以上主节点投票,所以无法完成选举过程。可以执行 cluster failover takeover 强制转移,接到命令的从节点不再进行选举流程而是直接更新本地配置纪元并替换主节点。
手动故障转移时,在满足当前需求的情况下建议优先级:cluster failver>cluster failover
force>cluster failover takeover。