作为一个分布式K-V存储,redis cluster通过将数据切分为16384个slot进行分布式存储,用公式表示如下:
作为一个支持水平扩容的分布式系统,redis集群在扩容时通常遵循如下步骤:
1.在新节点启动redis进程
2.将新节点加入集群
3.迁移部分slot至新节点
在较老版本的redis cluster中,该指令通过redis-trib.rb脚本执行,在新版本的redis中,脚本功能已经与redis-cli集成完毕,可通过redis-cli --cluster [command] [option]形式执行,在执行速度和依赖管理方面都有了较大的提高。相关命令和迁移效率可参见如下文档:
https://redislabs.com/wp-content/uploads/2018/04/redis_cluster_manager.pdf
对redis cluster的client/proxy来说,保证一个处于数据迁移中的redis cluster访问正常,要点在于如下能力:
1.识别处于迁移过程中的key
2.确定刷新slot -> node mapping的时机
3.识别需要重定向的请求进行并进行二次分发
在实践中,达成上述三项能力的核心在于依据请求响应的不同内容适配不同的处理逻辑。
以get请求为例,对于redis cluster来说,响应可分为如下类型:
1.正常返回value
2.返回-ASK 3999 127.0.0.1:6381
3.返回-MOVED 3999 127.0.0.1:6381
对于类型1,直接返回即可。
对于类型2,获取目标节点后,先发送ASKING指令,再重复发送get请求,不要尝试更新slot -> node mapping,因为slot此时还未完成迁移,若未前置ASKING指令,在访问target node时,将再次收到MOVED响应,指向source node。
对于类型3,获取目标节点后,刷新slot -> node mapping,再重复发送get请求
由上述分析可以看出,对于重定向请求,进行一次重发即可。
Tip:
1.一个key在任何时刻只可能存在于一个master node,因为在调用migrate指令时,source & target node都会被锁定
2.一个key最多只需要处理一次重定向,原因参见tip1
ASK & MOVED区别:
1.MOVED代表该slot中的key已经永久全部迁移至目标节点
2.ASK代表当前key已经被目标节点迁移,但该slot中还存在部分key未被迁移完成,slot的状态还未更新为stable