Redis集群详述(从服务内部讲解,彻底搞懂Redis集群)
1.简介Redis Cluster是Redis提供的分布式数据库解决方案。
排队。
没有合并操作(多个节点没有相同的key),因此在大数据值中可以表现良好,这在Redis数据模型中很常见。
写安全,系统尝试保存连接到大多数节点的客户端执行的所有写操作。
但是Redis并不能保证数据永远不会丢失。
可用性,如果主节点不可用,从节点可以替代主节点。
如果你没有学习Redis集群的经验,建议阅读这三篇文章(中文系列):
Redis集群教程
https:// /redis.cn/topics/cluster-tutorial.html
Redis集群规范
https://redis.cn/topic cs/cluster-spec.html
Redis3 Master 3 Slave模拟集群 部署
https://blog.csdn.net/qq_41125219/post/details/118686281
以下基于下图中的三主三从结构:-
资源列表:
节点IP槽位范围 主[0]192.168.211.107:6319Slots0-5460主[1] 192.168.211.107:6329Slots5461-10922主[2]192.168.211.107:6339Slots10923-16 383 从机[0]192.168.211.107:6369从机[1]192.168.211.107:6349从机[2]192.168.211。107:6359
Redis集群没有使用一致性哈希,而是引入了哈希槽的概念。
一个Redis集群有16384个哈希槽。
集群中的每个节点负责哈希槽,例如上面数据列表中的集群有3个节点,集群分配如下:
节点master[0]包含哈希。
槽位 0 到 5460
Nodemaster[1] 包含哈希槽 5461 到 10922
Nodemaster[2] 包含哈希槽 10923 到 16383
在详细了解Redis集群之前,需要了解Redis的内部结构。
例如,在集群中。
当Redis服务节点通过设置cluster_enabled为yes开启集群模式时,Redis服务节点不仅继续独立使用服务器组件,而且还会添加custerState、clusterNode、custerLink等结构体来存储异常。
集群模式下的数据。
clsuterNode用于存储节点名称等节点信息。
IP地址、端口信息、配置时间等,下面代码列出了一些最重要的属性:
red IS_NODE_SLAVE (从节点) // 状态 -> 在线或离线 eg: REDIS_NODE_PFAIL (疑似离线) REDIS_NODE_FAIL (离线) flags; // 节点配置epoch,用于故障转移,用于sentinel集群 class64_tconfigEpoch 表示配置epoch的集群状态; // 节点端口 inport; // 节点信息2048字节二进制位数组 //位数组 索引值可以是 0 或 1 // 数组索引 i 的槽值为 0,这意味着节点槽 i // 不负责处理。
数组索引i槽值1,委托节点负责处理 iunsignedcharslots[163] 84/8];//记录当前节点处理槽数的总和 intnumslots;//如果当前节点是从节点// 当前从节点的structclusterNode* Slaveof // 指向主节点。
if 当前节点为主节点 // 乘以当前主节点的从节点数量 intnumslaves; // 数组——记录所有与当前主节点重复的从节点 structclusterNode** Slaves;}clsuterNode;
上面代码中可能不太好理解的是空格[16384/8]数组即可。
理解为16384。
如果数组索引为1,则表示当前槽是当前簇的节点,如果为0,则表示不是当前簇。
节点集群节点可以识别当前节点负责处理的时间间隔。
没有间隙的集群中的第一个 klsuterNode 或 clsuterNode 间隙如下:
思考。
在我上面给出的资源列表中,集群是代表Master[0]的簇节点空间如下:
clusterLink是csuterNode中的一个属性,是连接节点所必需的as 套接字用于存储相关数据,如描述符、输入和输出缓冲区等。
下面的代码列出了一些最重要的属性:
每个节点都有一个custerState结构体,里面包含了集群当前的状态,集群中所有节点的信息(master node,slave 它存储所有数据(如节点)等。
等等,下面的代码列出了一些非常有用的属性:
slot数组以klsuterNode分隔,集群rNode中的slot数组记录了当前集群节点负责的slot,集群状态中的slot记录了整个集群中每个slot负责的集群节点。
集群状态下集群节点负责的槽位。
如图所示,数据列表中显示了集群状态中的槽位以及集群节点中的槽位数组:
Redis 集群中之所以使用两个槽数组,是出于性能考虑:
当我们找出整个集群中某个集群节点负责哪些槽时,我们只需需要查询。
clusterState 中的槽数组。
的如果没有 clusterState slot 数组,则必须遍历所有集群节点配置,这显然很慢。
此外,集群节点中的 slot 数组很重要,因为集群中的任何节点都需要支持每个节点的配置。
其他。
它是一个负责的槽,此时节点之间只需要将集群节点中槽的数组结构传递给彼此即可。
虽然第二个需要关注的结构是节点字典,但是所有集群节点除了主节点和从节点之外,都存储在节点字典中,所以我们也需要关注它。
第三个结构体要仔细理解从[16384]数组和transfer_slots_to[16384]这两个数组应该用到的,我们稍后再讲。
3. 集群工作 3.1 如何分配槽位? Redis集群总共有16384个槽,参见上面的三主三从部署流程,集群本身已经给我们分配了槽,但是如果我们要自己分配槽,我们该如何调整呢?
要为当前节点分配一个或多个槽位,我们可以向该节点发送以下命令:
CLUSTERADDSLOTS
例如我们要分配插槽。
将 0 和 1 分配给 master[0] 后,我们只需向 master[0] 节点发送以下命令:
CLUSTERADDSLOTS 01
分配节点槽位时,集群节点槽数组将被更新。
当其他节点收到消息时,对应于 clusterNode 和集群状态的节点数组会被更新。
3.2 ADDSLOTS在Redis集群中是如何实现的? 这其实是比较容易的。
当向 Redis 集群中的节点发送 CLUSTERADDSLOTS 时,它首先通过集群状态中的槽数组检查当前节点是否没有分配给其他节点。
如果指定,则会自动引发异常并将错误返回给指定的客户端。
如果分配给当前节点的所有槽位都没有分配给其他节点,则当前节点将这些槽位分配给自己。
分配主要分为三个步骤:
更新集群状态空间,并将指定的槽[i]指向当前集群节点
集群节点
更新集群节点数组和集合指定槽位置的值[i]更新为1 > 向集群中的其他节点发送消息,向其他节点发送集群节点槽。集群中有很多节点,客户端如何知道要查询哪个节点?
在理解这个问题之前,首先需要了解一点:Redis集群是如何计算出自己拥有哪个解锁密钥的? 根据官网介绍,Redis实际上并没有使用一致性哈希算法,而是将每个请求的key都用CRC16标记,然后对16384进行模来确定将其存储在哪个槽中。
HASH_SLOT=CRC16(key) mod16384
当客户端连接向节点发送请求时,接收命令的节点首先通过 集群状态计算后的一种算法,节点响应客户端的请求。
如果它不负责当前节点,则经历以下过程。
后续步骤:
节点向客户端返回 MOVED 路由错误 在 MOVED 路由错误中,计算出的实际持有密钥的集群节点的 IP 和端口将返回给客户端。
当客户端收到节点返回的MOVED路由错误时,它会根据集群服务器和客户端的IP和端口将命令转发到正确的节点。
这个问题其实涵盖了很多问题,比如Redis集群中删除特定节点、添加节点等。
可以通过将哈希槽从一个节点移动到另一个节点来概括。
而Redis集群最好的一点就是支持在线(连续)分配,官方称之为集群在线重新配置(live reconfiguration)。
在实现之前,一旦您了解了 CLUSTER 指令,您就可以将它们设置为:
CLUSTERADDSLOTSslot1[slot2] [slotN]
CLUSTERDELSLOTSslot1 [slot2] [slotN] ]
CLUSTERSETSLOTslotNODEnode
CLUSTERSETSLOTslotMIGRATINGnode
CLUSTERSETSLOTslotIMPORTING node
slot对集群的分类主要包括以上,仅在进行快速分类时使用。
CLUSTERSETSLOTslotNODENode 还用于自动将插槽分配给特定节点。
如果形成一个簇,通常是最后两个我们使用重新分配,其含义如下:
当一个槽被设置为迁移时,原来包含该哈希槽的节点仍然会接收到所有槽。
与此哈希槽匹配的请求,但仅当请求的密钥仍然存在于原始节点上时,才会由原始节点处理,否则请求将通过 -ASK 重定向(-ASKredirection)转发到迁移的目标节点。
当一个槽设置为导入时,节点在收到ASKING命令后接受所有查询该哈希槽的请求。
如果客户端发送查询命令,查询将被转发到正确处理此哈希槽的节点,并带有 -MOVED 重定向错误。
Redis-trib(集群管理软件redis-trib会负责Redis集群的槽位分配),发送CLUSTERSETSLOTslotIMPORTINGnode命令到目标节点(输入槽位节点),导入目标节点。
输入由源节点(输入输出节点)排列。
redis-trib 然后向源节点发送 CLUSTERGETSLOTslotMIGRATINGnode 命令,源节点准备 slot 导出
redis-trib 在源节点接收到该命令后,再发出 CLUSTERGETKEYSINSLOTslotc 命令slot 命令返回键,以及键的最大数量 返回
redis-trib向源节点发送MIGRATEipportkey0timeout命令,以便在源节点返回key的情况下将源节点返回的key迁移到目标节点。
迁移完成后,redis-trib会向节点发送CLUSTERSETSLOTslotNODEnode命令。
通过消息传递槽位分配信息,至此集群槽位迁移完成,集群中的其他节点也更新为新的槽位分配信息。
你太棒了,你总是想到这种交流,你太棒了! 成年人!
当我们谈论集群状态结构时,这个问题已经被官方解决了。
要解决此问题,请使用places_from_import_and_to_migration。
node clusterNode *migrate_slots_to[16384];// }clusterState;
导出节点槽时,将集群状态中排序的migrate_slots_share对应的订阅设置为对应的集群节点,此集群节点指向到 。
导入节点。
当节点导入一个slot时,clusterState中import_slots_share对应的订阅会被设置为对应的clusterNode。
通过上面两个常见的数组,我们是否可以判断当前槽位是否正在迁移,以及从哪里迁移到哪里? 我们对事情如此简单并不感到惊讶
此时,让我们回到问题,如果客户端请求的密钥位于正在迁移的槽中。
那么接收到命令的节点会首先尝试在自己的数据库中查找key,如果slot还没有被发明,并且当前key还没有被迁移,那么就可以直接响应客户端的请求。
如果key不再存在,则节点查询migration_slots_to数组对应的索引槽。
此时节点不会继续处理指令,而是返回ASKING命令。
客户端收到ASKING命令后,必须将请求定向到正确的节点,但是这里有一点需要注意(所以我在这里放了一个表情,以供读者注意)。
前面提到,一个节点在判断当前槽不是自己的进程时,会返回MOVED指令,那么它应该怎么做插槽何时迁移? 这就是 Redis 集群的意义所在。
当节点检测到槽位正在迁移时,客户端会收到ASKING命令,其中包含节点的IP和集群节点端口。
他们逃跑了。
然后客户端主页向迁移集群节点发送请求命令。
所以如果Redis没有收到查询命令,就会直接查询节点集群。
rState,并且正在迁移的slot还没有更新为clusterState,那么只能返回MOVED,会继续移动很多次 ,ASKING命令接收节点会强制执行一次该请求(只执行一次,下次需要再次发送ASKING命令)。
当然,前提是对于Redis集群中的每个主节点,我们都已经设置好了从节点,否则就没用了……大致步骤如下:
在一个典型的工作中集群中,每个节点向其他节点发送ping命令,正常情况下发送节点收到命令的节点集群节点标志设置为REDIS_NODE_PFAIL,但离线 他们是嫌疑人。
集群节点通过发送集群中各节点的状态信息消息来通知其他节点
如果集群中超过一半的主节点负责处理槽。
如果某个特定的主节点被配置为怀疑其离线,则该节点将被标记为离线,并且该节点将设置集群节点标志并指示它是接收到 REDIS_NODE_FAIL 命令的集群。
已经完成了,是时候继续前进了。
>
下线的主节点选择从节点作为最新的主节点,并将选定的节点执行到SLAVEOFnoone成为新的主节点
新的主节点成为删除的删除原来的主节点插入工作并替换它。
这些槽是自己修改的,即修改集群节点结构和集群状态结构。
新的主节点将PONG指令转发给集群生成并更新集群节点结构和集群状态结构
如果新的主节点 A 向其余主节点发送新的 SLAVEOF 指令,则该节点将成为自己的主节点。
从节点
最后新增的主节点负责主主节点的响应工作
这里如果需要深究细节的话我写的很模糊,阅读这篇文章你应该:
https://redis.cn/topics/cluster-spec.html
或者你可以阅读《Redis设计与实现》这本优秀书籍。
黄建红撰。
我也提到了很多。
K8S部署Redis Cluster集群(三主三从模式) - 部署笔记
在 Kubernetes 上部署 RedisCluster 集群(3主3从模式)-实用步骤
Redis因其快速的读取、写入和集群能力而被广泛应用为一种高效的数据结构存储系统。
要在 Kubernetes 上部署 RedisCluster 集群,您需要了解集群的工作原理以及 StatefulSet 控制器的顺序部署策略。
StatefulSets允许您根据实例数量启动节点,并且每个实例的数据都存储在持久卷(PV)中以确保数据一致性。
要动态创建NFS作为存储卷,首先必须在NFS服务器上创建共享目录并配置相应的RBAC和StorageClass。
1. 配置动态持久存储。
在NFS服务器上创建共享目录,并创建NFS客户端配置器来管理PV和PVC。
接下来,使用redis-trib.rb工具构建镜像,并通过configmap将其配置挂载到StatefulSet中。
2. 部署RedisCluster。
创建StatefulSet,定义volumeClaimTemplates,并保证每个节点都有对应的存储卷。
使用 kubectl 命令行运行 redis-trib.rb 工具,指定前三个节点为主节点,后三个节点为从节点。
3.初始化集群后,可以使用kubectl查看各个节点的角色,并与其从节点redis-cluster-3建立连接。
。
同样,redis-cluster-1和redis-cluster-4以及redis-cluster-2和redis-cluster-5也有这种关系。
4.验证部署:验证集群节点之间通信是否成功。
您可以使用命令行工具对集群进行基本操作,例如读写数据,并检查集群是否正常运行。
已确立的。
redis部署模式
重现部署模式?
Redis有三种部署模式:独立模式、主复制模式和集群模式:
1独立模式:Redis作为单个进程运行,所有数据都存储在内存中,您可以通过配置持久化选项实现数据持久化。
2 主从复制模式:Redis实例可以分为主节点和从节点。
达到读写鸿沟。
3集群模式:多个Redis节点可以组成一个集群,实现分布式存储和负载均衡。
Redis集群可以分为两种类型:分片集群和复制集群。
选择适合您需求的Redis部署模式,提高Redis性能和可用性。
如何在docker中部署多个独立的redis?
在Docker中部署多个独立的Redis集群,具体步骤如下: 首先创建自定义的网络地图,如: 例如Redis,并保证Redis集群运行在隔离的网段上,实现网络隔离。其次,使用shell脚本批量生成6个Redis配置文件,为集群部署做准备。
然后编写shell脚本启动6个Redis容器,保证集群中各个节点的正常运行。
验证六个容器是否成功启动并验证集群部署的初始完成情况。
接下来,进入Redis容器,创建集群,并确保集群配置正确。
成功创建集群后,使用 -c 参数连接到 Redis 集群,以确保您连接到集群而不是单个实例。
进行高可用测试,将键值对插入集群,检查存储分布的平衡性。
使用日志确认数据已成功添加到集群。
停止集群中的一个Redis实例,测试集群的容错能力。
使用keys*命令确认数据仍然可用,并通过从节点读取来验证集群部署的高可用性。
通过以上步骤,您就可以在Docker中部署并测试Redis集群,保证集群的高可用和负载均衡能力。