redis哨兵+主从的问题 、Redis Cluster集群

Redis集群

1、redis哨兵+主从的问题
2、Redis Cluster介绍

一、redis哨兵+主从的问题

假设我们在一台主从机器上配置了200G内存,但是业务需求是需要500G的时候,主从结构+哨兵可以实现高可用故障切换+冗余备份,但是并不能解决数据容量的问题,用哨兵,redis每个实例也是全量存储,每个redis存储的内容都是完整的数据,浪费内存且有木桶效应。

为了最大化利用内存,可以采用cluster群集,就是分布式存储。即每台redis存储不同的内容。

Redis 分布式方案一般有两种:

1、客户端分区方案,优点是分区逻辑可控,缺点是需要自己处理数据路由、高可用、故障转移等问题,比如在redis2.8之前通常的做法是获取某个key的 hashcode,然后取余分布到不同节点,不过这种做法无法很好的支持动态伸缩性需求,一旦节点的增或者删操作,都会导致key无法在redis中命中。
[图片上传失败...(image-c7f01f-1672315959845)]

2、代理方案,优点是简化客户端分布式逻辑和升级维护便利,缺点是加重架构部署复杂度和性能损耗,比如 twemproxy、Codis
[图片上传失败...(image-fc3155-1672315959845)]

3、官方为我们提供了专有的集群方案:Redis Cluster,它非常优雅地解决了 Redis 集群方面的问题,部署方便简单,因此理解应用好 Redis Cluster 将极大地解放我们使用分布式 Redis 的工作量。

二、Redis Cluster

1、简介

Redis Cluster 是 Redis 的分布式解决方案,在3.0版本正式推出,有效地解决了 Redis 分布式方面的需求。当遇到单机内存、并发、流量等瓶颈时,可以采用 Cluster 架构方案达到负载均衡的目的。
架构图:

[图片上传失败...(image-1c6be2-1672315959845)]

在这个图中,每一个蓝色的圈都代表着一个redis的服务器节点。它们任何两个节点之间都是相互连通的。客户端可以与任何一个节点相连接,然后就可以访问集群中的任何一个节点,对其进行存取和其他操作。

Redis 集群提供了以下两个好处:

1、将数据自动切分到多个节点的能力。  
2、当集群中的一部分节点失效或者无法进行通讯时, 仍然可以继续处理命令请求的能力,拥有自动故障转移的能力。

2、redis cluster vs. replication + sentinal如何选择

如果你的数据量很少,主要是承载高并发高性能的场景,比如你的缓存一般就几个G,单机足够了。

  • Replication:一个mater,多个slave,要几个slave跟你的要求的读吞吐量有关系,结合sentinal集群,去保证redis主从架构的高可用性,就可以了。

  • redis cluster:主要是针对海量数据+高并发+高可用的场景,海量数据,如果你的数据量很大,那么建议就用redis cluster。

数据分布是如何进行的

什么是数据分布?数据分布有两种方式,顺序分区和哈希分区。

分布式数据库首先要解决把整个数据集按照分区规则映射到多个节点的问题,即把数据集划分到多个节点上,每个节点负责整体数据的一个子集。

顺序分布就是把一整块数据分散到很多机器中,如下图所示。

[图片上传失败...(image-fa1b28-1672315959845)]

顺序分布一般都是平均分配的。

哈希分区

如下图所示,1~100这整块数字,通过 hash 的函数,取余产生的数。这样可以保证这串数字充分的打散,也保证了均匀的分配到各台机器上。

[图片上传失败...(image-37c7d9-1672315959845)]

哈希分布和顺序分布只是场景上的适用。哈希分布不能顺序访问,比如你想访问1~100,哈希分布只能遍历全部数据,同时哈希分布因为做了 hash 后导致与业务数据无关了。
[图片上传失败...(image-afa6fe-1672315959845)]

数据倾斜与数据迁移跟节点伸缩

顺序分布是会导致数据倾斜的,主要是访问的倾斜。每次点击会重点访问某台机器,这就导致最后数据都到这台机器上了,这就是顺序分布最大的缺点。

但哈希分布其实是有个问题的,当我们要扩容机器的时候,专业上称之为“节点伸缩”,这个时候,因为是哈希算法,会导致数据迁移。

哈希分区方式

因为redis-cluster使用的就是哈希分区规则所以分析下几种分区形式

1、节点取余分区

使用特定的数据(包括redis的键或用户ID),再根据节点数量N,使用公式:hash(key)%N计算出一个0~(N-1)值,用来决定数据映射到哪一个节点上。即哈希值对节点总数取余。

缺点:当节点数量N变化时(扩容或者收缩),数据和节点之间的映射关系需要重新计算,这样的话,按照新的规则映射,要么之前存储的数据找不到,要么之前数据被重新映射到新的节点(导致以前存储的数据发生数据迁移)

实践:常用于数据库的分库分表规则,一般采用预分区的方式,提前根据数据量规划好分区数,比如划分为512或1024张表,保证可支撑未来一段时间的数据量,再根据负载情况将表迁移到其他数据库中。

2、一致性哈希

一致性哈希分区(Distributed Hash Table)实现思路是为系统中每个节点分配一个 token,范围一般在0~232,这些 token 构成一个哈希环。数据读写执行节点查找操作时,先根据 key 计算 hash 值,然后顺时针找到第一个大于等于该哈希值的 token 节点

[图片上传失败...(image-e5efa2-1672315959845)]

上图就是一个一致性哈希的原理解析。

假设我们有 n1~n4 这四台机器,我们对每一台机器分配一个唯一 token,每次有数据(图中黄色代表数据),一致性哈希算法规定每次都顺时针漂移数据,也就是图中黄色的数 据都指向 n3。

这个时候我们需要增加一个节点 n5,在 n2 和 n3 之间,数据还是会发生漂移(会偏移到大于等于的节点),但是这个时候你是否注意到,其实只有 n2~n3 这部分的数据被漂移,其他的数据都是不会变的,这种方式相比节点取余最大的好处在于加入和删除节点只影响哈希环中相邻的节点,对其他节点无影响

  • 缺点:每个节点的负载不相同,因为每个节点的hash是根据key计算出来的,换句话说就是假设key足够多,被hash算法打散得非常均匀,但是节点过少,导致每个节点处理的key个数不太一样,甚至相差很大,这就会导致某些节点压力很大

  • 实践:加减节点会造成哈希环中部分数据无法命中,需要手动处理或者忽略这部分数据,因此一致性哈希常用于缓存场景。

3.虚拟槽分区

虚拟槽分区巧妙地使用了哈希空间,使用分散度良好的哈希函数把所有数据映射到一个固定范围的整数集合中,整数定义为槽(slot)。这个范围一般远远大于节点数,比如 Redis Cluster 槽范围是 0~16383。槽是集群内数据管理和迁移的基本单位。采用大范围槽的主要目的是为了方便数据拆分和集群扩展。每个节点会负责一定数量的槽,下图所示。

当前集群有5个节点,每个节点平均大约负责3276个槽。由于采用高质量的哈希算法,每个槽所映射的数据通常比较均匀,将数据平均划分到5个节点进行数据分区。Redis Cluster 就是采用虚拟槽分区,下面就介绍 Redis 数据分区方法。
[图片上传失败...(image-aa94a5-1672315959845)]

每当 key 访问过来,Redis Cluster 会计算哈希值是否在这个区间里。它们彼此都知道对应的槽在哪台机器上,这样就能做到平均分配了。

集群限制:
Key批量操作,mget()

三、准备搭建集群

介绍完 Redis 集群分区规则之后,下面我们开始搭建 Redis 集群。搭建集群工作需要以下三个步骤:

1)准备节点。
2)节点握手。
3)分配槽。  

1、准备节点

  • 性能:这是Redis赖以生存的看家本领,增加集群功能后当然不能对性能产生太大影响,所以Redis采取了P2P而非Proxy方式、异步复制、客户端重定向等设计,而牺牲了部分的一致性、使用性。

  • 水平扩展:集群的最重要能力当然是扩展,文档中称可以线性扩展到1000结点。
    可用性:在Cluster推出之前,可用性要靠Sentinel保证。有了集群之后也自动具有了Sentinel的监控和自动Failover能力。

Redis 集群一般由多个节点组成,节点数量至少为6个才能保证组成完整高可用的集群,前面的主从复制跟哨兵共同构成了高可用。

每个节点需要开启配置 cluster-enabled yes,让 Redis 运行在集群模式下。集群相关配置如下:

#节点端口 
port 6379 

#开启集群模式
 cluster-enabled yes

#节点超时时间,单位毫秒
 cluster-node-timeout 15000 

#集群内部配置文件
cluster-config-file "nodes-6379.conf"

[图片上传失败...(image-45e48a-1672315959845)]

2、节点规划

容器名称 容器IP地址 映射端口号 服务运行模式
Redis-master 172.22.0.9 22530 -> 26379 sentinel
Redis-master2 172.22.0.10 22531 -> 26379 sentinel
Redis-master3 172.22.0.11 22532 -> 26379 sentinel
redis-slave 172.30.0.5 6383 -> 6379 Master
redis-slave2 172.30.0.6 6384 -> 6379 Slave
redis-slave3 172.30.0.6 6385 -> 6379 Slave

四、搭建集群

介绍完 Redis 集群分区规则之后,下面我们开始搭建 Redis 集群。搭建集群工作需要以下三个步骤:

1)准备节点。
2)节点握手。
3)分配槽。

4.1、准备节点

Redis 集群一般由多个节点组成,节点数量至少为6个才能保证组成完整高可用的集群。每个节点需要开启配置 cluster-enabled yes,让 Redis 运行在集群模式下,上面的配置都相应的给到 redis 的配置文件当中并启动。

其他配置和单机模式一致即可,配置文件命名规则 redis-{port}.conf,准备好配置后启动所有节点,第一次启动时如果没有集群配置文件,它会自动创建一份,文件名称采用 cluster-config-file 参数项控制,建议采用 node-{port}.conf 格式定义,也就是说会有两份配置文件

当集群内节点信息发生变化,如添加节点、节点下线、故障转移等。节点会自动保存集群状态到配置文件中。需要注意的是,Redis 自动维护集群配置文件,不要手动修改,防止节点重启时产生集群信息错乱

配置文件信息如下:

[图片上传失败...(image-e769a0-1672315959845)]

文件内容记录了集群初始状态,这里最重要的是节点 ID,它是一个40位16进制字符串,用于唯一标识集群内一个节点,节点 ID 在集群初始化时只创建一次,节点重启时会加载集群配置文件进行重用,结合做相应的集群操作,而 Redis 的运行 ID 每次重启都会变化。

4.2、节点握手

节点握手是指一批运行在集群模式下的节点通过 Gossip 协议彼此通信,达到感知对方的过程。节点握手是集群彼此通信的第一步,由客户端发起命令:cluster meet{ip}{port}

关于Gossip可以看看文章的介绍
http://www.10tiao.com/html/681/201803/2651029463/1.html

通过命令 cluster meet 127.0.0.1 6380 让节点 6379 和 6380 节点进行握手通信。cluster meet 命令是一个异步命令,执行之后立刻返回。内部发起与目标节点进行握手通信
[图片上传失败...(image-3972c3-1672315959845)]

1)节点6379本地创建6380节点信息对象,并发送 meet 消息。  
2)节点6380接受到 meet 消息后,保存6379节点信息并回复 pong 消息。  
3)之后节点6379和6380彼此定期通过 ping/pong 消息进行正常的节点通信。  

通过 cluster nodes 命令确认6个节点都彼此感知并组成集群
[图片上传失败...(image-6d909d-1672315959845)]

注意:

1、每个Redis Cluster节点会占用两个TCP端口,一个监听客户端的请求,默认是6379,另外一个在前一个端口加上10000, 比如16379,来监听数据的请求,节点和节点之间会监听第二个端口,用一套二进制协议来通信。
节点之间会通过套协议来进行失败检测,配置更新,failover认证等等。
为了保证节点之间正常的访问,需要注意防火墙的配置。

2、节点建立握手之后集群还不能正常工作,这时集群处于下线状态,所有的数据读写都被禁止

3、设置从节点作为一个完整的集群,需要主从节点,保证当它出现故障时可以自动进行故障转移。集群模式下,Reids 节点角色分为主节点和从节点。
首次启动的节点和被分配槽的节点都是主节点,从节点负责复制主节点槽信息和相关的数据。

使用 cluster replicate {nodeId} 命令让一个节点成为从节点。其中命令执行必须在对应的从节点上执行,将当前节点设置为 node_id 指定的节点的从节点

redis-cli -h 47.98.147.49 -p 6395  CLUSTER REPLICATE   0affa79edef47e10a0459832d279fe74467be98b

redis-cli -h 47.98.147.49 -p 6396  CLUSTER REPLICATE   1e30c186681638411f25f949f1b6ffded5f5d0a3

4、分配槽

Redis 集群把所有的数据映射到16384个槽中。每个 key 会映射为一个固定的槽,只有当节点分配了槽,才能响应和这些槽关联的键命令。通过 cluster addslots 命令为节点分配槽

利用 bash 特性批量设置槽(slots),命令如下:  
redis-cli -h 47.98.147.49  -p  6391  cluster addslots {0..5461}
redis-cli -h 47.98.147.49  -p  6392  cluster addslots {5462..10922}
redis-cli -h 47.98.147.49  -p  6393  cluster addslots {10923..16383}

我们依照 Redis 协议手动建立一个集群。它由6个节点构成,3个主节点负责处理槽和相关数据,3个从节点负责故障转移。手动搭建集群便于理解集群建立的流程和细节,但是我们从中发现集群搭建需要很多步骤,当集群节点众多时,必然会加大搭建集群的复杂度和运维成本。因此 Redis 官方提供了 redis-trib.rb 工具方便我们快速搭建集群。

5、操作集群 -c 集群模式  

[图片上传失败...(image-4e4f80-1672315959845)]
如果没有指定集群模式,那么会出现如下错误

[图片上传失败...(image-1afff2-1672315959845)]

所有命令:

CLUSTER info:     打印集群的信息。
CLUSTER nodes:    列出集群当前已知的所有节点(node)的相关信息。

CLUSTER meet  :              将ip和port所指定的节点添加到集群当中。
CLUSTER addslots  [slot ...]:    将一个或多个槽(slot)指派(assign)给当前节点。
CLUSTER delslots  [slot ...]:    移除一个或多个槽对当前节点的指派。
CLUSTER slots: 列出槽位、节点信息。  

CLUSTER slaves :        列出指定节点下面的从节点信息。
CLUSTER replicate :    将当前节点设置为指定节点的从节点。

CLUSTER saveconfig:        手动执行命令保存保存集群的配置文件,集群默认在配置修改的时候会自动保存配置文件。
CLUSTER keyslot :     列出key被放置在哪个槽上。
CLUSTER flushslots:        移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。

CLUSTER countkeysinslot :           返回槽目前包含的键值对数量。
CLUSTER getkeysinslot  :     返回count个槽中的键。
CLUSTER setslot  node       将槽指派给指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽,然后再进行指派。  
CLUSTER setslot  migrating  将本节点的槽迁移到指定的节点中。  
CLUSTER setslot  importing  从 node_id 指定的节点中导入槽 slot 到本节点。  
CLUSTER setslot  stable              取消对槽 slot 的导入(import)或者迁移(migrate)。 

CLUSTER failover:            手动进行故障转移。
CLUSTER forget :    从集群中移除指定的节点,这样就无法完成握手,过期时为60s,60s后两节点又会继续完成握手。
CLUSTER reset [HARD|SOFT]:   重置集群信息,soft是清空其他节点的信息,但不修改自己的id,hard还会修改自己的id,不传该参数则使用soft方式。

CLUSTER count-failure-reports :    列出某个节点的故障报告的长度。
CLUSTER SET-CONFIG-EPOCH:                   设置节点epoch,只有在节点加入集群前才能设置。

五、redis-trib.rb 搭建集群

redis-trib.rb 是采用 Ruby 实现的 Redis 集群管理工具。内部通过 Cluster 相关命令帮我们简化集群创建、检查、槽迁移和均衡等常见运维操作,使用之前需要安装 Ruby 依赖环境。下面介绍搭建集群的详细步骤。

内部通过 Cluster 相关命令帮我们简化集群创建、检查、槽迁移和均衡等常见运维操作,使用之前需要安装 Ruby 依赖环境,相关扩展这个我在 dockerfile 文件当中已经写了指令,查看下理解意思就可以了。

启动好6个节点之后,使用 redis-trib.rb create 命令完成节点握手和槽分配过程

redis-trib.rb create --replicas 1 47.98.147.49:6391  47.98.147.49:6392  47.98.147.49:6393 47.98.147.49:6394 47.98.147.49:6395 47.98.147.49:6396

--replicas 参数指定集群中每个主节点配备几个从节点,这里设置为1,redis-trib.rb 会尽可能保证主从节点不分配在同一机器下,因此会重新排序节点列表顺序。节点列表顺序用于确定主从角色,先主节点之后是从节点。创建过程中首先会给出主从节点角色分配的计划,并且会生成报告

命令说明:

 redis-trib.rb help
 Usage: redis-trib   

创建集群

create          host1:port1 ... hostN:portN  
                --replicas  #带上该参数表示是否有从,arg表示从的数量

检查集群
check host:port

查看集群信息
info host:port

修复集群

fix   host:port
      --timeout   

在线迁移slot

reshard         host:port          #个是必传参数,用来从一个节点获取整个集群信息,相当于获取集群信息的入口
                  --from      #需要从哪些源节点上迁移slot,可从多个源节点完成迁移,以逗号隔开,传递的是节点的node id,还可以直接传递--from all,  这样源节点就是集群的所有节点,不传递该参数的话,则会在迁移过程中提示用户输入
                  --to        #slot需要迁移的目的节点的node id,目的节点只能填写一个,不传递该参数的话,则会在迁移过程中提示用户输入。
                  --slots     #需要迁移的slot数量,不传递该参数的话,则会在迁移过程中提示用户输入。
                  --yes            #设置该参数,可以在打印执行reshard计划的时候,提示用户输入yes确认后再执行reshard
                  --timeout   #设置migrate命令的超时时间。
                  --pipeline  #定义cluster getkeysinslot命令一次取出的key数量,不传的话使用默认值为10。

平衡集群节点slot数量

rebalance       host:port
                  --weight 
                  --auto-weights
                  --use-empty-masters
                  --timeout 
                  --simulate
                  --pipeline 
                  --threshold 
#将新节点加入集群 
add-node        new_host:new_port existing_host:existing_port
                  --slave
                  --master-id 
#从集群中删除节点  
del-node        host:port node_id

#设置集群节点间心跳连接的超时时间
set-timeout     host:port milliseconds

#在集群全部节点上执行命令
call            host:port command arg arg .. arg

#将外部redis数据导入集群
import          host:port
                  --from 
                  --copy
                  --replace

六、Redis-cluster原理

1、节点通信

在分布式存储中需要提供维护节点元数据信息的机制,所谓元数据是指:节点负责哪些数据,是否出现故障等状态信息,Redis 集群采用 Gossip(流言)协议,Gossip 协议工作原理就是节点彼此不断通信交换信息,一段时间后所有的节点都会知道集群完整的信息,这种方式类似流言传播

1) 集群中的每个节点都会单独开辟一个 TCP 通道,用于节点之间彼此通信,通信端口号在基础端口上加10000。     
2)每个节点在固定周期内通过特定规则选择几个节点发送 ping 消息。  
3)接收到 ping 消息的节点用 pong 消息作为响应。  

集群中每个节点通过一定规则挑选要通信的节点,每个节点可能知道全部节点,也可能仅知道部分节点,只要这些节点彼此可以正常通信,最终它们会达到一致的状态。
当节点出故障、新节点加入、主从角色变化、槽信息变更等事件发生时,通过不断的 ping/pong 消息通信,经过一段时间后所有的节点都会知道整个集群全部节点的最新状态,从而达到集群状态同步的目的。

2、集群伸缩

Redis 集群提供了灵活的节点扩容和收缩方案。在不影响集群对外服务的情况下,可以为集群添加节点进行扩容也可以下线部分节点进行缩容。

[图片上传失败...(image-2796aa-1672315959845)]

- 槽和数据与节点的对应关系

当主节点分别维护自己负责的槽和对应的数据,如果希望加入1个节点实现集群扩容时,需要通过相关命令把一部分槽和数据迁移给新节点

[图片上传失败...(image-bf1255-1672315959845)]

上面图里的每个节点把一部分槽和数据迁移到新的节点6385,每个节点负责的槽和数据相比之前变少了从而达到了集群扩容的目的,集群伸缩=槽和数据在节点之间的移动。

- 扩容操作

扩容是分布式存储最常见的需求,Redis 集群扩容操作可分为如下步骤:

1)准备新节点。
2)加入集群。
3)迁移槽和数据。

2.1、准备新节点

需要提前准备好新节点并运行在集群模式下,新节点建议跟集群内的节点配置保持一致,便于管理统一。

容器名称 容器IP地址 映射端口号 服务运行模式
Redis-master4 172.50.0.5 6397-> 6397 master
redis-slave4 172.30.0.5 6398 -> 6398 Slave

2.2、加入集群

通过 redis-trib.rb add-node 127.0.0.1:6385 127.0.0.1:6379 实现节点添加
要加入的节点 集群中的节点

docker run  -itd  --name redis-master4 -v  /usr/docker/redis/config:/config --net redis-cluster_redis-master -e PORT=6397 -p  6397:6397 -p 16397:16397   --ip  172.50.0.5  redis-cluster 

3.迁移槽和数据

加入集群后需要为新节点迁移槽和相关数据,槽在迁移过程中集群可以正常提供读写服务,迁移过程是集群扩容最核心的环节,下面详细讲解。

槽是 Redis 集群管理数据的基本单位,首先需要为新节点制定槽的迁移计划,确定原有节点的哪些槽需要迁移到新节点。迁移计划需要确保每个节点负责相似数量的槽,从而保证各节点的数据均匀,比如之前是三个节点,现在是四个节点,把节点槽分布在四个节点上。

[图片上传失败...(image-2b6fb-1672315959845)]

槽迁移计划确定后开始逐个把槽内数据从源节点迁移到目标节点
[图片上传失败...(image-fc514c-1672315959845)]

数据迁移过程是逐个槽进行的

流程说明:
1)对目标节点发送导入命令,让目标节点准备导入槽的数据。
2)对源节点发送导出命令,让源节点准备迁出槽的数据。
3)源节点循环执行迁移命令,将槽跟数据迁移到目标节点。

[图片上传失败...(image-49e96b-1672315959845)]

redis-trib 提供了槽重分片功能,命令如下:

redis-trib.rb reshard host:port --from --to --slots --yes --timeout --pipeline

参数说明:
·--host:      port:必传参数,集群内任意节点地址,用来获取整个集群信息。
·--from:      制定源节点的 id,如果有多个源节点,使用逗号分隔,如果是all源节点变为集群内所有主节点,在迁移过程中提示用户输入。
·--to:      需要迁移的目标节点的id,目标节点只能填写一个,在迁移过程中提示用户输入。
·--slots:    需要迁移槽的总数量,在迁移过程中提示用户输入。
·--yes:       当打印出 reshard 执行计划时,是否需要用户输入yes确认后再执行 reshard。
·--timeout:   控制每次 migrate 操作的超时时间,默认为60000毫秒。
·--pipeline:  控制每次批量迁移键的数量,默认为10。

1、迁移操作

redis-trib.rb reshard 127.0.0.1:6379

打印出集群每个节点信息后,reshard 命令需要确认迁移的槽数量,这里我们根据节点个数输入对应的值:
How many slots do you want to move (from 1 to 16384)4096
[图片上传失败...(image-1eb907-1672315959845)]

输入的节点 ID 作为目标节点,目标节点只能指定一个:

What is the receiving node ID xxxx

[图片上传失败...(image-ebd71b-1672315959845)]

之后输入源节点的 ID,这里分别输入相应的节点 ID 最后
用 done 表示结束:

数据迁移之前会打印出所有的槽从源节点到目标节点的计划,确认计划无误后输入 yes 执行迁移工作

redis-trib 工具会打印出每个槽迁移的进度:

[图片上传失败...(image-756cb-1672315959845)]

查看节点的信息cluster-node

[图片上传失败...(image-67ce79-1672315959845)]

输入 redis-trib.rb rebalance ip:port .

[图片上传失败...(image-ff4d6-1672315959845)]

2、主从节点设置

扩容之初我们把6385、6386节点加入到集群,节点6385迁移了部分槽和数据作为主节点,但相比其他主节点目前还没有从节点,因此该节点不具备故障转移的能力。

这时需要把节点6386作为6385的从节点,从而保证整个集群的高可用。使用
cluster replicate{masterNodeId} 命令为主节点添加对应从节点

七、收缩集群

收缩集群意味着缩减规模,需要从现有集群中安全下线部分节点,下线节点过程如下
[图片上传失败...(image-e9e4ff-1672315959845)]

1)首先需要确定下线节点是否有负责的槽,如果是,需要把槽迁移到其他节点,保证节点下线后整个集群槽节点映射的完整性。

2)当下线节点不再负责槽或者本身是从节点时,就可以通知集群内其他节点忘记下线节点,当所有的节点忘记该节点后可以正常关闭。

1、下线迁移槽

下线节点需要把自己负责的槽迁移到其他节点,原理与之前节点扩容的迁移槽过程一致,但是过程收缩正好和扩容迁移方向相反,下线节点变为源节点,其他主节点变为目标节点,源节点需要把自身负责的4096个槽均匀地迁移到其他主节点上。

使用 redis-trib.rb reshard 命令完成槽迁移。由于每次执行 reshard 命令只能有一个目标节点,因此需要执行3次 reshard 命令

准备导出

[图片上传失败...(image-d1d14e-1672315959845)]

指定目标节点

直到6397迁移干净,不放在任何节点
[图片上传失败...(image-4e1b3f-1672315959845)]

2、忘记节点

由于集群内的节点不停地通过 Gossip 消息彼此交换节点状态,因此需要通过一种健壮的机制让集群内所有节点忘记下线的节点。也就是说让其他节点不再与要下线节点进行 Gossip 消息交换。Redis 提供了 cluster forget{downNodeId} 命令实现该功能,会把这个节点信息放入黑名单,但是60s之后会恢复。

生产环境当中使用 redis-trib.rb del-node {host:port}{downNodeId} 命令进行相关操作

注意: redis-trib rebalance 命令选择

适用于节点的槽不平衡的状态,有槽的节点

1、默认节点加入,要先做节点槽的迁移  

2、节点已经迁移了所有的槽信息,并且已经从集群删除后,才可以使用平衡

八、客户端操作

我们已经搭建好 Redis 集群并且理解了通信和伸缩细节,但还没有使用客户端去操作集群。Redis 集群对客户端通信协议做了比较大的修改,为了追求性能最大化,并没有采用代理的方式而是采用客户端直连节点的方式

MOVED 重定向

在集群模式下,Redis 接收任何键相关命令时首先计算键对应的槽,再根据槽找出所对应的节点,如果节点是自身,则处理键命令;否则回复 MOVED 重定向错误,通知客户端请求正确的节点。这个过程称为 MOVED 重定向,这个过程之前已经体验过了

[图片上传失败...(image-c42ddc-1672315959845)]

可以直接用 composer require 使用客户端直接操作

常见问题:

移除节点之后因为,被移除节点,还保留节点信息,所以必须先删除之前的配置信息,否则有可能出现如下报错

[图片上传失败...(image-527df1-1672315959845)]

你可能感兴趣的:(redis哨兵+主从的问题 、Redis Cluster集群)