Redis集群模式

Redis系列

1. 主从模式

最简单的一种集群方式,集群中分为master数据库和slave数据库,master可以提供读写服务,slave只能提供读服务,所以一单master关掉之后,集群就变成了了只读服务了

2. 哨兵(sentinel)模式

在这里插入图片描述

由于主从模式存在一大弊端,主节点挂掉之后无法对外提供写服务,哨兵模式出现了。哨兵模式由哨兵集群和redis集群组成,特点是:

  1. 哨兵集群只负责监控redis集群,不提供读写服务
  2. 当master挂掉时,sentinel会选举一个新的master,此时服务会停顿
  3. 客户端只需要连接sentinel即可,redis集群出现问题,发生重新选举不需要切换数据源
  4. 只有master提供写服务,slave是只读的,所以master压力很大
  5. 数据量过大时,master就扛不住了

3. cluster模式

当数据量很大时,就需要对数据进行分布式存储,sentinel只能配置一个master,能力有限。claster(集群模式)是Redis提供的分布式数据方案,集群通过分配进行数据共享,并且提供复制和故障转移功能。涉及到概念节点槽指派命令执行重新分片转向故障转移消息
在这里插入图片描述
特点

  1. 节点相互独立,无中心结构
  2. 每个主节点可以设置多个从节点
  3. 节点互相连接
  4. 故障自动转移
  5. 可以大量水平拓展,官方推荐不超过1000个节点

3.1 节点

几个Redis集群由多个节点组成,最开始节点相互独立,需要我们将它们连接起来,连接命令:

CLUSTER MEET <IP> <PORT>

通过此命令,与目标节点握手,握手成功后,当前节点会将目标节点添加到当前节点集群中,如何查看集群状态:

CLUSTER NODES

启动集群模式配置:cluster-enabled=yes

3.1.1 集群的数据结构

clusterNode结构保存了一个节点的当前状态,如:创建时间、名字、配置纪元、节点ip、port等。

struct clusterNode{
	//创建节点时间
	mstime_t ctime;
	//节点名字,40个16进制字符组成
	char name[REDIS_CLUSTER_NAMELEN];
	//节点标识
	//使用不同的标识值记录节点的角色(比如主节点或者从节点)
	//以及节点目前所处的状态(在线或者下线)
	int flags;
	//节点当前配置纪元,用于实现故障转移
	uint64_t configEpoch;
	//节点的ip地址
	char ip[REDIS_IP_STR_LEN];
	//节点端口
	int port;
	//保存连接节点所需的有关信息
	clusterLink *link;
	//...
}

其中link属性是一个clusterLink结构:

typedef struct clusterLink{
	//连接的创建时间
	mstime_t ctime;
	//tcp套字节描述符
	int fd;
	//输出缓冲区,保存发送给其他节点的消息
	sds sndbuf;
	//输入缓冲区,保存从其他节点接收的消息
	sds rcvbuf;
	//与这个链接相关联的节点,没有就为null
	struct clusterNode *node;
}

最后每个节点都保存一个clusterState的结构,记录了当前节点视角下,集群目前所处的状态:

typedef struct clusterState{
	//指向当前节点的指针
	clusterNode *myself;
	//集群当前配置单元,用于实现故障转移
	uint64_t currentEpoch;
	//集群当前状态:上线还是下线
	int state;
	//集群中至少处理着一个槽的节点的数量
	int size;
	//集群节点名单(包括myself节点)
	//字典的键为节点的名字,值为节点对应的clusterNode结构
	dict *nodes;
	//...
}

以7001、7002、7003三个节点为例,站在7000的视角:

  1. currentEpoch为0表示集群配置纪元为0
  2. size为0,表示当前集群没有任何节点在处理槽,因此state属性为REDIS_CLUSTER_FAIL,表示集群处于下线状态
  3. nodes字典记录了集群目前包含的三个节点,分别由三个clusterNode表示,其中myself指向7000的clusterNode结构,字典的另外两个指针指向7001、7002的clusterNode结构,这两个节点是7000已知咋的在集群中的其它节点
  4. flags都是REDIS_NODE_MASTER,说明都是主节点
    在这里插入图片描述
    站在7001、7002的视角如同

3.1.2 CLUSTER MEET命令的实现

客户端向节点A发送CLUSTER MEET命令,可以让节点A节点B添加到节点A所在的集群里,握手过程如下

  1. A为B创建一个clusterNode结构,并将其添加到自己的clusterState.nodes字典里
  2. A根据给定的ip和端口号向B发送一条MEET消息
  3. B如果收到A的消息,会为A创建一个clusterNode结构,并将其添加到自己的clusterState.nodes字典里
  4. B向A返回一条PONG消息
  5. 如果A收到B的PONG消息,说明一切顺利,A就知道B成功接收到自己的MEET消息
  6. A向B返回一条PING消息
  7. 握手完成(和TCP三次握手很像)
发送命令
CLUSTER MEET <B_ip> <B_port>
发送MEET消息
返回PONG消息
返回PING消息
客户端
节点A
节点B

之后A会将B的信息传播给集群中其它节点,让其它节点与B握手,最终B被所有节点认识

3.2 槽指派

Redis通过分片方式保存数据:整个数据库被分为16384个槽(Slot),每个键都属于这些槽其中的一个,每个节点可以处理0-16384个槽
当这些槽全部都有节点处理时,集群处于上线(ok)状态;反之处于(fail),上面已经将7001、7002、7003加到同一个集群里面,但是此时集群处于fail状态,因为三个节点都没有指派槽,槽指派命令:

CLUSTER ADDSLOTS <slot> [slot ...]

举个例子,如何将0到5000指派给7001:

127.0.0.1:7000 > CLUSTER ADDSLOTS 0 1 2 3 4 ... 5000
ok

同理可以将剩下的槽指派给剩余节点,尽量保持平均

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值