Redis 集群
概述
Redis Cluster是Redis的分布式解决方案,在3.0版本正式推出,有效地解决了Redis分布式方面的需求。当遇到单机内存、并发、流量等瓶颈时,可以采用Cluster架构方案达到负载均衡的目的,集群内Gossip消息通信本身会消耗带宽,官方建议集群最大规模在1000以内。
集群搭建
环境准备
|
角色 |
IP |
Port |
备注 |
|
Master |
127.0.0.1 |
6379 |
搭建版本5.0.9 |
|
Master |
127.0.0.1 |
6380 |
|
|
Master |
127.0.0.1 |
6381 |
|
|
Slave |
127.0.0.1 |
6382 |
|
|
Slave |
127.0.0.1 |
6383 |
|
|
Slave |
127.0.0.1 |
6384 |
|
配置文件:
|
#节点端口 port 6379 # 开启集群模式 cluster-enabled yes # 节点超时时间,单位毫秒 cluster-node-timeout 15000 # 集群内部配置文件 cluster-config-file "nodes-6379.conf" cluster-require-full-coverage no |
配置说明:
|
参数名 |
含义 |
默认值 |
可选值 |
可否支持config set配置热生效 |
|
cluster-node-timeout |
集群节点超时时间(单位毫秒) |
15000 |
整数 |
可以 |
|
cluster-migration-barrier |
主从节点切换需要的从节点数最小个数 |
1 |
整数 |
可以 |
|
cluster-replica-validity-factor |
从节点有效性判断因子,当从节点与主节点最后通信时间超过(cluster-node-timeout* cluster-replica-validity-factor)+ repl-ping-replica-period时,对应从节点不具备故障转移资格,防止断线时间过长的从节点进行故障转移。设置为0表示从节点永不过期 |
10 |
整数 |
可以 |
|
cluster-require-full-coverage |
集群是否需要所有的slot都分配给在线节点,才能正常访问 |
yes |
yes|no |
可以 |
|
cluster-enabled |
是否开启集群模式 |
yes |
yes|no |
不可以 |
|
cluster-config-file |
集群配置文件名称 |
nodes.conf |
nodes-{port}.conf |
不可以 |
启动:
|
nohup src/redis-server redis.conf-6379 & nohup src/redis-server redis.conf-6380 & nohup src/redis-server redis.conf-6381 & nohup src/redis-server redis.conf-6382 & nohup src/redis-server redis.conf-6383 & nohup src/redis-server redis.conf-6384 & |

使用redis-trib.rb搭建集群
redis-trib.rb未来将被废弃,原有功能已经迁移到redis-cli。
- 使用 create命令完成节点握手和槽分配过程,命令如下:
|
redis-cli --cluster create 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 --cluster-replicas 1 # cluster-replicas代表每个master节点slave节点数 |

2. 完整性检查
集群完整性指所有的槽都分配到存活的主节点上,只要16384个槽中有一个没有分配给节点则表示集群不完整,check命令只需要给出集群中任意一个节
点地址就可以完成整个集群的检查工作。命令如下:
|
redis-cli --cluster check 127.0.0.1:6379 |

至此集群已经搭建完成。
集群扩容
扩容是分布式存储最常见的需求,Redis集群扩容操作可分为如下步骤:
1)准备新节点。
2)加入集群。
3)迁移槽和数据。
准备新节点
新加入集群的节点需要保证库内无任何数据,否则会报错
|
[ERR] Node 127.0.0.1:6386 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0. |
|
角色 |
IP |
Port |
备注 |
|
Master |
127.0.0.1 |
6385 |
搭建版本5.0.9 |
|
Slave |
127.0.0.1 |
6386 |
|
配置同上
启动:
|
nohup src/redis-server redis.conf-6385 & nohup src/redis-server redis.conf-6386 & |

加入集群
Redis-cli提供add-node命令添加新节点,命令如下:
|
#6385作为master节点加入 redis-cli --cluster add-node 127.0.0.1:6385 127.0.0.1:6379 #6386作为6385的slave节点加入 redis-cli --cluster add-node 127.0.0.1:6386 127.0.0.1:6385 --cluster-slave |


迁移槽和数据
新加入的master节点并未分配槽,因此需要重新非配槽,命令如下:
|
redis-cli --cluster reshard 127.0.0.1:6379 --cluster-from all --cluster-to 725eac13dcc25d8cad83b8d0265bf88e582f5d21 --cluster-slots 4096 --cluster-yes |

参数解释:
|
--cluster-from:迁移出来的节点,all表示所有master节点 --cluster-slots:新的节点分配的槽数 --cluster-yes:分配计划生成后,省掉人工输入yes |
集群减容
流程说明:
1)首先需要确定下线节点是否有负责的槽,如果是,需要把槽迁移到其他节点,保证节点下线后整个集群槽节点映射的完整性。
2)当下线节点不再负责槽或者本身是从节点时,就可以通知集群内其他节点忘记下线节点,当所有的节点忘记该节点后可以正常关闭。
下面演示下线6385(master)、6386(slave)节点。
从节点下线
从节点下线对集群并无影响(忽略容灾的情况),所以可以直接下线,具体命令如下:
|
#下线6386节点 redis-cli --cluster del-node 127.0.0.1:6379 c844212d7aad8cdc96403f93e07751536176a3d3 |

Master节点下线
Master节点下线前必须确保下线节点无负责的槽,以保证节点下线后整个集群槽节点映射的完整性。
迁移槽和数据
收缩正好和扩容迁移方向相反,6385变为源节点,其他主节点变为目标节点,源节点需要把自身负责的4096个槽均匀地迁移到其他主节点上。这里直接使用redis-trib.rb reshard命令完成槽迁移。由于每次执行reshard命令只能有一个目标节点,因此需要执行3次reshard命令,分别迁移1365、1365、1366个槽,如下所示:
|
#迁移1365个槽到6379 redis-cli --cluster reshard 127.0.0.1:6379 --cluster-from 725eac13dcc25d8cad83b8d0265bf88e582f5d21 --cluster-to 7ac5ed81566418ae93e53a12fe5438c873377942 --cluster-slots 1365 --cluster-yes #迁移1365个槽到6380 redis-cli --cluster reshard 127.0.0.1:6379 --cluster-from 725eac13dcc25d8cad83b8d0265bf88e582f5d21 --cluster-to 2c09be973ad60452bbe9b551c9952e2133a94b1d --cluster-slots 1365 --cluster-yes #迁移1365个槽到6381 redis-cli --cluster reshard 127.0.0.1:6379 --cluster-from 725eac13dcc25d8cad83b8d0265bf88e582f5d21 --cluster-to bf1d3510747b671e7b9b0563140fc7d091adbe0d --cluster-slots 1366 --cluster-yes |

节点下线
确认master节点槽和数据都迁移完后,执行下线操作,命令同下线从节点:
|
redis-cli --cluster del-node 127.0.0.1:6379 725eac13dcc25d8cad83b8d0265bf88e582f5d21 |

原理分析
1.Redis数据分区
分布式数据库首先要解决把整个数据集按照分区规则映射到多个节点的问题,即把数据集划分到多个节点上,每个节点负责整体数据的一个子集。
常见的数据分区规则有哈希分区和顺序分区两种,两种分区规则对比如下:
|
分区方式 |
特点 |
代表产品 |
|
哈希分区 |
1、 离散度好 2、 数据分布业务无关 3、 无法顺序访问 |
Redis cluster Cassandra Dynamo |
|
顺序分区 |
1、 离散度易倾斜 2、 数据分布业务相关 3、 可顺序访问 |
Bigtable Hbase Hypertable |
Redis集群采用的是哈希分区规则,以下对比常见哈希分区的优缺点:
|
哈希分区规则 |
特点 |
适用场景 |
|
节点取余分区 |
1、分区公式hash(key)%N,key为redis的键或用户ID,N为节点数 2、当节点数量变化时,如扩容或收缩节点,数据节点映射关系需要重新计算,会导致数据的重新迁移 3、简单 |
常用于数据库的分库分表规则,一般采用预分区的方式,提前根据数据量规划好分区数,比如划分为512或1024张表,保证可支撑未来一段时间的数据量,再根据负载情况将表迁移到其他数据库中。扩容时通常采用翻倍扩容,避免数据映射全部被打乱导致全量迁移的情况 |
|
一致性哈希分区 |
1、实现思路是为系统中每个节点分配一个token,范围一般在0~232,这些token构成一个哈希环。数据读写 执行节点查找操作时,先根据key计算hash值,然后顺时针找到第一个大于等于该哈希值的token节点。 2、加入和删除节点只影响哈希环中相邻的节点,对其他节点无影响 3、加减节点会造成哈希环中部分数据无法命中,需要手动处理或者忽略这部分数据 4、当使用少量节点时,节点变化将大范围影响哈希环中数据映射 5、普通的一致性哈希分区在增减节点时需要增加一倍或减去一半节点才能保证数据和负载的均衡 |
|
|
虚拟槽分区 |
1、采用分散度良好的哈希函数把所有数据映射到一个固定范围的整数集合中,整数定义为槽(slot)。这个范围一般远远大于节点数 2、解耦数据和节点之间的关系,简化了节点扩容和收缩难度 3、节点自身维护槽的映射关系,不需要客户端或者代理服务维护槽分区元数据。 4、支持节点、槽、键之间的映射查询,用于数据路由、在线伸缩等场景 |
Redis cluster就是采用此分区方式 |
2.故障转移
2.1故障发现
当集群内某个节点出现问题时,需要通过一种健壮的方式保证识别出节点是否发生了故障。Redis集群内节点通过ping/pong消息实现节点通信,消息不但可以传播节点槽信息,还可以传播其他状态如:主从状态、节点故障等。因此故障发现也是通过消息传播机制实现的,主要环节包括:主观下线(pfail)和客观下线(fail)。
·主观下线:指某个节点认为另一个节点不可用,即下线状态,这个状态并不是最终的故障判定,只能代表一个节点的意见,可能存在误判情况。
·客观下线:指标记一个节点真正的下线,集群内多个节点都认为该节
点不可用,从而达成共识的结果。如果是持有槽的主节点故障,需要为该节点进行故障转移。
集群中每个节点都会定期向其他节点发送ping消息,接收节点回复pong消息作为响应。如果在cluster-node-timeout时间内通信一直失败,则发送节点会认为接收节点存在故障,把接收节点标记为主观下线(pfail)状态。具体流程如下:

流程说明:
1)节点a发送ping消息给节点b,如果通信正常将接收到pong消息,节点a更新最近一次与节点b的通信时间。
2)如果节点a与节点b通信出现问题则断开连接,下次会进行重连。如果一直通信失败,则节点a记录的与节点b最后通信时间将无法更新。
3)节点a内的定时任务检测到与节点b最后通信时间超高cluster-nodetimeout时,更新本地对节点b的状态为主观下线(pfail)。
Redis集群对于节点最终是否故障判断非常严谨,只有一个节点认为主观下线并不能准确判断是否故障,因此需要多个节点协作确认节点是否真的故障。
当某个节点判断另一个节点主观下线后,相应的节点状态会跟随消息在集群内传播。ping/pong消息的消息体会携带集群1/10的其他节点状态数据,当接受节点发现消息体中含有主观下线的节点状态时,会在本地找到故障节点的ClusterNode结构,保存到下线报告链表中;随着Gossip消息传播,集群内节点不断收集到故障节点的下线报告。当半数以上持有槽的主节点都标记某个节点是主观下线时。触发客观下线流程。

流程说明:
1)当消息体内含有其他节点的pfail状态会判断发送节点的状态,如果发送节点是主节点则对报告的pfail状态处理,从节点则忽略。
2)找到pfail对应的节点结构,更新clusterNode内部下线报告链表。
3)根据更新后的下线报告链表告尝试进行客观下线。

尝试客观下线流程说明:
1)首先统计有效的下线报告数量,如果小于集群内持有槽的主节点总数的一半则退出。
2)当下线报告大于槽主节点数量一半时,标记对应故障节点为客观下线状态。
3)向集群广播一条fail消息,通知所有的节点将故障节点标记为客观下线,fail消息的消息体只包含故障节点的ID。
注意:下线报告的有效期限是server.cluster_node_timeout*2,如果在cluster-node-time*2时间内无法收集到一半以上槽节点的下线报告,那么之前的下线报告将会过期,也就是说主观下线上报的速度追赶不上下线报告过期的速度,那么故障节点将永远无法被标记为客观下线从而导致故障转移失败。因此不建议将cluster-node-time设置得过小,伪代码如下:
|
def clusterNodeCleanupFailureReports(clusterNode node) : list report_list = node.fail_reports; long maxtime = server.cluster_node_timeout * 2; long now = now(); for(clusterNodeFailReport report : report_list): // 如果最后上报过期时间大于cluster_node_timeout * 2则删除 if(now - report.time > maxtime): report_list.del(report); |
2.2故障恢复
故障节点变为客观下线后,如果下线节点是持有槽的主节点则需要在它的从节点中选出一个替换它,从而保证集群的高可用。下线主节点的所有从节点承担故障恢复的义务,当从节点通过内部定时任务发现自身复制的主节点进入客观下线时,将会触发故障恢复流程,流程图如下:

1. 资格检查
每个从节点都要检查最后与主节点断线时间,判断是否有资格替换故障的主节点。如果从节点与主节点断线时间超过cluster-node-timeout*cluster-slave-validity-factor,则当前从节点不具备故障转移资格。参数cluster-slavevalidity-factor用于从节点的有效因子,默认为10。
2. 准备选举时间
当从节点符合故障转移资格后,更新触发故障选举的时间,只有到达该时间后才能执行后续流程。故障选举时间相关字段如下:
|
struct clusterState { ... mstime_t failover_auth_time; /* 记录之前或者下次将要执行故障选举时间 */ int failover_auth_rank; /* 记录当前从节点排名 */ } |
这里之所以采用延迟触发机制,主要是通过对多个从节点使用不同的延迟选举时间来支持优先级问题。复制偏移量越大说明从节点延迟越低,那么它应该具有更高的优先级来替换故障主节点。优先级计算伪代码如下:
|
def clusterGetSlaveRank(): int rank = 0; // 获取从节点的主节点 ClusteRNode master = myself.slaveof; // 获取当前从节点复制偏移量 long myoffset = replicationGetSlaveOffset(); // 跟其他从节点复制偏移量对比 for (int j = 0; j < master.slaves.length; j++): // rank表示当前从节点在所有从节点的复制偏移量排名,为0表示偏移量最大. if (master.slaves[j] != myself && master.slaves[j].repl_offset > myoffset): rank++; return rank; } |
使用之上的优先级排名,更新选举触发时间,伪代码如下:
|
def updateFailoverTime(): // 默认触发选举时间:发现客观下线后一秒内执行。 server.cluster.failover_auth_time = now() + 500 + random() % 500; // 获取当前从节点排名 int rank = clusterGetSlaveRank(); long added_delay = rank * 1000; // 使用added_delay时间累加到failover_auth_time中 server.cluster.failover_auth_time += added_delay; // 更新当前从节点排名 server.cluster.failover_auth_rank = rank; |
所有的从节点中复制偏移量最大的将提前触发故障选举流程,如下图:

主节点b进入客观下线后,它的三个从节点根据自身复制偏移量设置延迟选举时间,如复制偏移量最大的节点slave b-1延迟1秒执行,保证复制延迟低的从节点优先发起选举。
3. 发起选举
当从节点定时任务检测到达故障选举时间(failover_auth_time)到达后,发起选举流程如下:
(1)更新配置纪元
配置纪元是一个只增不减的整数,每个主节点自身维护一个配置纪元
(clusterNode.configEpoch)标示当前主节点的版本,所有主节点的配置纪元都不相等,从节点会复制主节点的配置纪元。整个集群又维护一个全局的配置纪元(clusterState.current Epoch),用于记录集群内所有主节点配置纪元的最大版本。执行cluster info命令可以查看配置纪元信息:
|
127.0.0.1:6379> cluster info ... cluster_current_epoch:15 // 整个集群最大配置纪元 cluster_my_epoch:13 // 当前主节点配置纪元 |
配置纪元会跟随ping/pong消息在集群内传播,当发送方与接收方都是主节
点且配置纪元相等时代表出现了冲突,nodeId更大的一方会递增全局配置纪元并赋值给当前节点来区分冲突
(2)广播选举消息
在集群内广播选举消息(FAILOVER_AUTH_REQUEST),并记录已发
送过消息的状态,保证该从节点在一个配置纪元内只能发起一次选举。消息
内容如同ping消息只是将type类型变为FAILOVER_AUTH_REQUEST。
4. 投票选举
只有持有槽的主节点才会处理故障选举消息(FAILOVER_AUTH_REQUEST),因为每个持有槽的节点在一个配置纪元内都有唯一的一张选票,当接到第一个请求投票的从节点消息时回复FAILOVER_AUTH_ACK消息作为投票,之后相同配置纪元内其他从节点的选举消息将忽略。
投票过程其实是一个领导者选举的过程,如集群内有N个持有槽的主节点代表有N张选票。由于在每个配置纪元内持有槽的主节点只能投票给一个从节点,因此只能有一个从节点获得N/2+1的选票,保证能够找出唯一的从节点。所以集群主节点至少三个才能保证集群正常故障转移。

5. 替换主节点
当从节点收集到足够的选票之后,触发替换主节点操作:
1)当前从节点取消复制变为主节点。
2)执行clusterDelSlot操作撤销故障主节点负责的槽,并执行clusterAddSlot把这些槽委派给自己。
3)向集群广播自己的pong消息,通知集群内所有的节点当前从节点变为主节点并接管了故障主节点的槽信息。
注:
配置纪元的主要作用:
·标示集群内每个主节点的不同版本和当前集群最大的版本。
·每次集群发生重要事件时,这里的重要事件指出现新的主节点(新加入的或者由从节点转换而来),从节点竞争选举。都会递增集群全局的配置纪元并赋值给相关主节点,用于记录这一关键事件。
·主节点具有更大的配置纪元代表了更新的集群状态,因此当节点间进行ping/pong消息交换时,如出现slots等关键信息不一致时,以配置纪元更大的一方为准,防止过时的消息状态污染集群。
cluster-node-timeout参数设置:
故障转移时间跟cluster-node-timeout参数息息相关,默认是15秒,该参数设置的越小,所消耗的带宽越大;因此不能设置得太小。
2.3手动切换
应用场景:
1) 主节点迁移:运维Redis集群过程中经常遇到调整节点部署的问题,如节点所在的老机器替换到新机器等
2) 强制故障转移。当自动故障转移失败时,只要故障的主节点有存活的从节点就可以通过手动转移故障强制让从节点替换故障的主节点,保证集群的可用性
在从节点上执行cluster failover命令发起转移流程,默认情况下转移期间客户端请求会有短暂的阻塞,但不会丢失数据,流程如下:
1)从节点通知主节点停止处理所有客户端请求。
2)主节点发送对应从节点延迟复制的数据。
3)从节点接收处理复制延迟的数据,直到主从复制偏移量一致为止,保证复制数据不丢失。
4)从节点立刻发起投票选举(这里不需要延迟触发选举)。选举成功后断开复制变为新的主节点,之后向集群广播主节点pong消息
5)旧主节点接受到消息后更新自身配置变为从节点,解除所有客户端请求阻塞,这些请求会被重定向到新主节点上执行。
6)旧主节点变为从节点后,向新的主节点发起全量复制流程。
针对强制故障转移,cluster failover命令提供了两个参数force/takeover提供支持:
·cluster failover force——用于当主节点宕机且无法自动完成故障转移情况。从节点接到cluster failover force请求时,从节点直接发起选举,不再跟主节点确认复制偏移量(从节点复制延迟的数据会丢失),当从节点选举成功后替换为新的主节点并广播集群配置。
·cluster failover takeover——用于集群内超过一半以上主节点故障的场景,因为从节点无法收到半数以上主节点投票,所以无法完成选举过程。可以执行cluster failover takeover强制转移,接到命令的从节点不再进行选举流程而是直接更新本地配置纪元并替换主节点。takeover故障转移由于没有通过领导者选举发起故障转移,会导致配置纪元存在冲突的可能。当冲突发生时,集群会以nodeId字典序更大的一方配置为准。因此要小心集群分区后,手动执行takeover导致的集群冲突问题
注:
自动故障转移失败的场景有:
·主节点和它的所有从节点同时故障。这个问题需要通过调整节点机器部署拓扑做规避,保证主从节点不在同一机器/机架上。除非机房内大面积故障,否则两台机器/机架同时故障概率很低。
·所有从节点与主节点复制断线时间超过cluster-slave-validityfactor*cluster-node-tineout+repl-ping-slave-period,导致从节点被判定为没有故障转移资格,手动故障转移从节点不做中断超时检查。
·由于网络不稳定等问题,故障发现或故障选举时间无法在cluster-nodetimeout*2内完成,流程会不断重试,最终从节点复制中断时间超时,失去故障转移资格无法完成转移。
·集群内超过一半以上的主节点同时故障。
手动故障转移时,在满足当前需求的情况下建议优先级:cluster failver>cluster failover force>cluster failover takeover。
运维问题
集群完整性
为了保证集群完整性,默认情况下当集群16384个槽任何一个没有指派到节点时整个集群不可用。执行任何键命令返回(error)CLUSTERDOWN Hash slot not served错误,对于大多数业务无法容忍这种情况,因此建议将参数cluster-require-full-coverage配置为no,当主节点故障时只影响它负责槽的相关命令执行,不会影响其他主节点的可用性
带宽消耗
节点间消息通信对带宽的消耗体现在以下几个方面:
·消息发送频率:跟cluster-node-timeout密切相关,当节点发现与其他节点最后通信时间超过cluster-node-timeout/2时会直接发送ping消息。
·消息数据量:每个消息主要的数据占用包含:slots槽数组(2KB空间)和整个集群1/10的状态数据(10个节点状态数据约1KB)。
·节点部署的机器规模:机器带宽的上线是固定的,因此相同规模的集群分布的机器越多每台机器划分的节点越均匀,则集群内整体的可用带宽越高。
集群带宽消耗主要分为:读写命令消耗+Gossip消息消耗。因此搭建Redis集群时需要根据业务数据规模和消息通信成本做出合理规划:
1)在满足业务需要的情况下尽量避免大集群。同一个系统可以针对不同业务场景拆分使用多套集群。这样每个集群既满足伸缩性和故障转移要求,还可以规避大规模集群的弊端。
2)适度提高cluster-node-timeout降低消息发送频率,同时cluster-nodetimeout还影响故障转移的速度,因此需要根据自身业务场景兼顾二者的平衡。
3)如果条件允许集群尽量均匀部署在更多机器上。避免集中部署,如集群有60个节点,集中部署在3台机器上每台部署20个节点,这时机器带宽消耗将非常严重。
集群倾斜
集群倾斜指不同节点之间数据量和请求量出现明显差异,这种情况将加大负载均衡和开发运维的难度。因此需要理解哪些原因会造成集群倾斜,从而避免这一问题。
1. 数据倾斜
数据倾斜主要分为以下几种:
·节点和槽分配严重不均。
·不同槽对应键数量差异过大。
·集合对象包含大量元素。
·内存相关配置不一致。
1) 节点和槽分配严重不均。针对每个节点分配的槽不均的情况,可以使用redis-cli –cluster info {host:ip}进行定位,当节点对应槽数量不均匀时,可以使用redis-trib.rb rebalance命令进行平衡。
2) 不同槽对应键数量差异过大。键通过CRC16哈希函数映射到槽上,正常情况下槽内键数量会相对均匀。但当大量使用hash_tag时,会产生不同的键映射到同一个槽的情况。特别是选择作为hash_tag的数据离散度较差时,将加速槽内键数量倾斜情况。通过命令:cluster countkeysinslot{slot}可以获取槽对应的键数量,识别出哪些槽映射了过多的键。再通过命令clustergetkeysinslot{slot}{count}循环迭代出槽下所有的键。从而发现过度使用hash_tag的键。
3) 集合对象包含大量元素。对于大集合对象的识别可以使用redis-cli--bigkeys命令识别。找出大集合之后可以根据业务场景进行拆分。同时集群槽数据迁移是对键执行migrate操作完成,过大的键集合如几百兆,容易造成migrate命令超时导致数据迁移失败。
4) 内存相关配置不一致。内存相关配置指hash-max-ziplist-value、setmax-intset-entries等压缩数据结构配置。当集群大量使用hash、set等数据结构时,如果内存压缩数据结构配置不一致,极端情况下会相差数倍的内存,从而造成节点内存量倾斜。
2. 请求倾斜
集群内特定节点请求量/流量过大将导致节点之间负载不均,影响集群均衡和运维成本。常出现在热点键场景,当键命令消耗较低时如小对象的get、set、incr等,即使请求量差异较大一般也不会产生负载严重不均。但是当热点键对应高算法复杂度的命令或者是大对象操作如hgetall、smembers等,会导致对应节点负载过高的情况。避免方式如下:
1)合理设计键,热点大集合对象做拆分或使用hmget替代hgetall避免整体读取。
2)不要使用热键作为hash_tag,避免映射到同一槽。
3)对于一致性要求不高的场景,客户端可使用本地缓存减少热键调用。
数据迁移
可以使用redis-migrate-tool,该工具可满足大多数Redis迁移需求,特点如下:
·支持单机、Twemproxy、Redis Cluster、RDB/AOF等多种类型的数据迁移。
·工具模拟成从节点基于复制流迁移数据,从而支持在线迁移数据,业务方不需要停写。
·采用多线程加速数据迁移过程且提供数据校验和查看迁移状态等功能。
GitHub:https://github.com/vipshop/redis-migrate-tool
具体能否用于新版本需要实测

浙公网安备 33010602011771号