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,…...
手撸了一个文件传输工具
在日常的开发与运维中,文件传输工具是不可或缺的利器。无论是跨服务器传递配置文件,还是快速从一台机器下载日志文件,一个高效、可靠且简单的文件传输工具能够显著提高工作效率。今天,我想分享我自己手撸一个文件传输工具的全过程…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
