Redis设计与实现第17章 -- 集群 总结1(节点 槽指派)
集群通过分片sharding来进行数据共享,并提供复制和故障转移功能。
17.1 节点
一个Redis集群通常由多个节点node组成,刚开始每个节点都是相互独立的,必须将各个独立的节点连接起来,才能构成一个包含多个节点的集群。通过CLUSTER MEET <ip><port>
命令完成,向一个节点发送该命令,可以让node
节点与ip/port
所指定的节点进行握手handshake
,当握手成功后,node
节点就会将ip/port
所指定的节点添加到节点当前所在的集群中。
17.1.1 启动节点
一个节点就是一个运行在集群模式下的Redis服务器,这个服务器会在启动时根据cluster-enabled
配置选项是否为yes
来决定是否开启服务器的集群模式。
节点会继续使用所有在单机模式中使用的服务器组件。
初次之后,只有集群模式下才会用到的数据,节点保存在了clusterNode/clusterLink/clusterState
结构。
17.1.2 集群数据结构
clusterNode
结构保存了一个节点的当前状态,比如节点的创建时间、名字、配置纪元、IP地址和端口号。每个节点都使用一个clusterNode
结构来记录自己的状态,并且也记录集群里其他节点的作用。
struct clusterNode{//创建节点的时间mstime_t ctime;//节点的名字,由40个十六进制字符组成//例如68eef66df23420a5862208ef5b1a7005b806f2ffchar name[REDIS_CLUSTER_NAMELEN];//节点标识//使用各种不同的标识值记录节点的角色(比如主节点或者从节点),//以及节点目前所处的状态(比如在线或者下线)。int flags;//节点当前的配置纪元,用于实现故障转移uint64 tconfigEpoch;//节点的IP地址Char ip[REDIS_IP_STR_LEN];//节点的端口号int port;//保存连接节点所需的有关信息clusterLink *link;
其中link
结构保存了连接节点所需的有关信息,比如套接字描述符、输入缓冲区和输出缓冲区。
typedef struct clusterLink{//连接的创建时间mstime_t ctime;// TCP 套接字描述符int fd;//输出缓冲区,保存着等待发送给其他节点的消息(message)。sds sndbuf;
//输入缓冲区,保存着从其他节点接收到的消息。sds rcvbuf;//与这个连接相关联的节点,如果没有的话就为NULLstruct clusterNode *node;
}clusterLink;
redisClient结构和clusterLink结构都有自己的套接字描述符和输入、输出缓冲区,这两个结构的区别在于,redisClient结构中的套接字和缓冲区是用于连接客户端的,而clusterLink结构中的套接字和缓冲区则是用于连接节点的。
每个节点都保存一个clusterState结构,记录了在当前的视角下,集群目前所处的状态,例如集群是在线还是下线,包含多少个节点,当前的配置纪元。
typedef struct clusterstate//指向当前节点的指针clusterNode *myself;//集群当前的配置纪元,用于实现故障转移uint64 tcurrentEpoch;//集群当前的状态:是在线还是下线int state;//集群中至少处理着一个槽的节点的数量int size;//集群节点名单(包括myself节点)//字典的键为节点的名字,字典的值为节点对应的clusterNode结构dict *nodes;
}clusterState;
17.1.3 CLUSTER MEET命令的实现
通过向节点A发送CLUSTER MEET命令,客户端可以向接收命令的节点A将另一个节点B添加到节点A当前所在的集群里面。
收到命令的节点A将与节点B进行握手:
-
节点A会为节点B创建一个clusterNode结构,并将该结构添加到自己的clusterState.nodes字典里
-
之后,节点A会根据该命令给出的IP地址和端口号,向节点B发送一条MEET消息
-
如果一切顺利,节点B将接收到节点A发送的MEET消息,节点B会为节点A创建一个clusternode结构,并将该结构添加到自己的clusterState.nodes字典里
-
之后,节点B向节点A发送一条PONG消息
-
节点A收到以后,就知道节点B已经成功接收到了自己发送的MEET消息
-
节点A向节点B返回一条PING消息
-
节点B收到后,握手完成
之后,节点A会将节点B的信息通过Gossip协议传播给集群中其他节点,让其他节点也与节点B握手。
17.2 槽指派
Redis集群通过分片的方式来保存数据库中的键值对:集群的整个数据库被划分为16384个槽slot,数据库的每个键都属于这16384个槽的其中一个,集群中的每个节点可以处理0个或最多16384个槽
当数据库中的16384个槽都有节点在处理时,集群处于上线ok状态;否则,处于下线fail状态。
通过向节点发送CLUSTER ADDSLOTS命令,可以将一个或多个槽指派给节点负责,比如127.0.0.1:7000 > CLUSTER ADDSLOTS 0 1 2 3 4 ……5000
表示把槽0至槽5000指派给节点7000负责。
17.2.1 记录节点的槽指派信息
clusterNode结构的slots属性和numslot属性记录了节点负责处理哪些槽。
struct clusterNode{unsigned char slots[16384/8];int numslots;};
slots
属性是一个二进制数组,这个数组长度是16384/8=2048个字节,共包含16384个二进制位
Redis以0为起始索引,16383为终止索引,对slots数组中的16384个二进制位进行编号,并根据索引i上的二进制位的值来判断节点是否负责处理槽i。如果该位为1,表示负责处理。
因为取出和设置slots数组中的任意一个二进制位的值的复杂度仅为O(1)
,所以检查节点是否负责处理某个槽,或是把某个槽指派给节点负责,复杂度都是O(1)
numslots
属性记录节点负责处理的槽的数量,也就是slots
数组中值为1的二进制位的数量
17.2.2 传播节点的槽指派信息
一个节点除了会将自己负责处理的槽记录在clusterNode结构的slots属性和numslots属性之后,它还会将自己的slots数组通过消息发送给集群里的其他节点,以此来告知其他节点自己目前正在负责处理哪些槽。
当节点A通过消息从节点B那里接收到节点B的slots数组时,节点A会在自己的clusterState.nodes字典中查找节点B对应的clusterNode结构,并对结构中的slots数组进行保存或更新。
这样,集群里的每个节点都会将自己的slots数组通过消息发送给集群中的其他节点,并且每个接收到slots数组的节点都会将数组保存到相应节点的clusterNode结构里面。因此集群里的每个节点都会知道数据库的16384个槽分别被指派给了集群里的哪些节点。
17.2.3 记录集群所有槽的指派信息
clusterState结构的slots数组记录了集群里所有16384个槽的指派信息
typedef struct clusterstate(clusterNode *slots[16384];
}clusterstate;
slots数组包含16384个项,每个数组项都是一个指向clusterNode结构的指针:如果指向NULL,表示尚未指派给任何节点;如果指向一个clusterNode结构,表示槽i已经指派给了clusterNode结构所代表的节点。通过这样的记录方式,程序要检查槽i是否已经被指派,又或者取得负责槽i的节点,只需要访问clusterState.slots[i]的值即可,这个复杂度仅为O(1)
虽然clusterState.slots数组记录了集群中所有槽的指派信息,但是使用clusterNode结构的slots数组来记录单个节点的槽指派信息仍然是有必要的:因为程序需要将某个节点的槽指派信息通过消息发送给其他节点时,程序只需要将相应节点的clusterNode.slots数组整个发送出去就可以了;如果单独使用clusterState.slots数组的话,每次将节点A的槽指派信息传播给其他节点后,需要先遍历整个数组,记录节点A负责处理哪些槽,才能发送,效率低。
clusterState.slots数组记录了集群中所有槽的指派信息,clusterNode结构的slots数组记录clusterNode结构所代表的节点的槽指派信息。
17.2.4 CLUSTER ADDSLOTS命令的实现
CLUSTER ADDSLOTS
命令接受一个或多个槽作为参数,并将所有输入的槽指派给接收该命令的节点负责
def CLUSTER ADDSLOTS(*allinput slots):
#遍历所有输入槽,检查它们是否都是未指派槽
for i in all input slots:
#如果有哪怕一个槽已经被指派给了某个节点
#那么向客户端返回错误,并终止命令执行if clusterState.slots[i]!=NULL:reply error()return
#如果所有输入槽都是未指派槽
#那么再次遍历所有输入槽,将这些槽指派给当前节点
for i in all input slots:
#设置clusterstate结构的slots数组
#将slots[i]的指针指向代表当前节点的clusterNode结构clusterState.slotsi]=clusterState.myself
#访问代表当前节点的clusterNode结构的slots数组
#将数组在索引i上的二进制位设置为1setSlotBit(clusterstate.myself.slots,i)
命令执行完后,节点会通过发送消息告知集群中的其他节点,自己目前正在负责处理哪些槽
相关文章:
Redis设计与实现第17章 -- 集群 总结1(节点 槽指派)
集群通过分片sharding来进行数据共享,并提供复制和故障转移功能。 17.1 节点 一个Redis集群通常由多个节点node组成,刚开始每个节点都是相互独立的,必须将各个独立的节点连接起来,才能构成一个包含多个节点的集群。通过CLUSTER …...

汽车控制软件下载移动管家手机控车一键启动app
移动管家手机控制汽车系统是一款实现车辆远程智能控制的应用程序。通过下载并安装特定的APP,用户可以轻松实现以下功能:远程启动与熄火:无论身处何地,只要有网络,即可远程启动或熄火车辆,提前预冷或预…...
推荐几个可以免费下载网站模板的资源站
推荐几个可以免费下载网站模板的资源站,上面有免费的wordpress模板和帝国CMS模板可以下载。 模板帝 Mobandi.com 模板帝是一个提供丰富网站模板资源的平台,旨在帮助用户快速构建和美化自己的网站。无论是个人博客、企业官网还是电子商务平台ÿ…...

H3C OSPF实验
实验拓扑 实验需求 按照图示配置 IP 地址按照图示分区域配置 OSPF ,实现全网互通为了路由结构稳定,要求路由器使用环回口作为 Router-id,ABR 的环回口宣告进骨干区域 实验解法 一、配置IP地址 [R1]int l0 [R1-LoopBack0]ip add 1.1.1.1 32 […...

Vue框架开发一个简单的购物车(Vue.js)
让我们利用所学知识来开发一个简单的购物车 (记得暴露属性和方法!!!) 首先来看一下最基本的一个html框架 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"&…...
Windows Terminal Solarized Dark 配色方案调整
起因 Widnows 10/11 下面自带的 Terminal 还是比较方便的,因为不需要安装额外的 Terminal 软件。 我喜欢 Solarized Dark 配色方案,虽然有人批评这个配色方案比较老,但我觉得它比较优雅,尤其对外这种眼神比较差的人,比…...
PyTorch张量运算与自动微分
PyTorch张量运算与自动微分 PyTorch由Facebook人工智能研究院于2017年推出,具有强大的GPU加速张量计算功能,并且能够自动进行微分计算,从而可以使用基于梯度的方法对模型参数进行优化,大部分研究人员、公司机构、数据比赛都使用P…...

【从零开始的LeetCode-算法】3264. K 次乘运算后的最终数组 I
给你一个整数数组 nums ,一个整数 k 和一个整数 multiplier 。 你需要对 nums 执行 k 次操作,每次操作中: 找到 nums 中的 最小 值 x ,如果存在多个最小值,选择最 前面 的一个。将 x 替换为 x * multiplier 。 请你…...

【Linux】gdb / cgdb 调试 + 进度条
🌻个人主页:路飞雪吖~ 🌠专栏:Linux 目录 一、Linux调试器-gdb 🌟开始使用 🌠小贴士: 🌟gdb指令 🌠小贴士: ✨watch 监视 ✨打条件断点 二、小程序----进…...

Jenkins Nginx Vue项目自动化部署
目录 一、环境准备 1.1 Jenkins搭建 1.2 NVM和Nodejs安装 1.3 Nginx安装 二、Jenkins配置 2.1 相关插件安装 2.2 全局工具安装 2.3 环境变量配置 2.4 邮箱配置(构建后发送邮件) 2.5 任务配置 三、Nginx配置 3.1 配置路由转发 四、部署项目 …...

视频汇聚平台Liveweb国标GB28181视频平台监控中心设计
在现代安防视频监控领域,Liveweb视频汇聚平台以其卓越的兼容性和灵活的拓展能力,为用户提供了一套全面的解决方案。该平台不仅能够实现视频的远程监控、录像、存储与回放等基础功能,还涵盖了视频转码、视频快照、告警、云台控制、语音对讲以及…...

文件比较和文件流
文件比较和文件流 一、文本比较工具 diff1.基本用法1.1输出格式 2.常用选项 二、文件流1.文件的打开模式2.文件流的分类ifstreamofstreamfstrem区别 3.文件流的函数1. 构造函数2. is_open 用于判断文件是否打开3. open4. getline5. close6. get()7. read8. write9. put10. gcou…...

【2024最新】基于Springboot+Vue的就业信息管理系统Lw+PPT
作者:计算机搬砖家 开发技术:SpringBoot、php、Python、小程序、SSM、Vue、MySQL、JSP、ElementUI等,“文末源码”。 专栏推荐:SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:Java精选实战项…...

PySide6 QSS(Qt Style Sheets) Reference: PySide6 QSS参考指南
Qt官网参考资料: QSS介绍: Styling the Widgets Application - Qt for Pythonhttps://doc.qt.io/qtforpython-6/tutorials/basictutorial/widgetstyling.html#tutorial-widgetstyling QSS 参考手册: Qt Style Sheets Reference | Qt Widge…...
【笔记】成为雍正
观古代历史,不过帝王一家一姓之家史 时间 1662年,田文镜出生。1672年,张廷玉出生。1674年,胤礽出生。1678年,胤禛出生。1679年,年羹尧出生。1680年,鄂尔泰出生。1700年,索额图被赐死…...

Codeforces Round 913 (Div. 3)
题目链接 B. YetnotherrokenKeoard 题意 输入 输出 思路 用两个栈分别维护小写字母下标和大写字母下标,用一个vis数组标记字母是否删除 示例代码 void solve() {string s;cin >> s;int n s.size();vector<bool> vis(n, false);stack<int>sk…...
斐波那契数
C语言实现斐波那契数列的多种方法_斐波那契数列c语言-CSDN博客 题目描述 斐波那契数列为:1,1,2,3,5,8,13.....,常规递推公式f(n)f(n-1)f(n-2); 输入描述 输入一个整数n(0<n<50),为多组数据。 输出描述 输出第n个斐波那契数 样例输入 1 2 4样例输出…...

Redis高阶集群搭建+集群读写
问题 容量不够,redis 如何进行扩容?并发写操作, redis 如何分摊?另外,主从模式,薪火相传模式,主机宕机,导致 ip 地址发生变化,应用程序中配置需要修改对应的主机地址、端…...

Vision Transformer(vit)的主干
图解: 代码: class VisionTransformer(nn.Module):def __init__(self, img_size224, patch_size16, in_c3, num_classes1000,embed_dim768, depth12, num_heads12, mlp_ratio4.0, qkv_biasTrue,qk_scaleNone, representation_sizeNone, distilledFalse,…...

手撸了一个文件传输工具
在日常的开发与运维中,文件传输工具是不可或缺的利器。无论是跨服务器传递配置文件,还是快速从一台机器下载日志文件,一个高效、可靠且简单的文件传输工具能够显著提高工作效率。今天,我想分享我自己手撸一个文件传输工具的全过程…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...

用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...