redis——集群

本文转自 https://www.jianshu.com/p/b35d778fa529 和https://www.cnblogs.com/lykxqhh/p/5690923.html

一.  虚拟槽哈希分布

1.1  槽(slot)概念

Redis Cluster中有一个16384长度的槽的概念,他们的编号为0、1、2、3……16382、16383。这个槽是一个虚拟的槽,并不是真正存在的。正常工作的时候,Redis Cluster中的每个Master节点都会负责一部分的槽,当有某个key被映射到某个Master负责的槽,那么这个Master负责为这个key提供服务,至于哪个Master节点负责哪个槽,这是可以由用户指定的,也可以在初始化的时候自动生成(redis-trib.rb脚本)。这里值得一提的是,在Redis Cluster中,只有Master才拥有槽的所有权,如果是某个Master的slave,这个slave只负责槽的使用,但是没有所有权。

 

1.2  数据分片

在Redis Cluster中,拥有16384个slot,这个数是固定的,存储在Redis Cluster中的所有的键都会被映射到这些slot中。数据库中的每个键都属于这16384个哈希槽的其中一个,集群使用公式CRC16(key) % 16384来计算键key属于哪个槽,其中CRC16(key)语句用于计算键key的CRC16校验。集群中的每个节点负责处理一部分哈希槽。

 

1.3  节点的槽指派信息

clusterNode结构的slots属性和numslot属性记录了节点负责处理那些槽:
struct clusterNode {
//…
unsignedchar slots[16384/8];
};
Slots属性是一个二进制位数组(bit
array),这个数组的长度为16384/8=2048个字节,共包含16384个二进制位。
Master节点用bit来标识对于某个槽自己是否拥有。比如对于编号为1的槽,Master只要判断序列的第二位(索引从0开始)是不是为1即可。时间复杂度为O(1)。

 

1.4  集群所有槽的指派信息

通过将所有槽的指派信息保存在clusterState.slots数组里面,程序要检查槽i是否已经被指派,又或者取得负责处理槽i的节点,只需要访问clusterState.slots[i]的值即可,复杂度仅为O(1)。

 

1.5  请求重定向 

由于每个节点只负责部分slot,以及slot可能从一个节点迁移到另一节点,造成客户端有可能会向错误的节点发起请求。因此需要有一种机制来对其进行发现和修正,这就是请求重定向。有两种不同的重定向场景:
a)MOVED错误
1.请求的key对应的槽不在该节点上,节点将查看自身内部所保存的哈希槽到节点ID的映射记录, 节点回复一个MOVED错误。
2.需要客户端进行再次重试。

b)ASK错误
1.请求的key对应的槽目前的状态属于MIGRATING状态,并且当前节点找不到这个key了,节点回 复ASK错误。ASK会把对应槽的IMPORTING节点返回给你,告诉你去IMPORTING的节点尝试找找。
2.客户端进行重试首先发送ASKING命令,节点将为客户端设置一个一次性的标志(flag),使得 客户端可以执行一次针对IMPORTING状态的槽的命令请求,然后再发送真正的命令请求。
3.不必更新客户端所记录的槽至节点的映射。

二  基本架构

Redis集群搭建的方式有多种,例如使用zookeeper等,但从redis 3.0之后版本支持redis-cluster集群,Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有 节点连接。其redis-cluster架构图如下:

其结构特点:

  1. 所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
  2. 节点的fail是通过集群中超过半数的节点检测失效时才生效
  3. 客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
  4. redis-cluster把所有的物理节点映射到[0-16383]slot上(不一定是平均分配),cluster 负责维护node<->slot<->value。       
  5. Redis集群预分好16384个桶,当需要在 Redis 集群中放置一个 key-value 时,根据 CRC16(key) mod 16384的值,决定将一个key放到哪个桶中。

 

redis cluster节点分配

现在我们是三个主节点分别是:A, B, C 三个节点,它们可以是一台机器上的三个端口,也可以是三台不同的服务器。那么,采用哈希槽 (hash slot)的方式来分配16384个slot 的话,它们三个节点分别承担的slot 区间是:

       节点A覆盖0-5460;
       节点B覆盖5461-10922;
       节点C覆盖10923-16383.

       获取数据:

       如果存入一个值,按照redis cluster哈希槽的算法: CRC16('key')%16384 = 6782。 那么就会把这个key 的存储分配到 B 上了。同样,当我连接(A,B,C)任何一个节点想获取'key'这个key时,也会这样的算法,然后内部跳转到B节点上获取数据 

       新增一个主节点:

       新增一个节点D,redis cluster的这种做法是从各个节点的前面各拿取一部分slot到D上,我会在接下来的实践中实验。大致就会变成这样:

       节点A覆盖1365-5460
       节点B覆盖6827-10922
       节点C覆盖12288-16383
       节点D覆盖0-1364,5461-6826,10923-12287


       同样删除一个节点也是类似,移动完成后就可以删除这个节点了。

三  安装

集群的安装分为两种,一种是原生命令的安装,还有一种是官方工具的安装

原生命令的安装分为下面几步:

  1. 配置开启节点
  2. meet
  3. 指派槽
  4. 设置主从

但是原生命令安装在生产环境中是不使用的,因为麻烦,容易犯错。一般都是使用官方工具来进行安装,这样更高效,准确。

我们先准备Ruby环境准备,一共有如下三步骤:

  1. 下载、编译、安装Ruby
  2. 安装rubygem redis
  3. 安装redis-trib.rb

具体命令如下:

然后我们再搭建集群

具体步骤就不写了,大家可以去看:

https://www.cnblogs.com/lykxqhh/p/5690923.html

发布了114 篇原创文章 · 获赞 199 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/qq_36582604/article/details/89458905