redis主从、哨兵、集群

一、介绍

  • 1、主从模式:
    特点:master 节点挂掉后,需要手动指定新的 master,可用性不高
    适用场景:基本不用

  • 2、哨兵模式:
    特点:master 节点挂掉后,哨兵进程会主动选举新的 master,可用性高,但是每个节点存储的数据是一样的,浪费内存空间(这一条是相对下面的集群模式来说的)。
    适用场景:数据量不是很多、当集群规模不是很大、需要自动容错容灾的时候使用。

  • 3、集群模式:
    特点:Redis Cluster 模式是在2015年4月发布的3.0版本中引入的,解决了故障切换,加数据分布均匀的问题(基于slot 槽,类似于一执行hash对数据进行分片)最大限度利用了内存。
    使用场景:数据量比较大、QPS 要求较高的时候使用。

二、主从模式

2.1 介绍

redis主从:
1、一主多从,主负责写,从负责读
2、没有故障切换
3、一个主节点可以有多个从节点,但是一个从节点会只会有一个主节点,也就是所谓的一主多从结构。

file

从执行sync,主收到后bgsave线程启动,从库先全量同步数据,这段时间内主库的bgsave一直在记录增量数据,从库同步完全量后再同步bgsave记录的增量,然后后续就是只同步增量了

2.2 配置示例

机器名称 IP 端口
master 192.168.71.12 6379
slave1 192.168.71.14 6379
slave2 192.168.71.15 6379
slave3 192.168.71.16 6379

所有节点

setenforce 0
systemctl stop firewalld
yum install redis -y

先强调一个点:考虑到后续主从可能会发生切换,所以为了方便,建议无论主从,最开始都在redis.conf中配置上这两项且保持密码一致

masterauth 123456  # 连接主库用的密码,是主库里设置的密码
requirepass 123456 # 为自己这个redis设置的密码

主节点配置,随后先启动主节点

# 一、配置文件/etc/redis/redis.conf # 配置项末尾不要加注释,我加是为了给你提示,但你不能直接贴到文件里
# (1)修改一行
bind 0.0.0.0
# (2)增量两行
masterauth 123456 # 配置上,以防日后该主节点切换为从节点,然后去连某个新主redis
requirepass 123456

# 二、重启
systemctl restart redis

从节点配置(三台都一样),然后一台台启动从节点

# =========================》redis.conf配置如下(# 配置项末尾不要加注释,我加是为了给你提示,但你不能直接贴到文件里)
# (1)修改
bind 0.0.0.0
# (2)增加
# 配置主节点的ip和端口
slaveof 192.168.71.12 6379
# 从redis2.6开始,从节点默认是只读的
slave-read-only yes
# 主节点有登录密码,则必须指定
masterauth 123456
# 建议在从上也设置与主一模一样的密码,这与后续你切主会方便一些,因为无论哪个节点都是一样的密码
requirepass 123456

也可以不配置上面的文件,使用 redis-server 命令,在启动从节点时,通过参数–slaveof 指定主节点是谁。。

./redis-server --slaveof 192.168.71.12 6379

可以登录主或从节点查看主从状态

info replication

# 注意:redis 6.x版本与redis3.x版本不兼容
你用centos7.9默认yum安装的就是redis3.x版本,你用centos9默认yum安装的是redis6.x版

file

file

系统运行时,如果 master 挂掉了,可以在一个从库(如 slave1)上手动执行命令,slave2也是一样

slaveof no one  # 将 slave1 变成新的 master
slaveof 192.168.71.14 6379 # 将这两个机器的主节点指向的这个新的 master;

补充:
执行命令slaveof no one命令,可以关闭从服务器的复制功能。同时原来同步的所得的数据集都不会被丢弃。

挂掉的原 master修复 启动后作为新的 slave 也指向新的 master 上。

2.3 流程详解

file

  • 从数据库连接主数据库,发送 SYNC 命令;

  • 主数据库接收到 SYNC 命令后,可以执行 BGSAVE 命令生成 RDB 文件并使用缓冲区记录此后执行的所有写命令;

  • 主数据库 BGSAVE 执行完后,向所有从数据库发送快照文件,并在发送期间继续记录被执行的写命令;

  • 从数据库收到快照文件后丢弃所有旧数据,载入收到的快照;

  • 主数据库快照发送完毕后开始向从数据库发送缓冲区中的写命令;

  • 从数据库完成对快照的载入,开始接受命令请求,并执行来自主数据库缓冲区的写命令;(从数据库初始化完成)

  • 主数据库每执行一个写命令就会向从数据库发送相同的写命令,从数据库接收并执行收到的写命令(从数据库初始化完成后的操作)

  • 出现断开重连后,2.8 之后的版本会将断线期间的命令传给从数据库,增量复制。

  • 主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然,如果有需要,slave 在任何时候都可以发起全量同步。Redis 的策略是,无论如何,首先会尝试进行增量同步,如不成功,要求从机进行全量同步。

三、哨兵模式

3.1 介绍

1、哨兵模式介绍哨兵模式介绍

哨兵模式就是为了介绍主从模式无法自动故障切换而诞生的,把下图的哨兵节点去掉后就是主从模式

file

哨兵(sentinel)是Redis的高可用性(High Availability)的解决方案:由一个或多个sentinel实例组成sentinel集群可以监视一个或多个主服务器和多个从服务器。当主服务器进入下线状态时,sentinel可以将该主服务器下的某一从服务器升级为主服务器继续提供服务,从而保证redis的高可用性。

2、哨兵节点是什么?

哨兵节点是特殊的redis服务,不提供读写服务,主要用来监控redis实例节点。

3、哨兵节点具体都干什么,主要任务总结如下

(1)监控:哨兵会不断地检查你的Master和Slave是否运作正常。
(2)提醒(通知):当被监控的某个Redis节点出现问题时,哨兵可以通过 API 向管理员或者其他应用程序发送通知。
(3)自动故障转移:当一个Master不能正常工作时,哨兵会进行自动故障迁移操作,将失效Master的其中一个Slave升级为新的Master,并让失效Master的其他Slave改为复制新的Master;当客户端试图连接失效的Master时,集群也会向客户端返回新Master的地址,使得集群可以使用新Master代替失效Master。

4、哨兵模式下,客户端程序如何连接redis集群呢?

在Java客户端连接哨兵,只需要配置哨兵节点即可

spring.redis.sentinel.master=mymaster #哨兵配置文件中定义的集群名字
spring.redis.sentinel.nodes=哨兵ip1:哨兵端口1,哨兵ip2:哨兵端口2,哨兵ip3:哨兵端口3

5、哨兵模式下,客户端程序从哨兵那里获取到主节点ip后,以后每次都会询问哨兵要主节点ip吗?

答:不会
哨兵架构下client端第一次从哨兵找出redis的主节点,后续就直接访问redis的主节点,不会每次都通过sentinel代理访问redis的主节点。
那主节点挂掉后哨兵推荐出新的master后客户端如何知晓呢?
答:当redis的主节点挂掉时,哨兵会第一时间感知到,并且在slave节点中重新选出来一个新的master,然后将新的master信息通知给client端,从而实现高可用。
这里面redis的client端一般都实现了订阅功能,订阅sentinel发布的节点变动消息。

3.2 配置示例(哨兵节点通常为奇数个)

上我们之前配置的主从模式基础上进行就行

机器名称 IP 端口
master 192.168.71.12 6379
slave1 192.168.71.14 6379
slave2 192.168.71.15 6379
slave3 192.168.71.16 6379
sentinel 1 192.168.71.17 26379
sentinel 2 192.168.71.18 26379
sentinel 3 192.168.71.19 26379

这里我们将哨兵进程和 redis 分别部署在不同的机器上,避免因为 redis 宕机导致 sentinel 进程不可用。
所有节点

setenforce 0
systemctl stop firewalld
yum install redis -y

之前我们已经部署过redis主从了,我们只需要在此基础之上新增哨兵就行

# 三台哨兵节点都需要安装
yum install redis -y

# 每台机器的哨兵进程都需要一个哨兵的配置文件sentinel.conf,三台机器的哨兵配置是一样的。
====================》 vi /etc/redis/sentinel.conf # 配置项概述
# 1、禁止保护模式,保护模式是增强redis安全放置未经授权的客户端访问redis实例
protected-mode no
# 2、
sentinel monitor <master-name> <ip> <redis-port> <quorum>
# 各部分解释
# (1)sentinel monitor: 代表监控
# (2)<master-name>:mymaster代表哨兵集群的名字,客户端连接的时候需要用这个名字。只能由字母A-z、数字0-9 、这三个字符".-_"组成
# (3)<ip> <redis-port>:被监控的主从集群中主节点的ip与port
# (4)<quorum>:当quorum个数的哨兵节点认为master主节点失联 那么这时客观上认为主节点失联了

# 3、当主从的master存在密码时,需要配置密码
sentinel auth-pass <master-name> <password> 
# 各部分解释
# (1)<master-name>:是你的哨兵集群名字
# (2)<password>:是哨兵 sentinel 连接主从的密码,与你在主从redis.conf配置的requirepass保持一致
# 补充:由于master挂了之后,哨兵会进行重新的选举,如果slave也配置了连接密码,那么最好在其他的节点都配置上 masterauth xxx,保证挂了的服务重启之后能正常加入主从中去。

# 4、修改心跳检测的主观下线时间
sentinel down-after-milliseconds <master-name> <milliseconds> # 单位毫秒,即千分之一秒

# 5、默认情况一旦主redis节点发生故障,哨兵会将所有的从都切换到新主,这个切换过程中,所有从服务器将暂时无法提供服务。为了解决这一问题,官方提供了如下设置
sentinel parallel-syncs <master-name> <numslaves>
假设你有5个从服务器,故障切换发生之后,如果parallel-syncs的<numslaves>设置为3,那么在故障切换发生后:
- 1、最初的3个从服务器开始与新主建立连接并同步数据。
- 2、在这3个从服务器完成同步并作为新主的从服务器提供服务后,剩下的2个从服务器开始切换过程。
- 3、这2个从服务器断开与旧主的连接,然后尝试与新主建立连接并同步数据。
- 4、当这2个从服务器完成同步后,它们也将作为新主的从服务器恢复服务。
通过这个设置,你可以控制并发切换的从服务器的数量,保留一部分从服务器在切换过程中提供服务,
从而在一定程度上减轻由于主服务器故障切换导致的服务中断时间。尤其在新主服务器数据量大,
同步需要较长时间的情况下,这个设置可以有效地缓解服务中断的影响。

配置示例 /etc/redis/sentinel.conf # 找到相应的位置进行修改,注意要找到位置然后修改,否则可能会因为定义的哨兵集群名字重复而报错

# 1、主要配置(搜索相应的位置进行修改)
protected-mode no
sentinel monitor mymaster 192.168.71.12 6379 2
sentinel auth-pass mymaster 123456

# 2、优化配置(搜索相应的位置进行修改)
sentinel down-after-milliseconds mymaster 3000
sentinel parallel-syncs mymaster 2

启动

nohup redis-sentinel /etc/redis/sentinel.conf &

[root@m01 ~]# netstat -an |grep 26379
tcp        0      0 0.0.0.0:26379           0.0.0.0:*               LISTEN     
tcp6       0      0 :::26379                :::*                    LISTEN

3.3、哨兵工作原理

哨兵是一个分布式系统,可以在一个架构中运行多个哨兵进程,这些进程使用流言协议(gossip protocols)来传播Master是否下线的信息,并使用投票协议(agreement protocols)来决定是否执行自动故障迁移,以及选择哪个Slave作为新的Master。具体工作原理下面讲述。

(1)心跳检测机制

  1. Sentinel 与 Redis Node的关系
    Redis Sentinel 哨兵节点 是一个特殊的 Redis 节点。在哨兵模式创建时,需要通过配置指定 Sentinel 与 Redis Master Node 之间的关系,然后 Sentinel 会从主节点上获取所有从节点的信息,之后 Sentinel 会定时向主节点和从节点发送 info 命令获取其拓扑结构和状态信息。
  2. Sentinel与Sentinel之间是如何沟通的
    答:基于 Redis 的订阅发布功能, 每个 Sentinel 节点会向主 sentinel:hello 频道上发送该 Sentinel 节点对于redis master node的判断以及当前 Sentinel 节点的信息 ,同时每个 Sentinel 节点也会订阅该频道, 来获取其他 Sentinel 节点的信息以及它们对redis master node的判断。

通过以上两步所有的 Sentinel 节点以及它们与所有的 Redis 节点之间都已经彼此感知到,之后每个 Sentinel 节点会向主节点、从节点、以及其余 Sentinel 节点定时发送 ping 命令作为心跳检测, 来确认这些节点是否可达。

(2)判断master节点是否下线

  1. 每个Sentinel每秒一次向所有与它建立了命令连接的实例(主服务器、从服务器和其他Sentinel)发送PING命令,作用是通过心跳检测,检测主从服务器的网络连接状态。

  2. 如果 master 节点回复 PING 命令的时间超过 down-after-milliseconds 设定的阈值(默认30s),则这个 master 会被 sentinel 标记为主观下线,修改其 flags 状态为SRI_S_DOWN。

  3. 当sentinel 哨兵节点将 master 标记为主观下线后,会向其余所有的 sentinel 发送sentinel is-master-down-by-addr消息,询问其他sentinel是否同意该master下线。

    SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <runid>
    # ip:主观下线的服务ip
    # port:主观下线的服务端口
    # current_epoch:sentinel的纪元
    # runid:*表示检测服务下线状态,如果是sentinel的运行id,表示用来选举领头sentinel
  4. 每个sentinel收到命令之后,会根据发送过来的 ip和port 检查自己判断的结果,回复自己是否认为该master节点已经下线了。

    <down_state>< leader_runid >< leader_epoch >
    # down_state(1表示已下线,0表示未下线)
    # leader_runid(领头sentinal id)
    #leader_epoch(领头sentinel纪元)
  5. sentinel收到回复之后,如果同意master节点进入主观下线的sentinel数量大于等于quorum,则master会被标记为客观下线,即认为该节点已经不可用。

  6. 在一般情况下,每个 Sentinel 每隔 10s 向所有的Master,Slave发送 INFO 命令。当Master 被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次。作用:发现最新的集群拓扑结构。

(3)基于Raft协议的哨兵leader选举

到现在为止,已经知道了master客观下线,那就需要一个sentinel来负责故障转移,那到底是哪个sentinel节点来做这件事呢?需要通过选举实现,具体的选举过程如下:

  1. 判断客观下线的sentinel节点向其他 sentinel 节点发送 SENTINEL is-master-down-by-addr ip port current_epoch runid;(注意:这时的runid是自己的run id,每个sentinel节点都有一个自己运行时id)
  2. 目标sentinel回复是否同意master下线并选举领头sentinel,选择领头sentinel的过程符合先到先得的原则。举例:sentinel1判断了客观下线,向sentinel2发送了第一步中的命令,sentinel2回复了sentinel1,说选你为领头,这时候sentinel3也向sentinel2发送第一步的命令,sentinel2会直接拒绝回复;
  3. 当sentinel发现选自己的节点个数超过 majority 的个数的时候,自己就是领头节点;
  4. 如果没有一个sentinel达到了majority的数量,等一段时间,重新选举。

(4)故障转移

有了领头sentinel之后,下面就是要做故障转移了,故障转移的一个主要问题和选择领头sentinel问题差不多,到底要选择哪一个slaver节点来作为master呢?按照我们一般的常识,我们会认为哪个slave节点中的数据和master中的数据相识度高哪个slaver就是master了,其实哨兵模式也差不多是这样判断的,不过还有别的判断条件,详细介绍如下:

  1. 在进行选择之前需要先剔除掉一些不满足条件的slaver,这些slaver不会作为变成master的备选;
    • 剔除列表中已经下线的从服务
    • 剔除有5s没有回复sentinel的info命令的slave
    • 剔除与已经下线的主服务连接断开时间超过 down-after-milliseconds * 10 + master宕机时长 的slaver
  2. 选主
    • 选择优先级最高的节点,通过sentinel配置文件中的replica-priority配置项,这个参数越小,表示优先级越高
    • 如果第一步中的优先级相同,选择offset最大的,offset表示主节点向从节点同步数据的偏移量,越大表示同步的数据越多
    • 如果第二步offset也相同,选择run id较小的
  3. 故障转移,当选举出Leader Sentinel后,Leader Sentinel会对下线的主服务器执行故障转移操作,主要有三个步骤:
    • 它会将失效 Master 的其中一个 Slave 升级为新的 Master,并让失效 Master的其他 Slave 改为复制新的 Master;
    • 当客户端试图连接失效的 Master 时,集群也会向客户端返回新 Master 的地址,使得集群可以使用现在的 Master 替换失效 Master;
    • Master 和 Slave 服务器切换后, Master 的 redis.conf 、 Slave 的 redis.conf 和sentinel.conf 的配置文件的内容都会发生相应的改变,即, Master 主服务器的 redis.conf配置文件中会多一行 replicaof 的配置, sentinel.conf 的监控目标会随之调换。

3.4 总结哨兵

优点

  • 哨兵模式是基于主从模式的,所以,主从有的优点,哨兵模式都具有,哨兵只是在它的基础上加了哨兵集群

  • 主从可以自动切换,系统更健壮,可用性更高。

缺点

  • 具有主从模式的缺点,每台机器上的数据是一样的,内存的可用性较低。

  • Redis 较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。

四、集群模式

4.1 介绍

1、集群模式介绍

Redis 的哨兵模式基本已经可以实现高可用,读写分离 ,但是在这种模式下每台 Redis 服务器都存储相同的数据,很浪费内存,所以在 redis3.0 上加入了 Cluster 集群模式,实现了 Redis 的分布式存储,对数据进行分片,也就是说每台 Redis 节点上存储不同的内容;

file

2、集群模式工作原理

Cluster模式是Redis的一种高级集群模式,它通过数据分片和分布式存储实现了负载均衡和高可用性。在Cluster模式下,Redis将所有的键值对数据分散在多个节点上。每个节点负责一部分数据,称为槽位。通过对数据的分片,Cluster模式可以突破单节点的内存限制,实现更大规模的数据存储。

3、数据分片与槽位

Redis Cluster将数据分为16384个槽位,每个节点负责管理一部分槽位。当客户端向Redis Cluster发送请求时,Cluster会根据键的哈希值将请求路由到相应的节点。具体来说,Redis Cluster使用CRC16算法计算键的哈希值,然后对16384取模,得到槽位编号。

4、主负责读写和写,从库只负责备份
在redis的官方文档中,对redis-cluster架构上,有这样的说明:在cluster架构下,默认的,一般redis-master用于接收读写,而redis-slave则用于备份,当有请求是在向slave发起时,会直接重定向到对应key所在的master来处理

5、客户端程序如何链接redis集群?

对客户端来说,整个 cluster 被看做是一个整体,客户端可以连接任意一个 node 进行操作,接入任何一个实例就相当于接入了整个集群,就像操作单一 Redis 实例一样,当客户端操作的 key 没有分配到该 node 上时,Redis 会返回转向指令,指向正确的 node,这有点儿像浏览器页面的 302 redirect 跳转。

4.2 配置示例

根据官方推荐,集群部署至少要 3 台以上的 master 节点,最好使用 3 主 3 从六个节点的模式

找六台机器

机器名称 IP 端口
master1 192.168.71.11 6379
master2 192.168.71.12 6379
master3 192.168.71.13 6379
slave1 192.168.71.14 6379
slave2 192.168.71.16 6379
slave3 192.168.71.17 6379

所有节点

setenforce 0
systemctl stop firewalld
yum install redis -y

一、开启集群模式:每台机器均配置如下

bind 0.0.0.0
protected-mode no
# 开启集群模式
cluster-enabled yes

# 节点超时时间
cluster-node-timeout 15000

二、创建集群:
6 个 Redis 服务分别启动成功之后,这时虽然配置了集群开启,但是这六台机器还是独立的。使用集群管理命令将这 6 台机器添加到一个集群中。

redis-cli --cluster create 192.168.71.11:6379 192.168.71.12:6379 192.168.71.13:6379 192.168.71.14:6379 192.168.71.16:6379 192.168.71.17:6379 --cluster-replicas 1

cluster-replicas 表示从节点的数量,1代表每个主节点都有一个从节点。执行完成后自动生成配置的 redis-cluster.conf 文件。

[root@m01 ~]# redis-cli --cluster create 192.168.71.11:6379 192.168.71.12:6379 192.168.71.13:6379 192.168.71.14:6379 192.168.71.16:6379 192.168.71.17:6379 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.71.16:6379 to 192.168.71.11:6379
Adding replica 192.168.71.17:6379 to 192.168.71.12:6379
Adding replica 192.168.71.14:6379 to 192.168.71.13:6379
M: 32a7c50944fd31015d2e7e8a94db88bc9634501c 192.168.71.11:6379
   slots:[0-5460] (5461 slots) master
M: d079093147721a0a9913ae0f8f952642f18c18b0 192.168.71.12:6379
   slots:[5461-10922] (5462 slots) master
M: 62dec14d2669b0cd4cf73452b5bd6927f246fbee 192.168.71.13:6379
   slots:[10923-16383] (5461 slots) master
S: 62226042b257b0454ea06f10bf98883b2b887af8 192.168.71.14:6379
   replicates 62dec14d2669b0cd4cf73452b5bd6927f246fbee
S: 83e27af0d92efc5038817e11e25ab24f86b3e4c1 192.168.71.16:6379
   replicates 32a7c50944fd31015d2e7e8a94db88bc9634501c
S: 48ec8a2732594980fe13a77bca502d8ffa6803b8 192.168.71.17:6379
   replicates d079093147721a0a9913ae0f8f952642f18c18b0
Can I set the above configuration? (type 'yes' to accept): yes # 输入yes,接受上面配置
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.
>>> Performing Cluster Check (using node 192.168.71.11:6379)
M: 32a7c50944fd31015d2e7e8a94db88bc9634501c 192.168.71.11:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: 48ec8a2732594980fe13a77bca502d8ffa6803b8 192.168.71.17:6379
   slots: (0 slots) slave
   replicates d079093147721a0a9913ae0f8f952642f18c18b0
M: 62dec14d2669b0cd4cf73452b5bd6927f246fbee 192.168.71.13:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
M: d079093147721a0a9913ae0f8f952642f18c18b0 192.168.71.12:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: 83e27af0d92efc5038817e11e25ab24f86b3e4c1 192.168.71.16:6379
   slots: (0 slots) slave
   replicates 32a7c50944fd31015d2e7e8a94db88bc9634501c
S: 62226042b257b0454ea06f10bf98883b2b887af8 192.168.71.14:6379
   slots: (0 slots) slave
   replicates 62dec14d2669b0cd4cf73452b5bd6927f246fbee
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

三、测试验证

# 1、登录集群:选择任一节点
redis-cli -c -h 192.168.71.12 -p 6379 # -c,使用集群方式登录,有密码的话就在加上参数-a 123456

# 2、查看集群信息
CLUSTER INFO # 查看集群信息:
CLUSTER NODES # 列出节点信息

# 3、添加与查询(读写操作都会定向到master库上,不可能跑到从库上,因为从库只负责备份)
[root@m01 ~]# redis-cli -c -h 192.168.71.17 -p 6379
192.168.71.17:6379> 
192.168.71.12:6379> set age 18
-> Redirected to slot [741] located at 192.168.71.11:6379
OK

[root@m01 ~]# redis-cli -c -h 192.168.71.13 -p 6379 
192.168.71.13:6379> 
192.168.71.13:6379> keys *
(empty array)
192.168.71.13:6379> 
192.168.71.13:6379> get age
-> Redirected to slot [741] located at 192.168.71.11:6379
"18"
192.168.71.11:6379> 

4.3 原理

file

在 Redis 的每一个节点上,都有这么两个东西,一个是插槽(slot),它的的取值范围是:0-16383,可以从上面redis-trib.rb执行的结果看到这 16383 个 slot 在三个 master 上的分布。还有一个就是 cluster,可以理解为是一个集群管理的插件,类似的哨兵。

当我们的存取的 Key 到达的时候,Redis 会根据 crc16 的算法对计算后得出一个结果,然后把结果和 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。

当数据写入到对应的 master 节点后,这个数据会同步给这个 master 对应的所有 slave 节点。

为了保证高可用,redis-cluster 集群引入了主从模式,一个主节点对应一个或者多个从节点。当其它主节点 ping 主节点 master 1 时,如果半数以上的主节点与 master 1 通信超时,那么认为 master 1 宕机了,就会启用 master 1 的从节点 slave 1,将 slave 1 变成主节点继续提供服务。

如果 master 1 和它的从节点 slave 1 都宕机了,整个集群就会进入 fail 状态,因为集群的 slot 映射不完整。如果集群超过半数以上的 master 挂掉,无论是否有 slave,集群都会进入 fail 状态。

redis-cluster 采用去中心化的思想,没有中心节点的说法,客户端与 Redis 节点直连,不需要中间代理层,客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。

4.4 总结

优点:
1)集群完全去中心化,采用多主多从;所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
2)客户端与 Redis 节点直连,不需要中间代理层。客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
3)每一个分区都是由一个Redis主机和多个从机组成,分片和分片之间是相互平行的。
4)每一个master节点负责维护一部分槽,以及槽所映射的键值数据;集群中每个节点都有全量的槽信息,通过槽每个node都知道具体数据存储到哪个node上

缺点:

  • 1.Redis Cluster 是无中心节点的集群架构,依靠 Goss 协议(谣言传播)协同自动化修复集群的状态
    但 GosSIp 有消息延时和消息冗余的问题,在集群节点数量过多的时候,节点之间需要不断进行 PING/PANG 通讯,不必须要的流量占用了大量的网络资源。虽然 Reds4.0 对此进行了优化,但这个问题仍然存在。

  • 2.数据迁移问题
    Redis Cluster 可以进行节点的动态扩容缩容,这一过程,在目前实现中,还处于半自动状态,需要人工介入。在扩缩容的时候,需要进行数据迁移。
    而 Redis 为了保证迁移的一致性,迁移所有操作都是同步操作,执行迁移时,两端的 Redis 均会进入时长不等的阻塞状态,对于小 Key,该时间可以忽略不计,但如果一旦 Key 的内存使用过大,严重的时候会接触发集群内的故障转移,造成不必要的切换。

上一篇
下一篇
Copyright © 2022 Egon的技术星球 egonlin.com 版权所有 帮助IT小伙伴学到真正的技术