Redis系列(六):Redis集群模式(redis-cli集群模式)
mhr18 2024-11-15 22:09 21 浏览 0 评论
前言
集群,即Redis Cluster,是Redis3.0开始引入的分布式存储方案。集群是由多个节点(Node)组成,Redis的数据分布在这些节点中。集群中的节点分为主节点和从节点;只有主节点负责读写请求和集群信息的维护,从节点只进行主节点数据和状态信息的复制。
上图是Redis Cluster典型的架构图,集群中的每一个Redis节点都是互相连通的,客户端任意直连到集群中的任意一个节点,就可以对其他Redis节点进行读写操作。
集群的作用
集群的作用,主要可以归纳为以下两点:
- 数据分区:又称为数据分片,是集群最核心的功能!集群将数据分散到多个节点,一方面突破了Redis单机内存大小限制【单机内存大小受限制问题:如果单机内存太大,bgsave和bgrewriteaof的fork操作可能导致主线程阻塞,主从环境下主机切换时可能导致从节点长时间无法提供服务,全量复制阶段主节点的复制缓冲区可能溢出,等等】,存储容量大大增加;另一方面每个主节点都可以对外提供读服务和写服务,大大提高了集群的响应能力。
- 高可用:集群支持主从复制和主节点的自动故障转移,当任一节点发生故障时,集群仍然可以对外提供服务。
集群的基本原理
Redis集群中内置了16384个哈希槽。当客户端连接到Redis集群之后,会同时得到一份关于这个集群的配置信息,当客户端具体对某一个key值进行操作时,会计算出它的一个Hash值,然后把结果对16384求余数,这样每个key都会对应一个编号在0~16383之间的哈希槽,Redis会根据节点数量大致均等的将哈希槽映射到不同的节点。
【注】:这里仅对Redis Cluster的原理做一个简单的了解,接下来我们将从3个方面详细介绍,主要包括:数据的分区方案、通信机制、数据结构。
- 集群的分区方式
数据分区有顺序分区、哈希分区等,其中哈希分区由于其天然的随机性,使用比较广泛。集群的分区方案便是哈希分区的一种。我们知道衡量数据分区方法好坏的标准最主要的是:① 数据分布是否均匀;② 增减节点对数据分布的影响。
(1)方案一:哈希值 % 节点数
最容易想到的方案:哈希取余分区,计算key的hash值,然后对节点数量进行取余运算,从而决定数据映射到那个节点上。弊端:当新增或者删减节点时,节点数量发生变化,系统中所有的数据都需要重新计算映射关系,引发大规模的数据迁移。
(2)方案二:一致哈希算法分区
一致性哈希算法将整个哈希值空间组织成一个虚拟的圆环,范围是[0 - 2^32-1],对于每一个数据,根据key计算hash值,确定数据在环上的位置,然后从此位置沿顺时针,找到第一台Redis服务器就是其映射到的服务器。与哈希取余分区相比,一致性哈希分区将增减节点的影响限制在相邻的节点。
弊端:当节点数量较少时,增加或删减节点,对单个节点的影响可能很大,造成数据的严重不平衡。
(3)方案三:带有虚拟节点的一致性哈希分区
该方案是在一致性哈希分区基础上,引入虚拟节点的概念。Redis集群使用的便是这个方案,其中虚拟节点称为槽(slot)。槽是介于数据和实际节点之间的虚拟概念,每个实际节点包含一定数量的槽,每个槽包含哈希值在一定范围内的数据。数据的映射关系由数据hash到实际节点变成了数据hash到槽再到实际节点。
在使用了槽的一致性哈希分区中,槽是数据管理和迁移的基本单位。槽解耦了数据和实际节点之间的关系,增加和删减节点对系统的影响很小。在Redis集群,槽的数量是16384个。
上图总结了Redis集群将数据映射到实际节点的过程:
Step1:Redis对数据的特征值[一般是key]计算哈希值,使用的算法是CRC16;
Step2:根据哈希值,计算数据属于哪个槽slot;
Step3:根据槽和节点的映射关系,计算数据属于哪个节点。
- 节点通信机制
集群作为一个整体工作,是离不开节点之间的通信的。
- 两个端口
在哨兵机制中,节点分为数据节点和哨兵节点:数据节点存储数据,哨兵节点实现额外的控制功能。在集群中,是没有数据节点和哨兵节点之分的,所有的节点都是存储数据,也都参与集群状态的维护。为此,集群中的每个节点都提供另外两个TCP端口:
① 普通端口:主要用于为客户端提供服务(与单机节点类似),在节点间数据迁移时也会使用该端口;
② 集群端口:端口号是普通端口+10000(10000是固定值,无法改变)。集群端口只用于节点之间的通信,比如:搭建集群、增减节点、故障转移等操作时节点之间的通信
【注】:要特别注意两点:① 不要使用客户端连接集群端口;② 为了保证集群可以正常工作,在配置防火墙时,要同时开启普通端口和集群端口。
- Gossip协议
节点之间通信,按照通信协议可以分为几种类型:单对单、广播、Gossip协议等。
广播是指向集群内所有节点发送消息;优点:集群的收敛速度快(集群收敛是指集群内所有节点获得集群信息是一致的);缺点:每条消息都要发送给所有的节点,CUP、宽带等消耗都比较大。
Gossip协议:在节点数量有限的网络中,每个节点都“随机”的与部分节点通信(并不是真正的随机,而是根据特定的规则选择通信的节点);经过通信,每个节点的状态很快达到一致。优点:负载低、去中心化、容错性高(因为通信有冗余)等;缺点:集群的收敛速度慢。
- 消息类型
集群中的节点采用固定频率(每秒10次)的定时任务进行通信工作:判断是否需要发送消息及消息类型、确定接收节点、发送消息等。如果集群状态发生了改变,比如:增减节点、槽状态变更,通过节点之间的通信,所有节点会很快得知整个集群的状态,是集群收敛。
点之间发送的消息主要分为五种:MEET消息、PING消息、PONG消息、FAIL消息、PUBLISH消息。不同的消息类型,通信协议、发送的频率和时机、接收节点的选择等是不同的。
① MEET消息:在节点握手阶段,当节点收到客户端的CLUSTER MEET命令时,会向新加入的节点发送MEET消息,请求新节点加入到当前集群;新节点收到MEET消息后会回复一个PONG消息;
② PING消息:集群中每个节点每秒钟会选择部分节点发送PING消息,接收者收到消息后会回复一个PONG消息。PING消息的内容是自身节点和部分其他节点的状态信息,作用是彼此交换信息,以检测节点是否在线。PING消息使用Gossip协议发送,接收节点的选择兼顾了收敛速度和带宽成本,具体规则:一、随机找5个节点,在其中选择最久没有通信的1个节点 ;二、扫描节点列表,选择最近一次收到PONG消息时间大于cluster_node_timeout / 2 的所有节点,防止这些节点长时间未更新;
③ PONG消息:PONG消息封装了自身状态数据。可以分为两种:一、在接收到MEET/PING消息后回复的POGN消息; 二、节点向集群广播PONG消息,这样其他节点可以获知该节点的最新信息,比如:故障恢复后新的节点会广播PONG消息;
④ FAIL消息:当一个主节点判断另一个主节点进入FAIL状态时,会向集群广播这一FAIL消息;接收节点会将这一FAIL消息保存起来,便于后续的判断;
⑤ PUBLISH消息:节点接收到PUBLISH命令后,会执行该命令,然后向集群广播这一消息,接收节点也会执行PUBLISH命令。
- 数据结构
节点需要专门的数据结构来存储集群的状态。这里所谓集群的状态,是一个宽泛的概念,包括:集群是否处于上线状态、集群中有哪些节点、节点是否可达、节点的主从状态、槽的分布等等。
节点为了存储集群状态而提供的数据结构中,最关键的是clusterNode和clusterState结构:前者记录了一个节点的状态,后者记录了集群作为一个整体的状态。
① clusterNode结构
clusterNode结构保存了一个节点的当前状态,包括创建时间、节点id、ip和端口号等。每个节点都会用一个clusterNode结构记录自己的状态,并为集群内所有其他节点都创建一个clusterNode结构来记录节点状态。
typedef struct clusterNode {
// 节点创建时间
mstime_t ctime;
// 节点id
char name[REDIS_CLUSTER_NAMELEN];
// 节点的ip和端口号
char ip[REDIS_IP_STR_LEN];
int port;
// 节点标识:整型,每个bit都代表了不同状态,如节点的主从状态、是否在线、是否在握手等
int flags;
// 配置纪元:故障转移时起作用,类似于哨兵的配置纪元
uint64_t configEpoch;
/*
* 槽在该节点中的分布:占用16384/8个字节,16384个比特;
* 每个比特对应一个槽:比特值为1,则该比特对应的槽在节点中;
* 比特值为0,则该比特对应的槽不在节点中
*/
unsigned char slots[16384/8];
//节点中槽的数量
int numslots;
…
}clusterNode;
【注】:除了上述字段,clusterNode结构还包含节点连接、主从复制、故障发现和转移需要的信息等。
② clusterState结构
clusterState结构保存了在当前节点视角下,集群所处的状态。主要字段包括:
typedef struct clusterState {
// 自身节点
clusterNode *myself;
// 配置纪元
uint64_t currentEpoch;
// 集群状态:在线还是下线
int state;
// 集群中至少包含一个槽的节点数量
int size;
//哈希表,节点名称 -> clusterNode节点指针
dict *nodes;
//槽分布信息:数组的每个元素都是一个指向clusterNode结构的指针;如果槽还没有分配给任何节点,则为NULL
clusterNode *slots[16384];
… } clusterState;
【注】:除了上述字段,clusterState结构还包括故障转移、槽迁移等需要的信息。
往期精彩文章
Redis系列:
Redis系列(三):Redis持久化机制(RDB & AOF)
MySQL系列:
相关推荐
- Java培训机构,你选对了吗?(java培训机构官网)
-
如今IT行业发展迅速,不仅是大学生,甚至有些在职的员工都想学习java开发,需求量的扩大,薪资必定增长,这也是更多人选择java开发的主要原因。不过对于没有基础的学员来说,java技术不是一两天就能...
- 产品经理MacBook软件清单-20个实用软件
-
三年前开始使用MacBookPro,从此再也不想用Windows电脑了,作为生产工具,MacBook可以说是非常胜任。作为产品经理,值得拥有一台MacBook。MacBook是工作平台,要发挥更大作...
- RAD Studio(Delphi) 本月隆重推出新的版本12.3
-
#在头条记录我的2025#自2024年9月,推出Delphi12.2版本后,本月隆重推出新的版本12.3,RADStudio12.3,包含了Delphi12.3和C++builder12.3最...
- 图解Java垃圾回收机制,写得非常好
-
什么是自动垃圾回收?自动垃圾回收是一种在堆内存中找出哪些对象在被使用,还有哪些对象没被使用,并且将后者删掉的机制。所谓使用中的对象(已引用对象),指的是程序中有指针指向的对象;而未使用中的对象(未引用...
- Centos7 初始化硬盘分区、挂载(针对2T以上)添加磁盘到卷
-
1、通过命令fdisk-l查看硬盘信息:#fdisk-l,发现硬盘为/dev/sdb大小4T。2、如果此硬盘以前有过分区,则先对磁盘格式化。命令:mkfs.文件系统格式-f/dev/sdb...
- 半虚拟化如何提高服务器性能(虚拟化 半虚拟化)
-
半虚拟化是一种重新编译客户机操作系统(OS)将其安装在虚拟机(VM)上的一种虚拟化类型,并在主机操作系统(OS)运行的管理程序上运行。与传统的完全虚拟化相比,半虚拟化可以减少开销,并提高系统性能。虚...
- HashMap底层实现原理以及线程安全实现
-
HashMap底层实现原理数据结构:HashMap的底层实现原理主要依赖于数组+链表+红黑树的结构。1、数组:HashMap最底层是一个数组,称为table,它存放着键值对。2、链...
- long和double类型操作的非原子性探究
-
前言“深入java虚拟机”中提到,int等不大于32位的基本类型的操作都是原子操作,但是某些jvm对long和double类型的操作并不是原子操作,这样就会造成错误数据的出现。其实这里的某些jvm是指...
- 数据库DELETE 语句,还保存原有的磁盘空间
-
MySQL和Oracle的DELETE语句与数据存储MySQL的DELETE操作当你在MySQL中执行DELETE语句时:逻辑删除:数据从表中标记为删除,不再可见于查询结果物理...
- 线程池—ThreadPoolExecutor详解(线程池实战)
-
一、ThreadPoolExecutor简介在juc-executors框架概述的章节中,我们已经简要介绍过ThreadPoolExecutor了,通过Executors工厂,用户可以创建自己需要的执...
- navicat如何使用orcale(详细步骤)
-
前言:看过我昨天文章的同鞋都知道最近接手另一个国企项目,数据库用的是orcale。实话实说,也有快三年没用过orcale数据库了。这期间问题不断,因为orcale日渐消沉,网上资料也是真真假假,难辨虚...
- 你的程序是不是慢吞吞?GraalVM来帮你飞起来性能提升秘籍大公开
-
各位IT圈内外的朋友们,大家好!我是你们的老朋友,头条上的IT技术博主。不知道你们有没有这样的经历:打开一个软件,半天没反应;点开一个网站,图片刷不出来;或者玩个游戏,卡顿得想砸电脑?是不是特别上火?...
- 大数据正当时,理解这几个术语很重要
-
目前,大数据的流行程度远超于我们的想象,无论是在云计算、物联网还是在人工智能领域都离不开大数据的支撑。那么大数据领域里有哪些基本概念或技术术语呢?今天我们就来聊聊那些避不开的大数据技术术语,梳理并...
- 秒懂列式数据库和行式数据库(列式数据库的特点)
-
行式数据库(Row-Based)数据按行存储,常见的行式数据库有Mysql,DB2,Oracle,Sql-server等;列数据库(Column-Based)数据存储方式按列存储,常见的列数据库有Hb...
- AMD发布ROCm 6.4更新:带来了多项底层改进,但仍不支持RDNA 4
-
AMD宣布,对ROCm软件栈进行了更新,推出了新的迭代版本ROCm6.4。这一新版本里,AMD带来了多项底层改进,包括更新改进了ROCm的用户空间库和AMDKFD内核驱动程序之间的兼容性,使其更容易...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (74)
- oracle批量插入数据 (65)
- oracle事务隔离级别 (59)
- oracle 空为0 (51)
- oracle主从同步 (56)
- oracle 乐观锁 (53)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)