Redis集群搭建

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
简介: Redis主从实现读写分离,提升并发能力;哨兵保障高可用,自动故障转移;分片集群则解决海量数据存储与高并发写入问题,三者结合构建高性能、高可用的Redis分布式架构。

1.Redis主从
单节点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,这里讲一种方案就是搭建主从集群,实现读写分离。
1.1.主从集群结构
下图就是一个简单的Redis主从集群结构:

如图所示,集群中有一个master节点、两个slave节点(现在叫replica)。当我们通过Redis的Java客户端访问主从集群时,应该做好路由:
● 如果是写操作,应该访问master节点,master会自动将数据同步给两个slave节点
● 如果是读操作,建议访问各个slave节点,从而分担并发压力
1.2.搭建主从集群
我们会在同一个虚拟机中利用3个Docker容器来搭建主从集群,容器信息如下:
容器名 角色 IP 映射端口
r1 master 192.168.150.101 7001
r2 slave 192.168.150.101 7002
r3 slave 192.168.150.101 7003
1.2.1.启动多个Redis实例
我们利用课前资料提供的docker-compose文件来构建主从集群:

文件内容如下:
version: "6.2.7"

services:
r1:
image: redis:6.2.7
container_name: r1
network_mode: "host"
entrypoint: ["redis-server", "--port", "7001"]
r2:
image: redis:6.2.7
container_name: r2
network_mode: "host"
entrypoint: ["redis-server", "--port", "7002"]
r3:
image: redis:6.2.7
container_name: r3
network_mode: "host"
entrypoint: ["redis-server", "--port", "7003"]
将其上传至虚拟机的/root/redis目录下:

执行命令,运行集群:
docker-compose up -d
结果:

由于采用的是host模式,我们看不到端口映射。不过能直接在宿主机通过ps命令查看到Redis进程:

1.2.2.建立集群
虽然我们启动了3个Redis实例,但是它们并没有形成主从关系。我们需要通过命令来配置主从关系:

Redis5.0以前

slaveof

Redis5.0以后

replicaof
有临时和永久两种模式:
● 永久生效:在redis.conf文件中利用slaveof命令指定master节点
● 临时生效:直接利用redis-cli控制台输入slaveof命令,指定master节点
我们测试临时模式,首先连接r2,让其以r1为master

连接r2

docker exec -it r2 redis-cli -p 7002

认r1主,也就是7001

slaveof 192.168.150.101 7001
然后连接r3,让其以r1为master

连接r3

docker exec -it r3 redis-cli -p 7003

认r1主,也就是7001

slaveof 192.168.150.101 7001
然后连接r1,查看集群状态:

连接r1

docker exec -it r1 redis-cli -p 7001

查看集群状态

info replication
结果如下:
127.0.0.1:7001> info replication

Replication

role:master
connected_slaves:2
slave0:ip=192.168.150.101,port=7002,state=online,offset=140,lag=1
slave1:ip=192.168.150.101,port=7003,state=online,offset=140,lag=1
master_failover_state:no-failover
master_replid:16d90568498908b322178ca12078114e6c518b86
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:140
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:140
可以看到,当前节点r1:7001的角色是master,有两个slave与其连接:
● slave0:port是7002,也就是r2节点
● slave1:port是7003,也就是r3节点
1.2.3.测试
依次在r1、r2、r3节点上执行下面命令:
set num 123

get num
你会发现,只有在r1这个节点上可以执行set命令(写操作)

其它两个节点只能执行get命令(读操作)。也就是说读写操作已经分离了。

2.Redis哨兵
主从结构中master节点的作用非常重要,一旦故障就会导致集群不可用。那么有什么办法能保证主从集群的高可用性呢?
2.1.哨兵集群介绍
Redis提供了哨兵(Sentinel)机制来监控主从集群监控状态,确保集群的高可用性。
哨兵集群作用原理图:

哨兵的作用如下:
● 状态监控:Sentinel 会不断检查您的master和slave是否按预期工作
● 故障恢复(failover):如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后会成为slave
● 状态通知:Sentinel充当Redis客户端的服务发现来源,当集群发生failover时,会将最新集群信息推送给Redis的客户端
2.2.搭建哨兵集群
首先,我们停掉之前的redis集群:

老版本DockerCompose

docker-compose down

新版本Docker

docker compose down
然后,我们找到课前资料提供的sentinel.conf文件:

其内容如下:
sentinel announce-ip "192.168.150.101"
sentinel monitor hmaster 192.168.150.101 7001 2
sentinel down-after-milliseconds hmaster 5000
sentinel failover-timeout hmaster 60000
说明:
● sentinel announce-ip "192.168.150.101":声明当前sentinel的ip
● sentinel monitor hmaster 192.168.150.101 7001 2:指定集群的主节点信息
○ hmaster:主节点名称,自定义,任意写
○ 192.168.150.101 7001:主节点的ip和端口
○ 2:认定master下线时的quorum值
● sentinel down-after-milliseconds hmaster 5000:声明master节点超时多久后被标记下线
● sentinel failover-timeout hmaster 60000:在第一次故障转移失败后多久再次重试
我们在虚拟机的/root/redis目录下新建3个文件夹:s1、s2、s3:

将课前资料提供的sentinel.conf文件分别拷贝一份到3个文件夹中。
接着修改docker-compose.yaml文件,内容如下:
version: "6.2.7"

services:
r1:
image: redis:6.2.7
container_name: r1
network_mode: "host"
entrypoint: ["redis-server", "--port", "7001"]
r2:
image: redis:6.2.7
container_name: r2
network_mode: "host"
entrypoint: ["redis-server", "--port", "7002", "--slaveof", "192.168.101.68", "7001"]
r3:
image: redis:6.2.7
container_name: r3
network_mode: "host"
entrypoint: ["redis-server", "--port", "7003", "--slaveof", "192.168.101.68", "7001"]
s1:
image: redis:6.2.7
container_name: s1
volumes:

  - /root/redis/s1:/etc/redis
network_mode: "host"
entrypoint: ["redis-sentinel", "/etc/redis/sentinel.conf", "--port", "27001"]

s2:
image: redis:6.2.7
container_name: s2
volumes:

  - /root/redis/s2:/etc/redis
network_mode: "host"
entrypoint: ["redis-sentinel", "/etc/redis/sentinel.conf", "--port", "27002"]

s3:
image: redis:6.2.7
container_name: s3
volumes:

  - /root/redis/s3:/etc/redis
network_mode: "host"
entrypoint: ["redis-sentinel", "/etc/redis/sentinel.conf", "--port", "27003"]

直接运行命令,启动集群:
docker-compose up -d
运行结果:

我们以s1节点为例,查看其运行日志:

Sentinel ID is 8e91bd24ea8e5eb2aee38f1cf796dcb26bb88acf

+monitor master hmaster 192.168.150.101 7001 quorum 2

  • +slave slave 192.168.150.101:7003 192.168.150.101 7003 @ hmaster 192.168.150.101 7001
  • +sentinel sentinel 5bafeb97fc16a82b431c339f67b015a51dad5e4f 192.168.150.101 27002 @ hmaster 192.168.150.101 7001
  • +sentinel sentinel 56546568a2f7977da36abd3d2d7324c6c3f06b8d 192.168.150.101 27003 @ hmaster 192.168.150.101 7001
  • +slave slave 192.168.150.101:7002 192.168.150.101 7002 @ hmaster 192.168.150.101 7001
    可以看到sentinel已经联系到了7001这个节点,并且与其它几个哨兵也建立了链接。哨兵信息如下:
    ● 27001:Sentinel ID是8e91bd24ea8e5eb2aee38f1cf796dcb26bb88acf
    ● 27002:Sentinel ID是5bafeb97fc16a82b431c339f67b015a51dad5e4f
    ● 27003:Sentinel ID是56546568a2f7977da36abd3d2d7324c6c3f06b8d
    2.3.演示failover
    接下来,我们演示一下当主节点故障时,哨兵是如何完成集群故障恢复(failover)的。
    停止r1
    docker stop r1
    登录r2,查看集群状态:

稍微等待一段时间后,会发现sentinel节点触发了failover:
继续查看集群状态发现主节点为r2

3.Redis分片集群
主从模式可以解决高可用、高并发读的问题。但依然有两个问题没有解决:
● 海量数据存储
● 高并发写
要解决这两个问题就需要用到分片集群了。分片的意思,就是把数据拆分存储到不同节点,这样整个集群的存储数据量就更大了。
Redis分片集群的结构如图:

分片集群特征:
● 集群中有多个master,每个master保存不同分片数据 ,解决海量数据存储问题
● 每个master都可以有多个slave节点 ,确保高可用
● master之间通过ping监测彼此健康状态 ,类似哨兵作用
● 客户端请求可以访问集群任意节点,最终都会被转发到数据所在节点
3.1.搭建分片集群
Redis分片集群最少也需要3个master节点,由于我们的机器性能有限,我们只给每个master配置1个slave,形成最小的分片集群:

计划部署的节点信息如下:
容器名 角色 IP 映射端口
r1 master 192.168.150.101 7001
r2 master 192.168.150.101 7002
r3 master 192.168.150.101 7003
r4 slave 192.168.150.101 7004
r5 slave 192.168.150.101 7005
r6 slave 192.168.150.101 7006
3.1.1.集群配置
分片集群中的Redis节点必须开启集群模式,一般在配置文件中添加下面参数:
port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
其中有3个我们没见过的参数:
● cluster-enabled:是否开启集群模式
● cluster-config-file:集群模式的配置文件名称,无需手动创建,由集群自动维护
● cluster-node-timeout:集群中节点之间心跳超时时间
一般搭建部署集群肯定是给每个节点都配置上述参数,不过考虑到我们计划用docker-compose部署,因此可以直接在启动命令中指定参数,偷个懒。
在虚拟机的/root目录下新建一个redis-cluster目录,然后在其中新建一个docker-compose.yaml文件,内容如下:
version: "3.2"

services:
r1:
image: redis
container_name: r1
network_mode: "host"
entrypoint: ["redis-server", "--port", "7001", "--cluster-enabled", "yes", "--cluster-config-file", "node.conf"]
r2:
image: redis
container_name: r2
network_mode: "host"
entrypoint: ["redis-server", "--port", "7002", "--cluster-enabled", "yes", "--cluster-config-file", "node.conf"]
r3:
image: redis
container_name: r3
network_mode: "host"
entrypoint: ["redis-server", "--port", "7003", "--cluster-enabled", "yes", "--cluster-config-file", "node.conf"]
r4:
image: redis
container_name: r4
network_mode: "host"
entrypoint: ["redis-server", "--port", "7004", "--cluster-enabled", "yes", "--cluster-config-file", "node.conf"]
r5:
image: redis
container_name: r5
network_mode: "host"
entrypoint: ["redis-server", "--port", "7005", "--cluster-enabled", "yes", "--cluster-config-file", "node.conf"]
r6:
image: redis
container_name: r6
network_mode: "host"
entrypoint: ["redis-server", "--port", "7006", "--cluster-enabled", "yes", "--cluster-config-file", "node.conf"]
注意:使用Docker部署Redis集群,network模式必须采用host
3.1.2.启动集群
进入/root/redis-cluster目录,使用命令启动redis:
docker-compose up -d
启动成功,可以通过命令查看启动进程:
ps -ef | grep redis

结果:

root 4822 4743 0 14:29 ? 00:00:02 redis-server :7002 [cluster]
root 4827 4745 0 14:29 ? 00:00:01 redis-server
:7005 [cluster]
root 4897 4778 0 14:29 ? 00:00:01 redis-server :7004 [cluster]
root 4903 4759 0 14:29 ? 00:00:01 redis-server
:7006 [cluster]
root 4905 4775 0 14:29 ? 00:00:02 redis-server :7001 [cluster]
root 4912 4732 0 14:29 ? 00:00:01 redis-server
:7003 [cluster]
可以发现每个redis节点都以cluster模式运行。不过节点与节点之间并未建立连接。
接下来,我们使用命令创建集群:

进入任意节点容器

docker exec -it r1 bash

然后,执行命令

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:7004 192.168.150.101:7005 192.168.150.101:7006
命令说明:
● redis-cli --cluster:代表集群操作命令
● create:代表是创建集群
● --cluster-replicas 1 :指定集群中每个master的副本个数为1
○ 此时节点总数 ÷ (replicas + 1) 得到的就是master的数量n。因此节点列表中的前n个节点就是master,其它节点都是slave节点,随机分配到不同master
输入命令后控制台会弹出下面的信息:

这里展示了集群中master与slave节点分配情况,并询问你是否同意。节点信息如下:
● 7001是master,节点id后6位是da134f
● 7002是master,节点id后6位是862fa0
● 7003是master,节点id后6位是ad5083
● 7004是slave,节点id后6位是391f8b,认ad5083(7003)为master
● 7005是slave,节点id后6位是e152cd,认da134f(7001)为master
● 7006是slave,节点id后6位是4a018a,认862fa0(7002)为master
输入yes然后回车。会发现集群开始创建,并输出下列信息:

接着,我们可以通过命令查看集群状态:
redis-cli -p 7001 cluster nodes
结果:

3.2.Java客户端连接分片集群
RedisTemplate底层同样基于lettuce实现了分片集群的支持,而使用的步骤与哨兵模式基本一致,参考2.5节:
1)引入redis的starter依赖
引入SpringDataRedis的依赖:


org.springframework.boot
spring-boot-starter-data-redis

2)配置分片集群地址
与传统单点模式不同,需要配置每个redis实例的地址,如下:
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

3)配置读写分离
还要配置读写分离,让java客户端将写请求发送到master节点,读请求发送到slave节点。定义一个bean即可:
@Bean
public LettuceClientConfigurationBuilderCustomizer clientConfigurationBuilderCustomizer(){
return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
}
这个bean中配置的就是读写策略,包括四种:
● MASTER:从主节点读取
● MASTER_PREFERRED:优先从master节点读取,master不可用才读取slave
● REPLICA:从slave节点读取
● REPLICA_PREFERRED:优先从slave节点读取,所有的slave都不可用才读取master

相关文章
|
23天前
|
人工智能 自然语言处理 达摩院
2025年12月,中国数字人平台介绍与全栈技术驱动及技术指南
2025年,数字人迈向“能力拟人”新阶段,从形象展示进化为具备感知与决策的智能体。选型需超越外观,聚焦交互效率、安全合规、行业适配与持续运营,打造真正可落地的数字化生产力。
|
3月前
|
SQL 关系型数据库 MySQL
MySQL权限管理:用户与权限控制详解
本文深入解析MySQL权限管理系统,涵盖用户体系、权限模型及实战技巧,帮助构建安全的数据库防线。
|
7天前
|
安全 PHP
PHP 8.2 只读类:编写更安全、更简洁的代码
PHP 8.2 只读类:编写更安全、更简洁的代码
|
人工智能
2025年人工智能与可持续发展国际学术会议 2025 International Conference on Artificial Intelligence and Sustainable Development (ICAISD 2025)
2025年人工智能与可持续发展国际学术会议 2025 International Conference on Artificial Intelligence and Sustainable Development (ICAISD 2025)
753 7
|
安全 Java 网络安全
Android远程连接和登录FTPS服务代码(commons.net库)
很多文章都介绍了FTPClient如何连接ftp服务器,但却很少有人说如何连接一台开了SSL认证的ftp服务器,现在代码来了。
408 2
|
传感器 物联网 芯片
PWM 在智能照明系统中的应用优势有哪些
PWM(脉冲宽度调制)在智能照明系统中应用广泛,其优势包括:精准控制亮度、色温调节灵活、节能高效、延长灯具寿命、响应速度快及成本低廉。这些特点使其成为智能照明的理想选择。
|
机器学习/深度学习 人工智能 自然语言处理
大模型强崩溃!Meta新作:合成数据有剧毒,1%即成LLM杀手
在人工智能领域,大型语言模型(LLMs)的快速发展令人瞩目,但递归生成数据可能导致“模型崩溃”。Meta的研究揭示,模型在训练过程中会逐渐遗忘低概率事件,导致数据分布偏差。即使少量合成数据(如1%)也会显著影响模型性能,最终导致崩溃。研究强调保留原始数据的重要性,并提出社区合作和技术手段来区分合成数据和真实数据。论文地址:https://www.nature.com/articles/s41586-024-07566-y
413 2
|
编解码 移动开发 前端开发
一款超强的手机屏幕投影工具
一款超强的手机屏幕投影工具
一款超强的手机屏幕投影工具
|
缓存 Docker 容器
【docker hub镜像源失效】2024年6月6日 docker 国内镜像源失效
【docker hub镜像源失效】2024年6月6日 docker 国内镜像源失效
|
SQL 消息中间件 缓存
回滚机制有多少种?它们的实现原理是什么?你确定都知道?
回滚是指当程序或数据出错时,将程序或数据恢复到最近的一个正确版本的行为。最常见的如事务回滚、代码库回滚、部署版本回滚、数据版本回滚、静态资源版本回滚等。通过回滚机制可保证系统在某些场景下的高可用。