Redis的集群结构

12 篇文章 4 订阅

        Redis集群是Redis提供的分布式数据库方案,集群通过分片(sharding)进行数据共享,并提供复制和故障转移功能。

一、节点

        同其他分布式的集群一样,Redis集群也是由多个相互独立的节点组成的,通过将各个相互独立的节点连接起来,构成一个包含多个节点的集群。通过CLUSTER MEET <ip> <port>命令,将指定节点添加当前节点所在的集群:



        

二、槽

        Redis集群通过分片的方式来保存数据库中的键,集合的整个数据库被划分为16384个槽(slot),数据库中的每个键都属于这16384个槽中的一个,每个节点可以处理0~16384个槽。当数据库中16384个槽都有节点处理时集群处理上线状态,反之如果有任意一个槽没有得到处理则集群处于下线状态。

        在cluster.h/clusterNode结构中保存了每个集群节点的状态,包括当前节点所处理的槽信息:

// 节点状态
struct clusterNode {
    //...
    // 由这个节点负责处理的槽
    // 一共有 REDIS_CLUSTER_SLOTS / 8 个字节长
    // 每个字节的每个位记录了一个槽的保存状态
    // 位的值为 1 表示槽正由本节点处理,值为 0 则表示槽并非本节点处理
    // 比如 slots[0] 的第一个位保存了槽 0 的保存情况
    // slots[0] 的第二个位保存了槽 1 的保存情况,以此类推
    unsigned char slots[REDIS_CLUSTER_SLOTS/8]; /* slots handled by this node */
    // 该节点负责处理的槽数量
    int numslots;   /* Number of slots handled by this node */
    //...
}clusterNode;

        slots是一个二进制数组,在索引i上的值为1,则表示当前节点处理槽i;索引i上的值为0,则表示当前节点不处理槽i。这样就可以通过节点的slots属性,以O(1)的时间复杂度判断出当前节点是否处理某个槽。


        但如果只将槽指派信息保存在各个节点的clusterNode.slots数组里,当想了解槽i是否被指派时需要遍历每个节点,整个过程的负责度为O(N)。为达到简单高效的目的,Redis在时在cluster.h/clusterState结构中保存了每个槽的指派信息:

// 集群状态,每个节点都保存着一个这样的状态,记录了它们眼中的集群的样子。
// 另外,虽然这个结构主要用于记录集群的属性,但是为了节约资源,
// 有些与节点有关的属性,比如 slots_to_keys 、 failover_auth_count 
// 也被放到了这个结构里面。
typedef struct clusterState {
    //...    
    // 负责处理各个槽的节点
    // 例如 slots[i] = clusterNode_A 表示槽 i 由节点 A 处理
    clusterNode *slots[REDIS_CLUSTER_SLOTS];
    ///...
}

 

       通过这种方式,程序检查节点是否负责处理某个槽,或者是将某个槽指派给某个节点的时间复杂度都为O(1)。


三、集群

        数据库的16384个槽都进行了指派之后,集群就会进入上线状态,当客户端向节点发送数据库键相关的命令时,接收命令的节点会计算出命令要处理的数据库键属于哪个槽,然后检查槽是否指派给了自己:

(1)如果指派给了自己,则节点直接执行该命令;
(2)如果没有指派给自己,则指引客户端转向到正确的节点;



四、重新分片

         Redis集群通过重新分片功能保证集群不下线的情况下随时增加或减少节点的能力。Redis集群的重新分片是指:可以将任意数量已指派给某节点的槽改为指派给另一个节点,并且相关槽所在的键值也会从源节点移动到目标节点。

        Redis集群重新分片操作是由Redis集群管理软件redis-trib负责执行, 通过向源节点和目标节点发送命令进行重新分片操作:

(1)redis-trib向目标节点发送cluster setslot <slot> importing <source_id>命令,让目标节点准备导入属于槽slot的键值对;

(2)redis-trib向源节点发送cluster setslot <slot> migrating <target_id>命令,让源节点准备将属于槽slot的键值对迁移到目标节点;

(3)redis-trib向源节点发送cluster getkeysinslot <slot> <count>命令,将最多count个属于槽slot的键值对的键名;

(4)redis-trib向目标节点发送migrate <targe_ip> <target_pot> <key_name> 0 <timeout>命令,将被选中的键原子地从源节点迁移到目标节点;

(5)重复步骤(3)(4),直到所有属于槽slot的键值对都被迁移至目标节点为止;

(6)redis-trib向集合中任意一个节点发送cluster setslot <slot> node <target_id>命令,将槽slot指派给目标节点,这一指派消息会通过消息发送至整个集群,最终整个集群都知道槽slot已经指派给了目标节点。


        在进行重新分片期间,可能会出现这样一种情况:属于被迁移槽的一部分键值对保存在源节点里,而另一部分键值对保存在目标节点里。所以在重新分片期间,当客户端向源节点发送与数据库键相关的命令时,源节点会先在自己的数据库里查找指定键,如果找到就返回;如果没找到就指引客户端转向正在导入槽的目标节点,并再次发送之前键相关操作的命令。


参考资料
1、http://www.redis.net.cn/tutorial/3506.html
2、《Redis设计与实现》第二版---黄健宏
3、https://github.com/xingzhexiaozhu/redis-3.0-annotated
4、http://www.yiibai.com/redis/redis_strings.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redis集群是一个分布式实现,它采用了网状结构,每个节点通过TCP连接与其他节点连接。这种结构使得Redis集群在节点数量增加到1000个时仍能表现出良好的性能,并且可扩展性是线性的。\[1\] 关于Redis集群结构,它使用了异步复制来实现节点之间的数据同步,并且没有合并操作。在写入安全性方面,系统会尽力保存与大多数节点相连的客户端所做的写入操作,但仍然可能会有少部分写入丢失。在可用性方面,只要绝大多数的主节点是可达的,并且每个不可达的主节点都至少有一个从节点是可达的,Redis集群仍然能够进行分区操作。\[3\] 总结来说,Redis集群采用了网状结构,通过节点之间的TCP连接实现数据同步和通信。这种结构使得Redis集群具有良好的可扩展性和性能,并且在写入安全性和可用性方面也有一定的保证。\[1\]\[3\] #### 引用[.reference_title] - *1* *3* [Redis集群](https://blog.csdn.net/Iloveyougirls/article/details/81814679)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Redis集群-高可用集群搭建](https://blog.csdn.net/qq_36118179/article/details/114785995)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值