Redis Cluster 集群

Redis Cluster是Redis的分布式解决方案

一、数据分布

哈希分区那么不外乎一致性hash了,这个说太多了,不清楚的自行上网查阅,资料很多的。不过这里得讲下一致性hash的缺点

加减节点会造成hash环中有部分数据无法命中,需要手动或者忽略这部分数据。不过这个针对缓存场景是可以适用的

如果使用的hash环里的节点很少,那么节点的变化将会大范围影响数据的映射

普通的一致性哈希分区再增减节点是需要增加一倍或减去一遍节点才能保证数据和负载的均衡

那么圈子里就出现了一个改进版的,比如Gynamo系统

那么这里讲解下虚拟槽分区,就是在数据和节点之间多了一个槽(slot)这个概念。目前Redis Cluster槽范围0-16383.槽是集群内数据管理和迁移的基本单位,采用这么大范围的槽是为了方便数据拆分和集群扩展,让每个节点负责一定数量的槽

这里能均匀分布到16383个槽里,是有一个高级的哈希函数计算得来的,slot=CRC16(key)&16383

如上分区以后,自然有功能的限制的

相同的槽下才支持key的批量操作,比如mget这类命令

相同节点下才支持key的事务操作

大的键值对象不能映射到不同节点,因为key是数据分区最小粒度,不能比slot还大

集群下只支持使用一个数据库空间

复制结构只支持一层,从节点只能复制主节点,不支持嵌套树状复制结构

二、搭建集群

集群搭建网上教程很多,这里不重复,下面直接讲关键的知识点哦

这个时候执行命令cluster nodes只会展示自己的节点信息,这个时候需要节点握手

2)节点握手

指一批运行在集群模式下的节点通过Gossip协议彼此通信,达到感知对方的过程

cluster meet是一个异步命令

节点6379本地创建6380节点信息对象,并发送meet消息给6380

6380接受到meet消息后,保存6379节点信息并回复pong消息

之后6379和6380彼此定期通过ping/pong消息进行正常的节点通信

如上命令cluster meet 127.0.0.1 6380 节点握手以后再执行cluster nodes,此时就会展示两个节点的信息

全部握手以后还不能正常工作,这时的集群处于下线状态,所有数据读写都被禁止,可以通过cluster info命令获取集群当前状态

如上所示,全部节点握手以后被分配的槽cluster_slots_assigned是0,由于所有槽没有分配到节点,集群无法完成槽到节点的映射。只有16384个槽全部分配给节点后,集群才进入在线状态

3)分配槽

槽跟节点分配如上,分配完毕查看集群状态如下

如上,每个被分配槽的节点都需要从节点来支持故障转移

如上主从节点建立复制关系执行命令如下:

cluster replicate

完成以后再执行cluster nodes命令可以查看集群状态和复制关系的整个关系图

三、用redis-trib.rb搭建集群

上面第二大部分可以想象,集群节点过多必然导致集群更复杂,那么这里讲下redis-trib.rb

关于搭建redis-trib.rb执行命令网上教程有,这里不重复。这里主要讲下它的玩法

1)redis-trib.rb create

这里就启动六个redis节点,启动以后执行下面指令直接完成节点的握手和槽分配工作

--replicas 1 //1表示每个主节点分配一个从节点

上面命令执行后后面还有几个简单步骤

2)redis-trib.rb check

该指令检查16384个槽是否全部分配,缺一不可。随便集群中的一个及诶点执行redis-trib.rb check 127.0.0.1:6379就可以完成全部检查工作,这里可以不说6379这个节点

四、节点通信

节点通信靠Gossip协议进行的信息交换,具体可以自行上网查看,它包含消息头和消息体

1)通信过程

集群中每个节点都会单独开辟一个TCP通道,用户节点之间彼此通信,通信端口号再基础端口上加10000

当节点处故障,新节点加入,主从角色变化,槽信息变更等事件发生时,通过不断ping/pong消息通信,所有节点都会知道整个集群全部节点的最新状态从而达到集群状态同步的目的

2)Gossip协议进行的通信节点交换信息,交换过多带宽等,少影响节点间的信息交换频率。所有策略如下图所示

3)如上可知集群越大,整个通信传输消息越多。所以不是集群越大就越好,这个要注意

五、集群伸缩

这里开始重点讲解槽跟节点之间的关系了,大家看到这里一定有这个疑问,那么请继续看

新增的节点跟前面建立节点握手一样进入集群中,只是此时因为没有分配槽而无法进行数据读写

除了原始指令,也可以使用redis-trib.rb工具实现

添加从节点

添加新的主节点

1)扩容

这里节点扩容使用redis-trib.rb完成

首先命令redis-trib.rb reshard 127.0.0.1:6379

这时候会让你输入需要迁移多少个槽

输入目标的节点ID

输入多个源节点的ID

redis-trib.rb给出分配计划,选择yes 或者no

完成自动退出

执行cluster nodes命令查看

redis-trib.rb rebalance 127.0.0.1:6380 检查各个节点之间的槽的均衡性

新增的主节点扩容完毕,需要给该主节点新增从节点完成主从复制的安全措施

在从节点处执行cluster replicate

cluster nodes 查看全部完成情况

2)收缩

同扩容,只是源节点假设4096个槽分成N次通过reshard命令分N次迁移到N个目标节点上

cluster forget 移出的节点,集群里不再发生Gossip消息,在60秒之后节点就完全下线

建议下线节点使用redis-trib.rb del-node ,有从节点先下从节点再主节点

六、请求路由

如果redis客户端设置值的时候如果不在当前节点就会转换节点连接,如下图流程

注意:

通过{}这个标签可以实现同一个slot存储 ,对mget、pipeline这些指令的好处

客户端

ASK重定向如下

在集群环境下,使用批量操作场景优先选择Pipeline方式

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180904G1HS5O00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券