openEuler 系统使用 Docker Compose 容器化部署 Redis Cluster 集群
- Redis 的多种模式
- Redis-Alone 单机模式
- Redis 单机模式的优缺点
- Redis 高可用集群模式
- Redis-Master/Slaver 主从模式
- Redis-Master/Slaver 哨兵模式
- 哨兵模式监控的原理
- Redis 节点主客观下线标记
- Redis 节点主客观下线标记移除
- Redis-Cluster 模式
- Cluster 集群模式的原理
- Cluster 集群常见问题
- 【Question1】:数据分片怎么分?
- 【Question2】:数据分片之后怎么查,怎么写?
- 【Question3】:如何做到水平扩展?
- 【Question4】:如何做故障转移?
- Redis Cluster 部署环境说明
- Redis Cluster 集群规划
- 修改 Linux 系统 sysctl.conf 配置参数
- Dcoker Compose 部署 Redis Cluster 集群
- redis-compose.yaml 文件编写
- redis.conf 模板文件编写
- redis-build.sh 部署脚本编写
- redis-down.sh 卸载脚本编写
- 创建集群步骤
- 总结
Redis 的多种模式
在部署 Redis Cluster
集群的时候,我们来了解下 redis 提供了哪些模式。
Redis 提供多种部署模式,常见的有以下四种:
Redis-Alone
,单机模式;Redis-Master/Slaver
,主从复制模式;Redis-Sentinel
,哨兵模式;Redis-Cluster
,集群模式;
下面文章把 redis
这些模式统一划分为两类,分别是 基础模式
和 高可用集群模式
,接下来我们详细讲解这几种模式原理以及各自的优缺点。
Redis-Alone 单机模式
Redis-Alone
(单机模式),该模式最简单,就是安装一个 Redis
,启动起来,业务调用即可。
通常大不部分程序员 90%
的情况下基本都是从接触该模式开始学习 Redis
,该模式的使用场景是:例如在一个并非必须保证 Redis
高可用性的情况下,任何需要使用独立缓存的业务系统均可。
Redis 单机模式的优缺点
1、Redis-Alone
模式优点
- 部署简单,基本
0
成本。 - 成本低,没有备用节点,不需要其他的开支。
- 高性能,单机不需要同步数据,数据天然一致性。
2、Redis-Alone
模式缺点
- 存在单点故障问题,可靠性保证不是最佳,单节点有宕机的风险。
- 单机高性能受限于
CPU
的处理能力,Redis 4.x
以前是单线程的。
说明:Redis 是从 4.x 开始慢慢支持多线程的,直到 Redis6/7 后才稳定。
Redis 高可用集群模式
相对应 Redis-Alone
模式,务必保证 Redis
高可用性的情况下,推荐使用以下几种模式。
通常情况下,在中小型规模的业务系统中,一般使用 -Redis-Master/Slaver
(主从复制模式)和
Redis-Sentinel
(哨兵模式)即可满足需求,但是在中大型规模的业务系统中,还是推荐使用 Redis-Cluster
(集群模式)。
Redis-Master/Slaver 主从模式
Redis-Master/Slaver
(主从复制),是指将一台 Redis
服务器的数据,复制到其他的 Redis
服务器。
前者称为 主节点(master)
,后者称为 从节点(slave)
;特点是 数据复制是单向
的,只能由主节点到从节点。主节点用于写入数据,从节点用于读取数据。
说明:从节点的名在
redis5.0
之前叫做slave
,5.0
之后叫做replica
。
主从复制模式,这里我们采用 1主2从
共包含三个节点,一个主节点,两个从节点。
在同一台虚拟机中开启 3
个 redis
实例,模拟主从集群,规划配置如下信息如下:
IP:PORT | 角色 |
---|---|
172.17.97.27:6379 | master |
172.17.97.27:6380 | slaveof/replicaof |
172.17.97.27:6381 | slaveof/replicaof |
主从模式配置很简单,只需要在从节点配置主节点的 ip
和 端口号
即可。
slaveof <masterip> <masterport>
# 例如
# slaveof 172.17.97.27 6379
从上面很容易就想到一个问题,既然主从复制,意味着 master
和 slave
的数据都是一样的,有数据冗余问题。
在程序设计上,为了高可用性和高性能,是允许有冗余存在的。这点希望大家在设计系统的时候要考虑进去,不用为公司节省这一点资源。
对于追求极致用户体验的产品,是绝对不允许有宕机存在的。
主从模式在很多系统设计时都会考虑,一个 master
挂在多个 slave
节点,当 master
服务宕机,会 选举
产生一个新的 master
节点,从而保证服务的高可用性。
1、 Redis-Master/Slaver
(主从复制)的优点
- 一旦主节点宕机,
从节点
作为主节点
的备份
可以随时顶上来。 - 扩展
主节点
的读能力
,分担主节点读压力。 - 高可用基石:除了上述作用以外,主从复制还是
哨兵模式
和集群模式
能够实施的基础,因此说主从复制是Redis
高可用的基石。
2、 Redis-Master/Slaver
(主从复制)的缺点
- 一旦
主节点宕机
,从节点
晋升成主节点
,同时需要修改应用方
的主节点地址
,还需要命令所有从节点去复制新的主节点,整个过程需要人工干预
。 主节点
的写能力
受到单机的限制
。主节点
的存储能力
受到单机的限制
。
Redis-Master/Slaver 哨兵模式
继续追究上面的 Redis-Master/Slaver
(主从复制)模式,当主节点宕机之后,从节点是可以作为主节点顶上来,继续提供服务的。
但是会发现一个问题,主节点的 IP
已经变动了,此时应用服务还是拿着原主节点的地址去访问,这在生产环境就很尴尬了,整个过程得需要人工介入。
于是,在 Redis 2.8
版本开始引入了 哨兵(Redis-Sentinel)
这个概念。
在 主从复制集
的基础上,哨兵
实现了 自动化的故障恢复
。
此处规划信息如下,1个主节点,3个从节点和3个哨兵节点(一主三从三哨兵
):
如上图所示,哨兵节点由两部分组成,哨兵节点
和 数据节点
:
- 哨兵节点(
Sentinel
):哨兵系统由一个或多个哨兵节点组成,哨兵节点是特殊的 redis 节点
,不存储数据。 - 数据节点:主节点(
Master
)和从节点(Slaver
)都是数据节点(数据冗余)。
访问 redis
集群的数据都是通过哨兵集群的,哨兵监控整个 redis
集群。
一旦发现 redis
集群出现了问题,比如刚刚说的主节点挂了,从节点会顶上来。但是主节点地址变了,这时候应用服务无感知,也不用更改访问地址,因为 哨兵才是和应用服务做交互
的。
Sentinel
很好的解决了故障转移问题,在高可用方面又上升了一个台阶,当然 Sentinel
还有其他功能。
- 比如:主节点存活检测、主从运行情况检测、主从切换。
说明:
Redis
的Sentinel
最小配置是一主一从
,一个主节点至少得存在一个从节点。
哨兵模式监控的原理
每个 Sentinel
以 每秒钟一次的频率
,向它所有的 主服务器
、从服务器
以及其他 Sentinel 实例
发送一个 PING
命令。
Redis 节点主客观下线标记
- 如果一个 实例(
instance
)距离最后一次有效回复PING
命令的时间超过down-after-milliseconds
所指定的值,那么这个实例会被Sentinel
标记为主观下线
。 - 如果一个
主服务器
被标记为主观下线
,那么正在监视
这个主服务器
的所有Sentinel
节点,要以每秒一次的频率
确认该主服务器是否的确进入了主观下线
状态。 - 如果一个
主服务器
被标记为主观下线
,并且有足够数量
的Sentinel
(至少要达到配置文件指定的数量)在指定的时间范围
内同意这一判断,那么这个该主服务器被标记为客观下线
。
在一般情况下, 每个 Sentinel
会以 每 10 秒一次的频率
,向它已知的所有 主服务器
和 从服务器
发送 INFO
命令。
当一个 主服务器
被 Sentinel
标记为 客观下线
时,Sentinel
向 下线主服务器
的所有 从服务器
发送 INFO
命令的频率,会从10 秒一次改为每秒一次
。
Sentinel
和其他 Sentinel
协商 主节点
的状态,如果 主节点
处于 SDOWN
状态,则(进入选举机制
)投票自动选出新的主节点。将剩余的 从节点
指向 新的主节点
进行 数据复制
。
Redis 节点主客观下线标记移除
- 当没有足够数量的
Sentinel
同意主服务器
下线时,主服务器
的客观下线状态
就会被移除。 - 当
主服务器
重新向Sentinel
的PING
命令返回有效回复
时,主服务器
的主观下线状态
就会被移除。
1、Redis-Sentinel
(哨兵模式)的优点
- 哨兵模式是基于主从模式的,所有主从的优点,哨兵模式都具有。
- 主从可以自动切换,系统更健壮,可用性更高。
Sentinel
会不断的检查主服务器
和从服务器
是否正常运行。当被监控的某个Redis
服务器出现问题,Sentinel
通过API 脚本
向管理员或者其他的应用程序发送通知。
2、Redis-Sentinel
(哨兵模式)的缺点
Redis
较难支持在线扩容,对于集群容量达到上限时,在线扩容会变得很复杂。
Redis-Cluster 模式
主从复制集不能解决故障自动恢复问题,因此产生了哨兵模式(解决故障自动恢复),那到底为啥还要 集群模式(Redis-Cluster)
呢?
我们前面说过,主从复制集模式是 哨兵模式
和 集群模式
的基石,但是 主从
和 哨兵
都还有另外一些问题没有解决,比如:扩展性
,单个节点的 存储能力
和 访问能力
是有上限的。
Redis Sentinal
着眼于高可用性
,在master
宕机时会自动将slave
提升为master
,继续提供服务。Redis Cluster
着眼于扩展性
,在单个redis
内存不足时,使用Cluster
进行分片存储。
进入本篇文章的主题,也就是接下来要讲解的 Redis-Cluster
模式。
Redis Cluster
集群模式具有 高可用、可扩展性、分布式、数据分片存储、容错
等特性。
Cluster 集群模式的原理
通过 数据分片
的方式来进行 数据共享
问题,同时提供 数据复制
和 故障转移
功能。
之前的两种模式数据都是在一个节点上的,单个节点的存储是有上限的。集群模式就是把数据进行 分片存储
,当一个分片数据达到上限的时候,就分成多个分片。
Cluster 集群常见问题
【Question1】:数据分片怎么分?
集群的键空间被分割为 16384
个 slots
(即 hash
槽),通过 hash
的方式将数据分到不同的分片上的。
HASH_SLOT = CRC16(key) & 16384
CRC16
是一种循环校验算法,这里不是我们研究的重点,有兴趣可以看看。
这里用了 位运算
得到 取模
结果,位运算的速度高于取模运算。
提问:redis cluster 模式的 hash 槽为什么是分割为16384 个 slots ?
- 京东面试题(Redis):为啥 RedisCluster 设计成 16384 个槽,https://zhuanlan.zhihu.com/p/99037321
【Question2】:数据分片之后怎么查,怎么写?
读请求分配给 slave
节点,写请求分配给 master
,数据同步从 master
到 slave
节点。
读写分离提高并发能力,增加高性能。
【Question3】:如何做到水平扩展?
maste
节点可以做扩充,数据迁移 redis 内部自动完成。
当你新增一个 master
节点,需要做数据迁移,redis
服务不需要下线。
举个栗子:上面的有三个 master
节点,意味着 redis
的 hash 槽
被分为三个段,假设 三段
分别是 [0~ 7000],[7001~ 12000]、[12001~16383]
。
现在因为业务需要新增了一个 master
节点,四个节点共同占有 16384
个 slots
槽。
槽需要重新分配,数据也需要重新迁移,但是服务不需要下线。
redis-cluster
集群的重新分片由 redis
内部的管理软件 redis-trib
负责执行。redis
提供了进行重新分片的所有命令,redis-trib
通过向 主节点
发送命令来进行 重新分片
。
【Question4】:如何做故障转移?
假如途中红色的节点故障了,此时 master3
下面的 从节点
会通过 选举
产生一个 新的主节点
替换原来的故障节点。
此过程和 哨兵模式
的故障转移是一样的。
Redis Cluster 部署环境说明
Redis Cluster 集群规划
此处我们采用虚拟机一个节点容器化 6 主 6 从
组成的 Redis Cluster
模式,规划信息如下:
IP:Port | Linux | Redis version | Role |
---|---|---|---|
172.17.97.27:6479 | openEuler 22.03 lts x86_64 | redis:7.2.3-alpine3.18 | master |
172.17.97.27:6579 | openEuler 22.03 lts x86_64 | redis:7.2.3-alpine3.18 | master |
172.17.97.27:6679 | openEuler 22.03 lts x86_64 | redis:7.2.3-alpine3.18 | master |
172.17.97.27:6779 | openEuler 22.03 lts x86_64 | redis:7.2.3-alpine3.18 | slave/replica |
172.17.97.27:6879 | openEuler 22.03 lts x86_64 | redis:7.2.3-alpine3.18 | slave/replica |
172.17.97.27:6979 | openEuler 22.03 lts x86_64 | redis:7.2.3-alpine3.18 | slave/replica |
修改 Linux 系统 sysctl.conf 配置参数
注意:vm 环境 linux 系统修改
/etc/sysctl.conf
配置信息。
此处我们使用华为 openEuler 22.03 lts x86_64
系统,启动 redis
容器会出现如下 Redis 警告信息:
启动 Redis 警告:WARNING overcommit_memory is set to 0 Background save may fail under low memory condition.$ src/redis-server
# Server initialized
# WARNING overcommit_memory is set to 0!
Background save may fail under low memory condition.
To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot
or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
* Loading RDB produced by version 7.2.3
按照上面的提示信息,添加 vm.overcommit_memory = 1
。
编辑 /etc/sysctl.conf
配置信息如下:
[root@redis redis-cluster]# vi /etc/sysctl.conf # 执行命令使修改配置生效,或者 reboot 重启系统
[root@redis redis-cluster]# sysctl -p
kernel.sysrq = 0
net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.tcp_syncookies = 1
kernel.dmesg_restrict = 1
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
vm.overcommit_memory = 1
关于 /etc/sysctl.conf 配置说明,可以查看 =》 https://blog.csdn.net/cnwyt/article/details/118995722
我们先来看下在一个 VM
节点环境中,采用容器化部署的结果,部署成功输出如下信息:
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
完整信息输出如下:
/data # redis-cli --cluster create 172.17.97.27:6479 172.17.97.27:6579 172.17.97.27:6679 172.17.97.27:6779 172.17.97.27:6879 172.1
7.97.27:6979 --cluster-replicas 1 -a '123456'
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.17.97.27:6879 to 172.17.97.27:6479
Adding replica 172.17.97.27:6979 to 172.17.97.27:6579
Adding replica 172.17.97.27:6779 to 172.17.97.27:6679
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 4bf716f827a140f84bb59db89f8377c52b148348 172.17.97.27:6479slots:[0-5460] (5461 slots) master
M: 7e0aaa6b7759810a8a7a9d91720ed280f9c769a2 172.17.97.27:6579slots:[5461-10922] (5462 slots) master
M: c28eb34736d38df46e5f305f85e6245a5e88f04b 172.17.97.27:6679slots:[10923-16383] (5461 slots) master
S: db205fb27e8bd7a987f5263fc00ce5ce9d00a4c7 172.17.97.27:6779replicates 7e0aaa6b7759810a8a7a9d91720ed280f9c769a2
S: 2fe228281014ea89de0e86ee68922dfde6c3999b 172.17.97.27:6879replicates c28eb34736d38df46e5f305f85e6245a5e88f04b
S: 741eec69159a16b74c73e5a981d1a11307b41967 172.17.97.27:6979replicates 4bf716f827a140f84bb59db89f8377c52b148348
Can I set the above configuration? (type 'yes' to accept): 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 172.17.97.27:6479)
M: 4bf716f827a140f84bb59db89f8377c52b148348 172.17.97.27:6479slots:[0-5460] (5461 slots) master1 additional replica(s)
M: c28eb34736d38df46e5f305f85e6245a5e88f04b 172.17.97.27:6679slots:[10923-16383] (5461 slots) master1 additional replica(s)
S: 741eec69159a16b74c73e5a981d1a11307b41967 172.17.97.27:6979slots: (0 slots) slavereplicates 4bf716f827a140f84bb59db89f8377c52b148348
S: db205fb27e8bd7a987f5263fc00ce5ce9d00a4c7 172.17.97.27:6779slots: (0 slots) slavereplicates 7e0aaa6b7759810a8a7a9d91720ed280f9c769a2
S: 2fe228281014ea89de0e86ee68922dfde6c3999b 172.17.97.27:6879slots: (0 slots) slavereplicates c28eb34736d38df46e5f305f85e6245a5e88f04b
M: 7e0aaa6b7759810a8a7a9d91720ed280f9c769a2 172.17.97.27:6579slots:[5461-10922] (5462 slots) master1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
从上面集群输出的信息,我们可以看到有两个 [Warning]
信息,分别如下:
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe
.(在命令行界面上使用带有 “-a” 或 “-u” 选项的密码可能不安全。)[WARNING] Some slaves are in the same host as their master
. ([警告]某些从属服务器与其主服务器位于同一主机中。)
[Warning]/警告
信息说明:
- 第一点是我们集群中 redis 节点设置的密码过于简单
'123456'
,生产环境建议设置复杂度更高的密码; - 第二点是因为我们采用一个
VM
节点,然后容器化 6 个 redis 节点
模拟的redis-cluster
集群,所以位于同一个宿主机环境中。正式生产环境推荐每个redis
节点采用独立环境的宿主机搭建。
我们前面说过,redis-cluster
集群模式是基于 主从复制集
的基础上,主要是解决了 扩展性
问题,是集群更佳健壮和高可用,相应的数据采用分片存储,redis-cluster
集群模式 默认是 16384 个 (hash 槽)slots
,从上面的信息可以清晰的看到。
- 主节点:
- Master[0] 172.17.97.27:6479 -> Slots 0 - 5460 - Master[1] 172.17.97.27:6579 -> Slots 5461 - 10922 - Master[2] 172.17.97.27:6679 -> Slots 10923 - 16383
- 从节点:
- Adding replica 172.17.97.27:6879 to 172.17.97.27:6479- Adding replica 172.17.97.27:6979 to 172.17.97.27:6579- Adding replica 172.17.97.27:6779 to 172.17.97.27:6679
接下来我们详细叙述,如何采用容器化 docker compose
部署 redis cluster
集群模式。
Dcoker Compose 部署 Redis Cluster 集群
依据上面 redis
使用 6
节点(三主三从
)的规划,在 vm 宿主机中新建目录 redis-cluster
,所属路径 /home/jeff/docker/redis-cluster
:
cd /home/jeff/
mkdir docker
cd ./docker
mkdir redis-cluster
准备好文件夹目录后,在 redis-cluster
文件夹中添加如下相关文件,目录文件展示如下:
注意:文件
redis-build.sh
和redis-down.sh
给可执行权限,命令操作如下:
chmod +x redis-build.sh redis-down.sh
redis-compose.yaml 文件编写
version: '3.8'
services:redis6479:network_mode: 'host'image: redis:7.2.3-alpine3.18container_name: redis6479restart: alwayscommand: ["redis-server", "/usr/local/etc/redis/redis.conf"]logging:driver: 'json-file'options:max-size: '3g'volumes:- ./redis6479/data:/data- ./redis6479/redis.conf:/usr/local/etc/redis/redis.conf- ./redis6479/logs:/logsredis6579:network_mode: 'host'image: redis:7.2.3-alpine3.18container_name: redis6579restart: alwayscommand: ["redis-server", "/usr/local/etc/redis/redis.conf"]logging:driver: 'json-file'options:max-size: '3g'volumes:- ./redis6579/data:/data- ./redis6579/redis.conf:/usr/local/etc/redis/redis.conf- ./redis6579/logs:/logsredis6679:network_mode: 'host'image: redis:7.2.3-alpine3.18container_name: redis6679restart: alwayscommand: ["redis-server", "/usr/local/etc/redis/redis.conf"]logging:driver: 'json-file'options:max-size: '3g'volumes:- ./redis6679/data:/data- ./redis6679/redis.conf:/usr/local/etc/redis/redis.conf- ./redis6679/logs:/logsredis6779:network_mode: 'host'image: redis:7.2.3-alpine3.18container_name: redis6779restart: alwayscommand: ["redis-server", "/usr/local/etc/redis/redis.conf"]logging:driver: 'json-file'options:max-size: '3g'volumes:- ./redis6779/data:/data- ./redis6779/redis.conf:/usr/local/etc/redis/redis.conf- ./redis6779/logs:/logsredis6879:network_mode: 'host'image: redis:7.2.3-alpine3.18container_name: redis6879restart: alwayscommand: ["redis-server", "/usr/local/etc/redis/redis.conf"]logging:driver: 'json-file'options:max-size: '3g'volumes:- ./redis6879/data:/data- ./redis6879/redis.conf:/usr/local/etc/redis/redis.conf- ./redis6879/logs:/logsredis6979:network_mode: 'host'image: redis:7.2.3-alpine3.18container_name: redis6979restart: alwayscommand: ["redis-server", "/usr/local/etc/redis/redis.conf"]logging:driver: 'json-file'options:max-size: '3g'volumes:- ./redis6979/data:/data- ./redis6979/redis.conf:/usr/local/etc/redis/redis.conf- ./redis6979/logs:/logs
redis.conf 模板文件编写
此处写一个通用格式化的 redis.conf
配置文件,后续使用 sh
脚本为每个 redis
节点 copy
一个副本并修改成对应节点的配置信息。
# 修改为后台启动
#daemonize yes
# 修改端口号
port 6379
# 指定数据文件存储位置
#dir /usr/local/redis-app/6379/
# 开启集群模式
cluster-enabled yes
# 集群节点信息文件配置
cluster-config-file nodes-6379.conf
# 集群节点超时间
cluster-node-timeout 15000
# 去掉bind绑定地址
# bind 127.0.0.1 -::1 (这里没写错就是加#注释掉bind配置)
# 关闭保护模式
#protected-mode no
# 开启aof模式持久化
appendonly yes
# 设置连接Redis需要密码123(选配)
requirepass 123456
# 设置Redis节点与节点之间访问需要密码123(选配)
masterauth 123456
注意:生产环境为了安全性保障,redis 的访问密码尽量设置复杂度高一些。
redis-build.sh 部署脚本编写
基于上面我们编写的 redis-compose.yaml
文件编写内容,编写自动化部署的 redis-build.sh
脚本如下:
#!/bin/bash
echo "1.创建 redis-app 目录,路径 /usr/local/redis-app/"
cd /usr/local/
sudo mkdir ./redis-appecho "2.准备 redis6479 节点目录文件"
cd /usr/local/redis-app/
sudo mkdir ./6479
cd /home/jeff/docker/redis-cluster;
sudo mkdir ./redis6479
cp -f ./redis.conf ./redis6479/redis.conf;
sed -i "s/6379/6479/g" ./redis6479/redis.conf;
cd ./redis6479
sudo rm -rf ./redis6479/data;
sudo rm -rf ./redis6479/logs;echo "3.准备 redis6579 节点目录文件"
cd /usr/local/redis-app/
sudo mkdir ./6579
cd /home/jeff/docker/redis-cluster;
sudo mkdir ./redis6579
cp -f ./redis.conf ./redis6579/redis.conf;
sed -i "s/6379/6579/g" ./redis6579/redis.conf;
cd ./redis6579
sudo rm -rf ./redis6579/data;
sudo rm -rf ./redis6579/logs;echo "4.准备 redis6679 节点目录文件"
cd /usr/local/redis-app/
sudo mkdir ./6679
cd /home/jeff/docker/redis-cluster;
sudo mkdir ./redis6679
cp -f ./redis.conf ./redis6679/redis.conf;
sed -i "s/6379/6679/g" ./redis6679/redis.conf;
cd ./redis6679
sudo rm -rf ./redis6679/data;
sudo rm -rf ./redis6679/logs;echo "5.准备 redis6779 节点目录文件"
cd /usr/local/redis-app/
sudo mkdir ./6779
cd /home/jeff/docker/redis-cluster;
sudo mkdir ./redis6779
cp -f ./redis.conf ./redis6779/redis.conf;
sed -i "s/6379/6779/g" ./redis6779/redis.conf;
cd ./redis6779
sudo rm -rf ./redis6779/data;
sudo rm -rf ./redis6779/logs;echo "6.准备 redis6879 节点目录文件"
cd /usr/local/redis-app/
sudo mkdir ./6879
cd /home/jeff/docker/redis-cluster;
sudo mkdir ./redis6879
cp -f ./redis.conf ./redis6879/redis.conf;
sed -i "s/6379/6879/g" ./redis6879/redis.conf;
cd ./redis6879
sudo rm -rf ./redis6879/data;
sudo rm -rf ./redis6879/logs;echo "7.准备 redis6979 节点目录文件"
cd /usr/local/redis-app/
sudo mkdir ./6979
cd /home/jeff/docker/redis-cluster;
sudo mkdir ./redis6979
cp -f ./redis.conf ./redis6979/redis.conf;
sed -i "s/6379/6979/g" ./redis6979/redis.conf;
cd ./redis6979
sudo rm -rf ./redis6979/data;
sudo rm -rf ./redis6979/logs;echo "8.指定 redis-compose.yaml 文件执行 docker compose 部署"
cd /home/jeff/docker/redis-cluster;
docker compose -f redis-compose.yaml up -d
执行构建脚本:
[root@redis redis-cluster]# ./redis-build.sh
redis-down.sh 卸载脚本编写
此处主要是卸载 docker compose
部署的 redis
节点及相关的文件目录,redis-down.sh
文件编写信息如下:
#!/bin/bash
cd /home/jeff/docker/redis-cluster;echo "停止并移除 redis 容器、网络、镜像和数据卷,打印版本并退出"
docker compose -f ./redis-compose.yaml down -v;echo "清理 redis 节点文件夹"
sudo rm -rf ./redis6479/ ./redis6579/ ./redis6679/ ./redis6779/ ./redis6879/ ./redis6979/;echo "清理 redis-app 文件夹"
cd /usr/local/;
sudo rm -rf ./redis-app/;
执行卸载脚本:
[root@redis redis-cluster]# ./redis-down.sh
创建集群步骤
上面基本环境(相关部署文件、配置文件和 sh
脚本)准备好后,开始执行部署计划,操作步骤如下:
- 执行
redis-build.sh
部署redis
容器节点;
[root@redis redis-cluster]# ./redis-build.sh
- 随机进入一个规划的
master
节点,并创建集群;
# 进入 master 节点
docker container exec -it redis6479 /bin/sh
# 创建 redis-cluster 集群
redis-cli --cluster create 172.17.97.27:6479 172.17.97.27:6579 172.17.97.27:6679 172.17.97.27:6779 172.17.97.27:6879 172.1
7.97.27:6979 --cluster-replicas 1 -a '123456'
创建 redis-cluster
集群参数说明:
--cluster create ip:port
创建集群,多个节点空格分开;--cluster-replicas
设置master
节点的副本集数,即主节点跟随的从节点数量;-a
设置redis-cluster
节点访问的密码;
查看 docker
进入 container
(容器)帮助信息:
[root@redis redis-cluster]# docker container exec --helpUsage: docker container exec [OPTIONS] CONTAINER COMMAND [ARG...]Execute a command in a running containerAliases:docker container exec, docker execOptions:-d, --detach Detached mode: run command in the background--detach-keys string Override the key sequence for detaching a container-e, --env list Set environment variables--env-file list Read in a file of environment variables-i, --interactive Keep STDIN open even if not attached--privileged Give extended privileges to the command-t, --tty Allocate a pseudo-TTY-u, --user string Username or UID (format: "<name|uid>[:<group|gid>]")-w, --workdir string Working directory inside the container
详细执行部署环节输出信息如下:
- 1、
compose
文件创建redis
节点容器成功,输出信息如下:
[root@redis redis-cluster]# pwd
/home/jeff/docker/redis-cluster
[root@redis redis-cluster]# ls
redis-build.sh redis-compose.yaml redis.conf redis-down.sh
[root@redis redis-cluster]# ./redis-build.sh
1.创建 redis-app 目录,路径 /usr/local/redis-app/
2.准备 redis6479 节点目录文件
3.准备 redis6579 节点目录文件
4.准备 redis6679 节点目录文件
5.准备 redis6779 节点目录文件
6.准备 redis6879 节点目录文件
7.准备 redis6979 节点目录文件
8.指定 redis-compose.yaml 文件执行 docker compose 部署
[+] Running 6/6✔ Container redis6479 Started 2.8s ✔ Container redis6679 Started 2.6s ✔ Container redis6779 Started 2.8s ✔ Container redis6879 Started 2.8s ✔ Container redis6579 Started 2.7s ✔ Container redis6979 Started 2.8s
- 2、查看
docker compose
列表信息:
[root@redis redis-cluster]# docker compose ls
NAME STATUS CONFIG FILES
redis-cluster running(6) /home/jeff/docker/redis-cluster/redis-compose.yaml
[root@redis redis-cluster]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4e8d63ac3c32 redis:7.2.3-alpine3.18 "docker-entrypoint.s…" 7 minutes ago Up 7 minutes redis6979
cd434dba60ef redis:7.2.3-alpine3.18 "docker-entrypoint.s…" 7 minutes ago Up 7 minutes redis6579
2905135c4a71 redis:7.2.3-alpine3.18 "docker-entrypoint.s…" 7 minutes ago Up 7 minutes redis6779
ee9613dc1b5f redis:7.2.3-alpine3.18 "docker-entrypoint.s…" 7 minutes ago Up 7 minutes redis6879
481cc70b8c5d redis:7.2.3-alpine3.18 "docker-entrypoint.s…" 7 minutes ago Up 7 minutes redis6679
e24b2c8f2d87 redis:7.2.3-alpine3.18 "docker-entrypoint.s…" 7 minutes ago Up 7 minutes redis6479
- 3、进入容器创建
redis-cluster
集群信息如下:
[root@redis redis-cluster]# docker container exec -it redis6479 /bin/sh
/data # redis-cli --cluster create 172.17.97.27:6479 172.17.97.27:6579 172.17.97.27:6679 172.17.97.27:6779 172.17.97.27:6879 172.17.97.27:6979 --cluster-replicas 1 -a '123456'
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.17.97.27:6879 to 172.17.97.27:6479
Adding replica 172.17.97.27:6979 to 172.17.97.27:6579
Adding replica 172.17.97.27:6779 to 172.17.97.27:6679
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 7aaf8e48ca3807ede36dbec999dacbf5f8640650 172.17.97.27:6479slots:[0-5460] (5461 slots) master
M: ef9705329a431960c5f89d7e4928b1fda90f77f1 172.17.97.27:6579slots:[5461-10922] (5462 slots) master
M: ccf56f0a5d50c34337586c9c1dc6d00ce6c7ef82 172.17.97.27:6679slots:[10923-16383] (5461 slots) master
S: d2b927276d4f603c05f66b5148553ab0ee06be73 172.17.97.27:6779replicates ccf56f0a5d50c34337586c9c1dc6d00ce6c7ef82
S: 9329e3afdc5bc2bff031770efa3a7168ef1a0b83 172.17.97.27:6879replicates 7aaf8e48ca3807ede36dbec999dacbf5f8640650
S: bbc04f53247738b0edaa8efa2b86daef072a2989 172.17.97.27:6979replicates ef9705329a431960c5f89d7e4928b1fda90f77f1
Can I set the above configuration? (type 'yes' to accept): 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 172.17.97.27:6479)
M: 7aaf8e48ca3807ede36dbec999dacbf5f8640650 172.17.97.27:6479slots:[0-5460] (5461 slots) master1 additional replica(s)
S: d2b927276d4f603c05f66b5148553ab0ee06be73 172.17.97.27:6779slots: (0 slots) slavereplicates ccf56f0a5d50c34337586c9c1dc6d00ce6c7ef82
M: ccf56f0a5d50c34337586c9c1dc6d00ce6c7ef82 172.17.97.27:6679slots:[10923-16383] (5461 slots) master1 additional replica(s)
S: bbc04f53247738b0edaa8efa2b86daef072a2989 172.17.97.27:6979slots: (0 slots) slavereplicates ef9705329a431960c5f89d7e4928b1fda90f77f1
M: ef9705329a431960c5f89d7e4928b1fda90f77f1 172.17.97.27:6579slots:[5461-10922] (5462 slots) master1 additional replica(s)
S: 9329e3afdc5bc2bff031770efa3a7168ef1a0b83 172.17.97.27:6879slots: (0 slots) slavereplicates 7aaf8e48ca3807ede36dbec999dacbf5f8640650
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
- 4、命令连接到
redis-cluster
集群
redis-cli -c -h 172.17.97.27 -p 6479 -a '123456' --raw
Warning: Using a password with ‘-a’ or ‘-u’ option on the command line interface may not be safe.
- 5、查看
redis-cluster
集群状态
172.17.97.27:6479> cluster nodes
d2b927276d4f603c05f66b5148553ab0ee06be73 172.17.97.27:6779@16779 slave ccf56f0a5d50c34337586c9c1dc6d00ce6c7ef82 0 1699594804000 3 connected
ccf56f0a5d50c34337586c9c1dc6d00ce6c7ef82 172.17.97.27:6679@16679 master - 0 1699594806108 3 connected 10923-16383
bbc04f53247738b0edaa8efa2b86daef072a2989 172.17.97.27:6979@16979 slave ef9705329a431960c5f89d7e4928b1fda90f77f1 0 1699594804098 2 connected
ef9705329a431960c5f89d7e4928b1fda90f77f1 172.17.97.27:6579@16579 master - 0 1699594805103 2 connected 5461-10922
9329e3afdc5bc2bff031770efa3a7168ef1a0b83 172.17.97.27:6879@16879 slave 7aaf8e48ca3807ede36dbec999dacbf5f8640650 0 1699594803000 1 connected
7aaf8e48ca3807ede36dbec999dacbf5f8640650 172.17.97.27:6479@16479 myself,master - 0 1699594804000 1 connected 0-5460
172.17.97.27:6479> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:746
cluster_stats_messages_pong_sent:748
cluster_stats_messages_sent:1494
cluster_stats_messages_ping_received:743
cluster_stats_messages_pong_received:746
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:1494
total_cluster_links_buffer_limit_exceeded:0
至此,我们规划的 1 VM 宿主机 6 redis 节点
规格(三主三从
)模式的 redis-cluster
集群就部署完成了。
总结
每种模式都有各自的优缺点,在实际使用场景中要根据业务特点去选择合适的模式。
redis
是一个非常常用的中间件,作为一个使用者来说,学习成本一点不高。
如果作为一个很好的中间件去研究的话,还是有很多值得学习和借鉴的地方。比如 redis 的各种数据结构(动态字符串、跳跃表、集合、字典等)、高效的内存分配(jemalloc)、高效的IO模型等等。
每个点都可以深入研究,在后期设计高并发、高可用系统的时候融入进去。