Redis集群水平扩展(一)

Redis分布式方案一般有两种

1、客户端分区,优点是分区逻辑可控,缺点是需要客户端处理数据路由、高可用、故障转移等。

2、代理方案,优点是简化客户端逻辑和升级,缺点是加重架构复杂性和性能损耗。

Redis Cluster是官方提供的分布式解决方案,从3.0版本正式推出,和以上两种方案都不太一样,采用了虚拟槽分区,分区方式采用了hash分区,它并没有使用一致性hash(增减节点会导致部分数据无法命中,当使用少量节点时节点变化会导致影响数据映射),而是使用改进的一致性hash-虚拟槽方式分区。Redis Cluster使用了 16384 个虚拟槽,槽被分配给节点管理。

节点通信使用 Gossip协议,常用的消息有 ping,pong,meet,fail。每个节点都会保存集群的完整拓扑信息和槽信息(这就避免了单点)。所以向任何一个节点发送请求,若数据在当前节点则命中,若不在则返回 MOVED IP PORT 消息,指明数据所在的节点信息,客户端只需要重新发送即可。即  CRC16(key)->slot_num->节点 或者 CRC16(key)->slot_num->节点 返回 MOVED信息,客户端可以redirect到目标节点,疑问: 如果目标节点正在扩容或者摘除,如何处理?见下面分析。

 

Redis Cluster缺点

1、批量操作有问题,mget,mset命令只能支持具有相同slot值的key(所有可以使用 hash_tag 来把key映射到相同slot);

2、key事务支持有限,不能跨节点,也不能把大的对象映射到不同节点;

3、复制结构只支持一层,不支持树形结构,即从节点只有一层;

 

集群扩容与节点摘除

集群扩容

(1)准备新节点

(2)加入集群(只需要向一个节点发送meet命令,Gossip协议就会传播至所有节点)

(3)迁移槽和数据

         3.1 准备槽迁移计划,即要迁移哪个槽,默认的集群会尽量平均分配槽至各节点

         3.2 向目标节点发送命令,目标节点做准备

         3.3 向源节点发命令,源节点做准备

         3.4 源节点循环获取要迁移的槽里面的key

         3.5 源节点批量(pipeline)迁移数据至目标节点(期间是保证高可用(ASK机制保证),如何保证下面讲)

         3.6 向集群所有的主节点发送命令,说明槽已经迁移至新节点

集群收缩

(1)当下线的节点不负责槽或者下线的节点是从节点,只需要通知其他节点,通知成功后下线节点即可

(2)如果当前节点有负责的槽,则和机器扩容步骤(3)一样,将本节点负责的槽迁移出去

 

集群请求路由

为了提升效率,Jedis本地会额外缓存一份slot到node的映射数据,所以一般情况下获取到的node是对的,若槽和节点映射有变化,会有MOVED信息,客户端会去节点获取slot到node最新信息更新本地。

 

MOVED路由

1、 CRC16(key)->Slot槽,若节点是当前节点,则处理,若节点不是当前节点,则返回 MOVED 信息

2、客户端向 MOVED指向的节点重发请求

 

ASK重定向

1、 CRC16(key)->Slot槽最终进入目标节点,若槽在迁移且对象不在,则返回ASK信息

2、客户端向ASK信息的节点发送请求

 

所以即便在槽迁移过程中,集群仍然能保证高可用。

 

 

 

参考连接:

https://ballenlee.iteye.com/blog/2410315

 

 

 

2 Replies to “Redis集群水平扩展(一)”

Leave a Reply

Your email address will not be published.