Redis 分片集群搭建并使用 RedisTemplate 实现读写分离
上篇博客介绍了 Redis 哨兵集群的搭建,虽然已经解决了 master 在宕机后,与 slave 之间会自动切换的问题,但是其承载的数据量天花板仍然是单机的最大内存容量,无法承载更多的数据量。
本篇博客介绍 Redis 分片集群的搭建,集群内部拥有多个 master 节点,每个 master 存放的数据不一样,从而使 Redis 集群能够承载更多的数据量。每个 master 有自己的 slave 节点,在宕机后也能够与 slave 节点自动切换,保障 Redis 集群的高可用。
本篇博客的代码 Demo 仍然在前两篇博客的基础上拷贝过来,不需要修改任何代码,只需要修改一下 application.yml 文件,即可实现 RedisTemplate 连接分片集群实现读写分离的效果,在博客的最后会提供源代码的下载。
一、分片集群的搭建
Redis 分片集群的搭建非常简单,本篇博客搭建一个拥有 3 个 master 和 3 个 slave 的分片集群,主要分为 2 个步骤:首先启动 6 个 Redis 实例,然后运行以下创建集群的命令即可。本篇博客仍然使用虚拟机进行模拟搭建,我的虚拟机操作系统是 CentOS7(ip 地址是 192.168.136.128),已经安装好了 docker 和 docker-compose ,首先我们先创建好相关的目录,我创建的主目录是 /app/redis-cluster-slot ,具体结构如下:
上图是我已经搭建好的 Redis 分片集群目录结构,直接拿来用了。其中 dump.rdb 和 redis.log 是各个 Redis 服务启动后自动生成的,可以忽略。这里创建了 6 个子目录 redis6379、redis6479、redis6579、redis7379、redis7479、redis7579,里面用来存放每个 Redis 的配置文件、备份数据、日志。
由于每个 Redis 实例的配置文件,基本上一模一样,只是启动端口不一样而已,所以这里只列出一个即可:
protected-mode no
bind 0.0.0.0
save 900 1
save 300 10
save 60 10000
rdbcompression yes
dbfilename dump.rdb
dir /data
# 日志存放位置
logfile /data/redis.log
# 开启集群功能
cluster-enabled yes
# 集群的配置文件名称,不需要我们创建,由redis自己维护
cluster-config-file /tmp/nodes.conf
# 节点心跳失败的超时时间
cluster-node-timeout 5000
# 关闭 aof 日志备份
appendonly no
# 启动端口
port 6379
# 自定义密码
requirepass root
# 访问 master 节点时需要提供的密码
masterauth root
# 虚拟机会有多个 ip,这里指定具体一个 ip 地址
replica-announce-ip 192.168.136.128
以上列出的是 redis6379 目录下的配置文件,其端口是 6379,其它目录下的配置文件只需要改一下端口即可,端口与目录名称中的数字保持一致,配置文件中的其余部分一模一样。需要注意以下几点即可:
- cluster-enabled yes 表示开启集群功能
- cluster-config-file /tmp/nodes.conf 集群的配置文件名称,不需要我们创建,由redis自己维护
- cluster-node-timeout 5000 节点心跳失败的超时时间
- requirepass root 和 masterauth root 这里设置 redis 本身的密码,以及访问 master 节点的密码,由于集群中每个节点都有可能是 master 节点,因此如果 Redis 节点设置了访问密码的话,必须也要设置访问 master 节点的密码
- replica-announce-ip 192.168.136.128 本篇博客的集群搭建,仍然使用 docker 的 host 模式,因此这里指定虚拟机的 ip
然后在 /app/redis-cluster-slot 目录下,创建 docker-compose.yml 文件,内容如下:
version: "3.5"
services:
redis6379:
image: redis
container_name: redis6379
restart: always
privileged: true
network_mode: "host"
volumes:
- /app/redis-cluster-slot/redis6379/data:/data
- /app/redis-cluster-slot/redis6379/redis.conf:/etc/redis.conf
command:
redis-server /etc/redis.conf
redis6479:
image: redis
container_name: redis6479
restart: always
privileged: true
network_mode: "host"
volumes:
- /app/redis-cluster-slot/redis6479/data:/data
- /app/redis-cluster-slot/redis6479/redis.conf:/etc/redis.conf
command:
redis-server /etc/redis.conf
redis6579:
image: redis
container_name: redis6579
restart: always
privileged: true
network_mode: "host"
volumes:
- /app/redis-cluster-slot/redis6579/data:/data
- /app/redis-cluster-slot/redis6579/redis.conf:/etc/redis.conf
command:
redis-server /etc/redis.conf
redis7379:
image: redis
container_name: redis7379
restart: always
privileged: true
network_mode: "host"
volumes:
- /app/redis-cluster-slot/redis7379/data:/data
- /app/redis-cluster-slot/redis7379/redis.conf:/etc/redis.conf
command:
redis-server /etc/redis.conf
redis7479:
image: redis
container_name: redis7479
restart: always
privileged: true
network_mode: "host"
volumes:
- /app/redis-cluster-slot/redis7479/data:/data
- /app/redis-cluster-slot/redis7479/redis.conf:/etc/redis.conf
command:
redis-server /etc/redis.conf
redis7579:
image: redis
container_name: redis7579
restart: always
privileged: true
network_mode: "host"
volumes:
- /app/redis-cluster-slot/redis7579/data:/data
- /app/redis-cluster-slot/redis7579/redis.conf:/etc/redis.conf
command:
redis-server /etc/redis.conf
可以发现,docker-compose.yml 文件中,启动了 6 个 Redis 实例,但是彼此之间没有任何关系。我们运行 docker-compose up -d
先把 6 个 Redis 实例服务启动起来,使用 docker-compose ps
查看其运行状态:
由于采用 docker 的 host 模式部署,这里看不到启动端口,可以使用 netstat -tulnp | grep redis
查看:
下面开始使用 cluster 命令去创建分片集群。我使用 RDM 客户端工具测试,发现其不支持 cluster 命令。然后我又使用微软的 windows 版本的 redis-cli 测试,发现其版本太老,也不支持 cluster 命令,因此我们只能进入上面启动的其中一个 redis 容器中运行 cluster 命令去创建集群了。
我们就进入 redis6379 这个服务的容器中去创建分片集群吧:
首先运行 docker exec -it redis6379 bash
进入 redis6379 服务的容器中,然后运行以下命令创建分片集群:
redis-cli --cluster create --cluster-replicas 1 192.168.136.128:6379 192.168.136.128:6479 192.168.136.128:6579 192.168.136.128:7379 192.168.136.128:7479 192.168.136.128:7579 -a root
以上命令的参数说明:
- --cluster 表示执行的是集群命令,create 表示创建分片集群
- --cluster-replicas 1 表示集群中每个 master 节点有 1 个 slave 节点
- -a 表示访问每个 redis 实例的密码,本篇博客配置的访问 redis 的密码是 root
集群创建命令运行之后,系统会提示把最前面的 3 个 ip端口的节点作为主节点,后面的 3 个ip端口的节点作为 slave 节点,如果你认为没问题的话,输入 yes 即可,系统就会自动创建分片集群,最终效果去下所示:
可以发现每个 master 节点都分配了一定数量的 slots(插槽),Redis 的数据是存放在具体的某个 slot 中的,数据跟着 slot 走,而不是跟随具体的 Redis 节点或服务器走。如果添加了新的 master 节点后,可以迁移 slot,数据也将随着 slot 的迁移而迁移。对于 Redis 分片集群来说,一共拥有 16384 个 slot(序号为 0 到 16383)可以使用。
然后我们可以登录到任意一个 Redis 服务中,运行 cluster nodes
命令查看集群节点信息:
从上面可以看出,哪些是 master 节点,以及其拥有的 slot 范围,通过 slave 后面的很长的一串字符串,可以看出它所属的 master 节点。到此为止,Redis 的分片集群已经搭建成功。
你可以连接任意一个 redis 节点,master 和 slave 都可以,运行相关的 redis 读写命令,Redis 集群会根据 key 计算出 slot 值,然后切换到 slot 所在的节点去写入或者读取数据。如果你给 Redis 设置了密码的话,跳转到具体的 redis 节点后,会提示你先输入密码,才能写入或读取数据,可能体验不是很好,但实际上我们下面要使用 RedisTemplate 去访问才做分片集群的话,是很方便的,以为 RedisTemplate 内部切换不同的节点时会自动发送密码验证。
另外分片集群中某个 master 宕机的话,其所属的 slave 会自动切换为 master 节点,原来的 master 节点恢复后会变成 slave 节点。如果你想手动进行 master 和 slave 切换的话,也可以先使用客户端工具连接到 slave 节点,然后运行 cluster failover
命令即可。这里就不再进行演示了,大家可以自行验证。
二、RedisTemplate 操作分片集群实现读写分离
本篇博客仍然使用前两篇博客的 Demo 代码,一行代码都不需要更改,只需要更改配置文件即可。
这里仅仅列出 application.yml 配置文件的具体内容:
spring:
redis:
# 这里配置的是连接具体的 redis 节点的密码
password: root
# 把集群中的所有master节点和slave节点都配置上即可
cluster:
nodes:
- 192.168.136.128:6379
- 192.168.136.128:6479
- 192.168.136.128:6579
- 192.168.136.128:7379
- 192.168.136.128:7479
- 192.168.136.128:7579
jedis:
pool:
# 最大连接数
max-active: 10
# 最大空闲连接数
max-idle: 5
# 最小空闲
min-idle: 1
# 连接超时时间(毫秒)
max-wait: 3000
跟前篇博客的 Demo 运行情况相似,从控制台日志中,无法看出 RedisTemplate 是从哪个节点读取的数据
验证 RedisTemplate 操作分片集群实现读写分离的方法跟上篇博客的方案一样,这里就不再赘述。
本篇博客的源代码下载地址为:https://files.cnblogs.com/files/blogs/699532/springboot_redis_cluster3.zip