openEuler 系统使用 Docker Compose 容器化部署 Redis Cluster 集群
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 配置参数
- Docker 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
集群模式。
Docker 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模型等等。
每个点都可以深入研究,在后期设计高并发、高可用系统的时候融入进去。
相关文章:

openEuler 系统使用 Docker Compose 容器化部署 Redis Cluster 集群
openEuler 系统使用 Docker Compose 容器化部署 Redis Cluster 集群 Redis 的多种模式Redis-Alone 单机模式Redis 单机模式的优缺点 Redis 高可用集群模式Redis-Master/Slaver 主从模式Redis-Master/Slaver 哨兵模式哨兵模式监控的原理Redis 节点主客观下线标记Redis 节点主客观…...

C# ZXing 二维码,条形码生成与识别
C# ZXing 二维码条形码生成识别 安装ZXing使用ZXing生成条形码生成二维码生成带Logo的二维码识别二维码、条形码 安装ZXing NuGet搜索ZXing安装ZXing.Net包 使用ZXing using ZXing; using ZXing.Common; using ZXing.QrCode; using ZXing.QrCode.Internal; 生成条形码 //…...
[vim]Python编写插件学习笔记1 - 开始
0 环境 Windows 11 22H2gVim82 (D:/ProgramFiles/Vim)Python311 (D:/ProgramFiles/Python311)Vundle v0.10.2 1 Vim 支持 Python gVim82 默认配置中,使用的是 Python3.8。 但我的环境安装的是 Python3.11,且不是安装在默认路径下。虽然添加了 PATH 环…...
深入理解JVM虚拟机第二十篇:静态变量和局部变量的对比以及栈帧对垃圾回收的意义以及JVM中栈帧与堆内对象的应用关系图示
大神链接:作者有幸结识技术大神孙哥为好友,获益匪浅。现在把孙哥视频分享给大家。 孙哥链接:孙哥个人主页 作者简介:一个颜值99分,只比孙哥差一点的程序员 本专栏简介:话不多说,让我们一起干翻JVM 本文章简介:话不多说,让我们讲清楚静态变量和局部变量的对比 文章目录…...

【计算机网络基础实验】实验二 有线IP互通网络实践
任务一 IP路由协议实现企业路由器通信 目录如下: 任务一 IP路由协议实现企业路由器通信2.1.1 任务描述2.1.2 任务目的2.1.3 任务实施实验需求实验步骤步骤1:更改每台设备的名称步骤2: 给R1接口配置相应IP地址步骤3: 给R2接口配置相…...

【Orangepi Zero2 全志H616】驱动串口实现Tik Tok—VUI(语音交互)
一、编程实现语音和开发板通信 wiringpi库源码demo.c 二、基于前面串口的代码修改实现 uartTool.huartTool.cuartTest.c 三、ADB adb控制指令 四、手机接入Linux热拔插相关 a. 把手机接入开发板 b. 安装adb工具,在终端输入adb安装指令: sudo apt-g…...

【Spring】静态代理
例子: 租房子 角色: 我 (I ) 中介( Proxy ) 房东( host ) Rent 接口 package org.example;public interface Rent {void rent(); }房东 package org.example;public class Host implements Rent{Overridepublic void rent() …...
tomcat web.xml文件中servlet的load-on-startup
先看一个例子: <servlet><description>JAX-WS endpoint - restful</description><display-name>restful</display-name><servlet-name>restful-addnumbers</servlet-name><servlet-class>com.sun.xml.ws.transpor…...
记chrome打不开网址,无法搜索问题
打开网址解决办法 2023关于chrome谷歌浏览器无法正常上网问题,解决办法,亲测有效 下载插件,解压后拖入chrome的扩展程序中,可以打开国内网址 google引擎搜索解决办法 打开无痕浏览 (不知道什么原理,可…...

Spring面试题:(五)Spring注解开发@Component,@Autowired,@Bean,@Configuration
Bean基本注解 spring提供注解的版本 Component注解替代bean标签 bean其它属性的相关注解: scope 替代scopelazy 替代lazy-initPostConstruct 替代init-methodPreDestroy 替代destroy-method 使用Component注解的前提是开启注解扫描 衍生注解Repository,Servi…...

【Qt-23】ui界面设计-ToolBar
1、ToolBar 右击主窗体添加工具栏 新建动作,可设置图标,图标有本地文件和资源两种方式。 修改toolButtonStyle的属性,可设置图标与汉字显示的方式。 页面跳转: connect(ui->action, SIGNAL(triggered()), this, SLOT(openWid…...
nodejs 异步架构
nodejs的核心之一就是非阻塞的异步IO,于是想知道它是怎么实现的,挖了下nodejs源码,找到些答案,在此跟大家分享下。首先,我用了一段js代码test-fs-read.js做测试,代码如下: var path require(pa…...

腾讯云优惠券介绍、作用、领取方法及使用教程
随着云计算技术的发展,越来越多的企业和个人选择使用云服务进行数据存储、计算等业务。腾讯云作为国内知名的云服务商,提供了一整套完善的云解决方案,并不定期发放优惠券以吸引更多的客户。本文将为大家详细介绍腾讯云优惠券的作用、领取方法…...

浅谈智能变电站自动化系统的应用与产品选型
安科瑞电气股份有限公司 上海嘉定 201801 摘要:现如今,智能变电站发展已经成为了电力系统发展过程中的内容,如何提高智能变电站的运行效率也成为电力系统发展的一个重要目标,为了能够更好地促进电力系统安全稳定运行,…...

适用于初学者的 .NET MAUI
适用于初学者的 .NET MAUI | Microsoft Learn 记录微软Learn中用到的代码。文章比较粗糙,大部分是项目代码粘贴。想详细学习的可到上面的链接学习,代码可以从这里复制后直接运行。 练习中一共有两个页面: 1、MainPage.xaml 用于添加列表中的…...
Web3项目灵魂所在之智能合约编写(Web3项目一实战之二)
正如标题所言,为什么将智能合约称为Web3项目的灵魂所在呢?其实,智能合约好比是传统App的服务器端,若服务器端宕机了,App也就僵死了。 假使您正在浏览本篇文章时,对智能合约还不是很了解,或者说是只知其名不知其意的话,那么,烦请您移步我另外一篇关于 区块链中的智能合…...

python-jupyter实现OpenAi语音对话聊天
1.安装jupyter 这里使用的是jupyter工具,安装时需要再cmd执行如下命令,由于直接执行pip install jupyter会很慢,咱们直接使用国内源 pip install --user jupyter -i http://pypi.tuna.tsinghua.edu.cn/simple/ --trusted-host pypi.tuna.t…...

恒源云之oss上传数据、云台下载数据
目录 一、本地cmd上传数据二、使用云平台下载数据 一、本地cmd上传数据 需要下载恒源云客户端oss需要先将数据(代码、数据集)压缩成zip文件。 本地cmd打开oss,测试是否安成功 oss输入oss命令,并正确输入账号密码 oss login在个人…...
大数据-之LibrA数据库系统告警处理(ALM-12039 GaussDB主备数据不同步)
告警解释 GaussDB主备数据不同步,系统每10秒检查一次主备数据同步状态,如果连续6次查不到同步状态,或者同步状态异常,产生告警。 当主备数据同步状态正常,告警恢复。 告警属性 告警ID 告警级别 可自动清除 12039…...
【左程云算法全讲6】链表相关
系列综述: 💞目的:本系列是个人整理为了秋招面试的,整理期间苛求每个知识点,平衡理解简易度与深入程度。 🥰来源:材料主要源于左程云算法课程进行的,每个知识点的修正和深入主要参考…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...

linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...