文章目录
1. Redis哨兵模式
在主从集群模式下,salve节点宕机后可以找master节点同步数据,但是倘若master节点宕机后怎么办?
Redis提供了哨兵(Sentinel)机制来实现主从集群的自动故障恢复。哨兵的结构和作用如下:
-
监控:Sentinel 会不断检查您的master和slave是否按预期工作。
-
自动故障恢复:如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主。
- 当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。
-
通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端。
并且单个哨兵对Redis服务器进行监控,可能会出现问题,因此可以使用多个哨兵进行监控。各个哨兵之间还会互相监控,这样就形成了多哨兵模式
1.1 搭建哨兵集群
这里准备使用三个节点作为Sentinel集群,用来监管之前的Redis主从集群。
三个sentinel实例信息如下:
节点 | IP | PORT |
---|---|---|
s1 | 192.168.150.101 | 27001 |
s2 | 192.168.150.101 | 27002 |
s3 | 192.168.150.101 | 27003 |
准备一个sentinel.conf的配置文件
port 27001
sentinel announce-ip 192.168.150.101
sentinel monitor mymaster 192.168.150.101 7001 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
dir "/tmp/s1"
port 27001
:是当前sentinel实例的端口sentinel monitor mymaster 192.168.150.101 7001 2
:指定主节点信息mymaster
:主节点名称,自定义,任意写192.168.150.101 7001
:主节点的ip和端口2
:选举master时的quorum值
另外两个sentinel也需要准备这个配置文件,只是需要把端口号改了。
然后启动三个redis实例
# 第1个
redis-sentinel s1/sentinel.conf
# 第2个
redis-sentinel s2/sentinel.conf
# 第3个
redis-sentinel s3/sentinel.conf
这样哨兵集群的搭建完成了。
哨兵启动后只指定了master的地址,要想知道整个集群中完整的拓扑关系怎么做呢?
哨兵每隔10s就会向每个master节点发送info
命令,info
命令返回的信息中,包含了主从拓扑关系,其中包括每个slave的地址和端口号。有了这些信息后,哨兵就会记住这些节点的拓扑信息,在后续发生故障时,选择合适的slave节点进行故障恢复。
那么哨兵之间是怎样通信的呢?
哨兵之间是通过Redis提供的发布(pub)/订阅(sub)机制完成的。哨兵节点不会直接与其他哨兵节点建立连接,而是首先会和主库建立起连接,然后向一个名为”sentinel:hello”频道发送自己的信息(IP 和端口),其他订阅了该频道的哨兵节点就会获取到该哨兵节点信息,从而哨兵节点之间互知。
1.2 选举规则与故障转移
一旦master故障,sentinel就需要在多个salve中选择一个作为新的master,选择规则如下:
- 首先判断salve节点与master断开时间长短,如果超过指定值(down-after-milliseconds * 10)则会排除该slave节点
- 然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举
- 如果slave-prority一样,则判断slave节点的offset值,越大说明数据越新,优先级越高
- 最后是判断slave节点的运行id大小,越小优先级越高。
简而言之,就是slave-priority配置 > 数据完整性 > runid较小者进行选择
选举出新的master之后,就要开始进行故障转移了,步骤如下:
- sentinel给备选的slave1节点发送slaveof no one命令,让该节点成为master
- sentinel给所有其它slave发送slaveof 192.168.150.101 7002 命令,让这些slave成为新master的从节点,开始从新的master上同步数据。
- 最后,sentinel将故障节点标记为slave,当故障节点恢复后会自动成为新的master的slave节点
1.3 RedisTemplate的哨兵模式
在Java中使用哨兵模式,需要以下步骤:
-
在pom文件中引入redis的starter依赖:
<!--redis依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
-
然后在配置文件application.yml中指定sentinel相关信息:
spring: redis: sentinel: master: mymaster # 指定master名称 nodes: # 指定redis-sentinel集群信息 - 192.168.150.101:27001 - 192.168.150.101:27002 - 192.168.150.101:27003
-
配置主从读写配置
@Bean public LettuceClientConfigurationBuilderCustomizer clientConfigurationBuilderCustomizer(){ return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED); }
**这里的ReadFrom是配置Redis的读取策略,是一个枚举,**包括下面选择:
- MASTER:从主节点读取
- MASTER_PREFERRED:优先从master节点读取,master不可用才读取replica
- REPLICA:从slave(replica)节点读取
- REPLICA _PREFERRED:优先从slave(replica)节点读取,所有的slave都不可用才读取master
这样配置完之后,客户端就能感知到主节点发生改变了。
那么,主节点发生变化的时候,客户端是如何感知的呢?
这是基于redis提供的发布(pub)/订阅(sub)机制完成的,客户端可以从哨兵订阅消息,故障转移后,客户端会收到订阅消息。
2. Redis分片集群
主从哨兵模式可以更好解决高可用、高并发读的问题。但是面对高并发写与海量数据存储的问题,这种模式依然存在问题
因此,分片集群模式的出现,就能解决上述出现的问题。
分片集群特征:
-
集群中有多个master,每个master保存不同数据
-
每个master都可以有多个slave节点
-
master之间通过ping监测彼此健康状态
-
客户端请求可以访问集群任意节点,最终都会被转发到正确节点
2.1 搭建分片集群
这里就搭建3个master节点,每个master包含一个salve节点。
信息如下:
IP | PORT | 角色 |
---|---|---|
192.168.150.101 | 7001 | master |
192.168.150.101 | 7002 | master |
192.168.150.101 | 7003 | master |
192.168.150.101 | 8001 | slave |
192.168.150.101 | 8002 | slave |
192.168.150.101 | 8003 | slave |
准备一个redis.conf文件
port 6379
# 开启集群功能
cluster-enabled yes
# 集群的配置文件名称,不需要我们创建,由redis自己维护
cluster-config-file /tmp/6379/nodes.conf
# 节点心跳失败的超时时间
cluster-node-timeout 5000
# 持久化文件存放目录
dir /tmp/6379
# 绑定地址
bind 0.0.0.0
# 让redis后台运行
daemonize yes
# 注册的实例ip
replica-announce-ip 192.168.150.101
# 保护模式,不需要密码就可以进去
protected-mode no
# 数据库数量
databases 1
# 日志
logfile /tmp/6379/run.log
每个实例都修改成自己的端口号,然后启动实例。
虽然服务启动了,但是目前每个服务之间都是独立的,没有任何关联。
在Redis5.0以后,集群管理已经集成到redis-cli中
redis-cli --cluster create --cluster-replicas 1 192.168.150.101:7001 192.168.150.101:7002 192.168.150.101:7003 192.168.150.101:8001 192.168.150.101:8002 192.168.150.101:8003
命令说明:
redis-cli --cluster
或者./redis-trib.rb
:代表集群操作命令create
:代表是创建集群--replicas 1
或者--cluster-replicas 1
:指定集群中每个master的副本个数为1,此时节点总数 ÷ (replicas + 1)
得到的就是master的数量。因此节点列表中的前n个就是master,其它节点都是slave节点,随机分配到不同master
这样集群的搭建完成了。
2.2 散列插槽
在Redis的分片集群中,Redis会把每一个master节点映射到0~16383共16384个插槽(hash slot)上,查看集群信息时就能看到:
**数据key不是与节点绑定,而是与插槽绑定。**redis会根据key的有效部分计算插槽值,分两种情况:
- key中包含”{}”,且“{}”中至少包含1个字符,“{}”中的部分是有效部分
- key中不包含“{}”,整个key都是有效部分
例如:key是num,那么就根据num计算,如果是{itcast}num,则根据itcast计算。计算方式是利用CRC16算法得到一个hash值,然后对16384取余,得到的结果就是slot值。
如图,在7001这个节点执行set a 1时,对a做hash运算,对16384取余,得到的结果是15495,因此要存储到103节点。
到了7003后,执行get num
时,对num做hash运算,对16384取余,得到的结果是2765,因此需要切换到7001节点
如何将同一类数据固定的保存在同一个Redis实例?
这一类数据使用相同的有效部分,例如key都以{typeId}为前缀
2.3 集群伸缩
redis-cli –cluster还提供了添加节点的命令。
新建一个redis节点7004,执行下面命令
redis-cli --cluster add-node 192.168.150.101:7004 192.168.150.101:7001
通过命令查看集群状态:
redis-cli -p 7001 cluster nodes
如图,7004加入了集群,并且默认是一个master节点:
但是此时7004的插槽数为0,任何数据都不可以存储在7004中。
因此,就需要进行转移插槽的操作了
假如想要将num存储在7004节点,就要先看看num的插槽是多少了
如上图所示,num的插槽为2765.
我们可以将0~3000的插槽从7001转移到7004,命令格式如下:
建立连接:
这里就是问要移动多少个插槽,这里我想移动3000个
这里问的是那个node来接收这些插槽??
显然是7004节点,可以查看节点的id
这里询问,你的插槽是从哪里移动过来的?
- all:代表全部,也就是三个节点各转移一部分
- 具体的id:目标节点的id
- done:没有了
这里可以选择从7001获取,所以填写7001的id
填完后,点击done,这样插槽转移就准备好了:
最后输入yes,就可以了
再次查看,可以看见插槽分配成功了
2.4 故障转移
对于宕机的master进行故障转移,有以下两种方式:
- 自动故障转移
- 手动故障转移
2.4.1 自动故障转移
自动故障转移的话,当一个redis宕机
首先先是疑似宕机
然后确认下线,自动升级一个salve为新的master
当7002再次启动,就会变为一个slave节点了:
2.4.2 手动故障转移
利用cluster failover命令可以手动让集群中的某个master宕机,切换到执行cluster failover命令的这个slave节点,实现无感知的数据迁移。其流程如下:
这种failover命令可以指定三种模式:
- 缺省:默认的流程,如图1~6歩
- force:省略了对offset的一致性校验
- takeover:直接执行第5歩,忽略数据一致性、忽略master状态和其它master的意见
2.5 RedisTemplate访问分片集群
RedisTemplate底层同样基于lettuce实现了分片集群的支持,而使用的步骤与哨兵模式基本一致:
1)引入redis的starter依赖
2)配置分片集群地址
3)配置读写分离
与哨兵模式相比,其中只有分片集群的配置方式略有差异,如下:
spring:
redis:
cluster:
nodes:
- 192.168.150.101:7001
- 192.168.150.101:7002
- 192.168.150.101:7003
- 192.168.150.101:8001
- 192.168.150.101:8002
- 192.168.150.101:8003
参考:
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/94963.html