Appearance
Redis
编译安装
下载源码:https://github.com/redis/redis/releases
安装依赖
bash
$ yum -y install gcc gcc-c++ make jemalloc-devel
# 还有问题尝试执行
$ yum groupinstall "Development Tools"如果报错没有
jemalloc/jemalloc.h,使用命令make MALLOC=libc PREFIX=/usr/local/redis install用libc也行
解压
bash
$ tar -xf redis-7.0.14.tar.gz进入目录
bash
$ cd redis-7.0.14编译
bash
$ make && make install编译后默认写入到
/usr/local/bin目录下,需要指定目录参考:bash$ make PREFIX=/usr/local/redis && make install PREFIX=/usr/local/redis这种方式编译后路径会变为:
/usr/local/redis/bin
复制配置文件
bash
$ mkdir /etc/redis
$ cp redis.conf /etc/redis/添加systemctl
bash
$ vi /etc/systemd/system/redis.servicebash
[Unit]
Description=Redis
After=network.target
[Service]
Type=simple
PIDFile=/var/run/redis_6379.pid
ExecStart=/usr/local/bin/redis-server /etc/redis/redis.conf
ExecReload=/usr/local/bin/redis-server -s reload
ExecStop=/usr/local/bin/redis-server -s stop
TimeoutStartSec=60
PrivateTmp=true
[Install]
WantedBy=multi-user.targetbash
$ systemctl daemon-reload
$ systemctl enable redis
$ systemctl disable redis
$ systemctl start redis
$ systemctl stop redis
$ systemctl restart redis
$ systemctl status redis
$ systemctl list-units --type=service # 查看所有已启动的服务Redis主从复制
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器
- 前者称为主节点(Master),后者称为从节点(Slave)
- 数据的复制是单向的,只能由主节点到从节点
默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点
主从复制的作用
数据冗余:主从复制实现了数据的 热备份 ,是持久化之外的一种数据冗余方式。
故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的 冗余 。
负载均衡:在主从复制的基础上,配合 读写分离 ,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在 写少读多 的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
高可用基石:除了上述作用以外,主从复制还是 哨兵 和 集群 能够实施的基础,因此说主从复制是Redis高可用的基础。
主从复制的流程
【1】若启动一个Slave机器进程,则它会向Master机器发送一个“sync command”命令,请求同步连接。
【2】无论是第一次连接还是重新连接,Master机器都会启动一个后台进程,将数据快照保存到数据文件中(执行rdb操作),同时Master还会记录修改数据的所有命令并缓存在数据文件中。
【3】后台进程完成缓存操作之后,Maste机器就会向Slave机器发送数据文件,Slave端机器将数据文件保存到硬盘上,然后将其加载到内存中,接着Master机器就会将修改数据的所有操作一并发送给Slave端机器。若Slave出现故障导致宕机,则恢复正常后会自动重新连接。
【4】Master机器收到Slave端机器的连接后,将其完整的数据文件发送给Slave端机器,如果Mater同时收到多个Slave发来的同步请求,则Master会在后台启动一个进程以保存数据文件,然后将其发送给所有的Slave端机器,确保所有的Slave端机器都正常。
只要连接/重新连接master,一次完全同步(全量复制)将被自动执行
主从复制搭建
Master节点Redis配置文件
bash
$ vi /etc/redis/6379.conf
bind 0.0.0.0 # 修改bind 项,0.0.0.0监听所有网段
daemonize yes # 开启守护进程
logfile /var/log/redis_6379.log # 指定日志文件目录
dir /var/lib/redis/6379 # 指定工作目录
appendonly yes # 开启AOF持久化功能Slave节点Redis配置文件
bash
$ vi /etc/redis/6379.conf
bind 0.0.0.0 # 修改bind 项,0.0.0.0监听所有网卡
daemonize yes # 开启守护进程
logfile /var/log/redis_6379.log # 指定日志文件目录
dir /var/lib/redis/6379 # 指定工作目录
replicaof xxx.xxx.xxx.xxx 6379 # 指定要同步的Master节点IP和端口
appendonly yes # 开启AOF持久化功能验证
主节点执行:
bash
$ tail -f /var/log/redis_6379.log出现类似于如下内容:
Synchronization with replica xxx.xxx.xxx.xxx:6379 succeeded主节点执行:
bash
$ redis-cli info replication出现类似于
bash
# Replication
role:master
connected_slaves:2
slave0:ip=xxx.xxx.xxx.xxx,port=6379,state=online,offset=555,lag=0
slave1:ip=xxx.xxx.xxx.xxx,port=6379,state=online,offset=555,lag=0Redis哨兵模式
哨兵的核心功能:在主从复制的基础上,哨兵引入了主节点的自动故障转移
哨兵模式的原理
哨兵(sentinel):是一个分布式系统,用于对主从结构中的每台服务器进行监控,当出现故障时通过投票机制选择新的 Master 并将所有 Slave 连接到新的 Master。所以整个运行哨兵的集群的数量 不少于 3个节点。
哨兵模式的作用
- 监控:哨兵会不断地检查主节点和从节点是否运作正常
- 自动故障转移:当主节点不能正常工作时,哨兵会开始自动故障转移操作,它会将失效主节点的其中一个从节点升级为新的主节点,并让其他从节点改为复制新的主节点
- 通知(提醒):哨兵可以将故障转移的结果发送给客户端
结构
哨兵结构由两部分组成,哨兵节点和数据节点:
- 哨兵节点:哨兵系统由一个或多个哨兵节点组成,哨兵节点是特殊的redis节点,不存储数据。
- 数据节点:主节点和从节点都是数据节点。
哨兵的启动依赖于主从模式,所以须把主从模式安装好的情况下再去做哨兵模式,所有节点上都需要部署哨兵模式,哨兵模式会监控所有的 Redis 工作节点是否正常,当 Master 出现问题的时候,因为其他节点与主节点失去联系,因此会投票,投票过半就认为这个 Master 的确出现问题,然后会通知哨兵间,然后从 Slaves 中选取一个作为新的 Master。
需要特别注意的是,客观下线是主节点才有的概念;如果从节点和哨兵节点发生故障,被哨兵主观下线后,不会再有后续的客观下线和故障转移操作。
假设主服务器宕机,哨兵1先检测到这个结果,系统并且不会马上进行failover过程,仅仅是哨兵1主观认为主服务器不可用,这现象称为主观下线,当其它哨兵也检测到主服务不可用,并且数量达到一定值,那么这些哨兵之间就会进行一次投票,投票的由一个哨兵发起,进行failover(故障转移)操作,切换成功后,就会通过发布订阅模式,让各哨兵把自己监控的从服务器实现切换主机客观下线
单哨兵与多哨兵
主从切换技术方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这需要人工干预,还会造成一段时间内服务不可用,Redis从2.8开始正式提供了Sentinel(哨兵模式)来解决这个问题。
单哨兵
主从切换自动版,Redis提供一个哨兵的命令,哨兵是一个独立的进程,独立运行的,哨兵会通过发送命令,等待Redis服务器响应,从而接口运行中的多个Redis实例,如果主机宕机了,会根据投票票数最多的从机,将其自动切换为主机。
多哨兵
单哨兵存在一个问题,如果最高哨兵死了呢,那么就没人进行监控了,所以在生产机中通常会存在多个哨兵同时监控Redis,并且多个哨兵也相互监控。
哨兵模式的搭建
Redis 配置文件
bash
$ vi /etc/redis/sentinel.conf
protected-mode no # 关闭保护模式
port 26379 # Redis哨兵默认的监听端口
daemonize yes # 指定sentinel为后台启动
logfile "/var/log/sentinel.log" # 指定日志存放路径
dir "/var/lib/redis/6379" # 指定数据库存放路径
# sentinel monitor [被监控的名称] [host] [port] [1]
sentinel monitor mymaster xxx.xxx.xxx.xxx 6379 2 # 指定该哨兵节点监控xxx.xxx.xxx.xxx:6379这个主节点,
# 该主节点的名称是mymaster,最后的2的含义与主节点的故障判定有关:至少需要2个哨兵节点同意,才能判定主节点故障并进行故障转移
sentinel down-after-milliseconds mymaster 30000 # 判定服务器down掉的时间周期,默认30000毫秒(30秒)
sentinel failover-timeout mymaster 180000 # 故障节点的最大超时时间为180000(180秒)启动哨兵模式
先启master,再启slave
bash
$ redis-sentinel /etc/redis/sentinel.conf &验证结果
故障模拟自己尝试哈
bash
$ ps aux | grep redis
$ tail -f /var/log/sentinel.log
$ redis-cli -p 26379 INFO Sentinel哨兵模式的配置文件
shell
# Example sentinel.conf
# 哨兵sentinel实例运行的端口 默认26379
port 26379
# 哨兵sentinel的工作目录
dir /tmp
# 哨兵sentinel监控的redis主节点的 ip port
# master-name 可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。
# quorum 当这些quorum个数sentinel哨兵认为master主节点失联 那么这时 客观上认为主节点失联了
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 2
# 当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供密码
# 设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
# 指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000
# 这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,
# 这个数字越小,完成failover所需的时间就越长,
# 但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。
# 可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
# sentinel parallel-syncs <master-name> <numslaves>
sentinel parallel-syncs mymaster 1
# 故障转移的超时时间 failover-timeout 可以用在以下这些方面:
#1. 同一个sentinel对同一个master两次failover之间的间隔时间。
#2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
#3.当想要取消一个正在进行的failover所需要的时间。
#4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了
# 默认三分钟
# sentinel failover-timeout <master-name> <milliseconds>
sentinel failover-timeout mymaster 180000
# SCRIPTS EXECUTION
#配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知相关人员。
#对于脚本的运行结果有以下规则:
#若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10
#若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
#如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
#一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。
#通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本,
# 这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信息。调用该脚本时,将传给脚本两个参数,
# 一个是事件的类型,
# 一个是事件的描述。
# 如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。
# 通知脚本
# sentinel notification-script <master-name> <script-path>
sentinel notification-script mymaster /var/redis/notify.sh
# 客户端重新配置主节点参数脚本
# 当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已经发生改变的信息。
# 以下参数将会在调用脚本时传给脚本:
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
# 目前<state>总是“failover”,
# <role>是“leader”或者“observer”中的一个。
# 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通信的
# 这个脚本应该是通用的,能被多次调用,不是针对性的。
# sentinel client-reconfig-script <master-name> <script-path>
sentinel client-reconfig-script mymaster /var/redis/reconfig.shRedis集群模式【多主多从集群】
前置:
部署6节点redis【如果不是3主3从,自行调整】
集群,即Redis Cluster,是Redis 3.0开始引入的分布式存储方案
集群由多个节点(Node)组成,Redis的数据分布在这些节点中。集群中的节点分为主节点和从节点:只有主节点负责读写请求和集群信息的维护;从节点只进行主节点数据和状态信息的复制
集群的作用
【1】数据分区:数据分区(或称数据分片)是集群最核心的功能。 集群将数据分散到多个节点,一方面突破了Redis单机内存大小的限制,存储容量大大增加;另一方面每个主节点都可以对外提供读服务和写服务,大大提高了集群的响应能力。 Redis单机内存大小受限问题;例如,如果单机内存太大,bgsave和bgrewriteaof的fork操作可能导致主进程阻塞,主从环境下主机切换时可能导致从节点长时间无法提供服务,全量复制阶段主节点的复制缓冲区可能溢出。
【2】高可用:集群支持主从复制和主节点的自动故障转移(与哨兵类似);当任一节点发生故障时,集群仍然可以对外提供服务;
集群的数据分片
Redis集群的数据分片:
Redis集群引入了哈希槽的概念
Redis集群有16384个哈希槽( 编号0-16383)
集群的每个节点负责一部分哈希槽
每个Key通过CRC16校验后对16384取余来决定放置哪个哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作
以3个节点组成的集群为例:
- 节点A包含0到5460号哈希槽
- 节点B包含5461到10922号哈希槽
- 节点C包含10923到16383号哈希槽
Redis集群的主从复制模型:
集群中具有A、B、C三个节点,如果节点B失败了,整个集群就会因缺少5461-10922这个范围的槽而不可以用。 为每个节点添加一个从节点A1、B1、C1整个集群便有三个Master节点和三个slave节点组成,在节点B失败后,集群选举B1位为的主节点继续服务。当B和B1 都失败后,集群将不可用。
群集模式的搭建
redis的集群一般需要6个节点,3主3从
修改配置文件
bash
# 关闭保护模式
protected-mode no
# 日志级别
loglevel warning
# 日志存放目录
logfile "/data/redis.log"
# 数据文件目录
dir /data
dbfilename dump.rdb
# 数据库数量
databases 16
# 保存数据库到数据文件
save 900 1
save 300 10
save 60 10000
# 集群相关配置
## 修改 redis.conf 大约 1576行 位置的 cluster-enabled 配置,取消注释并保证值为yes,这个配置保证集群被启用
cluster-enabled yes
## 修改 redis.conf 大约 1584行 位置,设置一个集群配置文件名
cluster-config-file nodes-6379.conf
## 修改 redis.conf 大约 1590行 位置,设置集群节点down机的超时时间,单位毫秒
cluster-node-timeout 15000启动Redis
分别启动redis
bash
$ systemctl start redis可以看到集群以cluster模式启动成功
bash
$ ps -ef | grep redis
polkitd 26656 26614 0 8月10 ? 00:38:04 redis-server *:6379
root 76729 1 0 09:24 ? 00:00:00 /usr/local/bin/redis-server 0.0.0.0:6379 [cluster]
root 76782 30063 0 09:24 pts/0 00:00:00 grep --color=auto redis将6个redis关联到一起,任意redis执行这行命令即可,需要执行这行命令创建一个集群,注意修改后面的IP地址:
bash
$ redis-cli --cluster create --cluster-replicas 1 \
192.168.10.1:6379 \
192.168.10.2:6379 \
192.168.10.3:6379 \
192.168.10.4:6379 \
192.168.10.5:6379 \
192.168.10.6:6379注意,如果redis配置了密码,那么在创建集群时需要指定密码
bash$ redis-cli -a redisPassword --cluster create --cluster-replicas 1 \ 192.168.10.1:6379 \ 192.168.10.2:6379 \ 192.168.10.3:6379 \ 192.168.10.4:6379 \ 192.168.10.5:6379 \ 192.168.10.6:6379如果已经创建了集群,需要增加密码,那么在配置文件内配置好
masterauth和requirepass重启即可。requirepass:配置访问密码,masterauth:配置从节点向master请求的密码
这行意思是创建一个集群,每个master有一个分片(有一个slaver),执行之后会出现这样一个界面,在这里直接输入yes:
bash
$ redis-cli --cluster create --cluster-replicas 1 \
192.168.10.1:6379 \
192.168.10.2:6379 \
192.168.10.3:6379 \
192.168.10.4:6379 \
192.168.10.5:6379 \
192.168.10.6:6379
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.10.5:6379 to 192.168.10.1:6379
Adding replica 192.168.10.6:6379 to 192.168.10.2:6379
Adding replica 192.168.10.4:6379 to 192.168.10.3:6379
M: 49e3016a3f43204b529b525b4c0928b715bd64f9 192.168.10.1:6379
slots:[0-5460] (5461 slots) master
M: 3ed97a777289a8e76ebf33e9dae2e17ef4a88ffe 192.168.10.2:6379
slots:[5461-10922] (5462 slots) master
M: 0f86a10fc4dd069662284061bc1aa77a2d436043 192.168.10.3:6379
slots:[10923-16383] (5461 slots) master
S: 9781650f40619fe8e0c586b0b814186e392d6f5d 192.168.10.4:6379
replicates 0f86a10fc4dd069662284061bc1aa77a2d436043
S: acbf4c8121684b7caec9e28a0d5f4210aae0aec3 192.168.10.5:6379
replicates 49e3016a3f43204b529b525b4c0928b715bd64f9
S: 82df33dce884985e1106b65ecbfa1fe07f09c17b 192.168.10.6:6379
replicates 3ed97a777289a8e76ebf33e9dae2e17ef4a88ffe
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然后可以看到这样的提示,这也代表搭建成功:
bash
>>> Performing Cluster Check (using node 192.168.10.1:6379)
M: 49e3016a3f43204b529b525b4c0928b715bd64f9 192.168.10.1:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 9781650f40619fe8e0c586b0b814186e392d6f5d 192.168.10.4:6379
slots: (0 slots) slave
replicates 0f86a10fc4dd069662284061bc1aa77a2d436043
M: 3ed97a777289a8e76ebf33e9dae2e17ef4a88ffe 192.168.10.2:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: acbf4c8121684b7caec9e28a0d5f4210aae0aec3 192.168.10.5:6379
slots: (0 slots) slave
replicates 49e3016a3f43204b529b525b4c0928b715bd64f9
M: 0f86a10fc4dd069662284061bc1aa77a2d436043 192.168.10.3:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 82df33dce884985e1106b65ecbfa1fe07f09c17b 192.168.10.6:6379
slots: (0 slots) slave
replicates 3ed97a777289a8e76ebf33e9dae2e17ef4a88ffe
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.之后你在使用redis的时候redis会自动通过一定的算法算出缓存key的slot值(查询的时候也会计算,不同的key在不同的master当中查询,并且三台master互通),并设置到指定的master当中,如何连接这个redis集群呢?可以在任意一台机器上输入这行命令:
bash
$ redis-cli -c
# 或者带上端口号
$ redis-cli -c -p 6379查看集群节点状态
bash
CLUSTER NODESbash
127.0.0.1:6379> CLUSTER NODES
9781650f40619fe8e0c586b0b814186e392d6f5d 192.168.10.4:6379@16379 slave 0f86a10fc4dd069662284061bc1aa77a2d436043 0 1724720400319 3 connected
3ed97a777289a8e76ebf33e9dae2e17ef4a88ffe 192.168.10.2:6379@16379 master - 0 1724720402329 2 connected 5461-10922
acbf4c8121684b7caec9e28a0d5f4210aae0aec3 192.168.10.5:6379@16379 slave 49e3016a3f43204b529b525b4c0928b715bd64f9 0 1724720401000 1 connected
0f86a10fc4dd069662284061bc1aa77a2d436043 192.168.10.3:6379@16379 master - 0 1724720401324 3 connected 10923-16383
82df33dce884985e1106b65ecbfa1fe07f09c17b 192.168.10.6:6379@16379 slave 3ed97a777289a8e76ebf33e9dae2e17ef4a88ffe 0 1724720399000 2 connected
49e3016a3f43204b529b525b4c0928b715bd64f9 192.168.10.1:6379@16379 myself,master - 0 1724720400000 1 connected 0-5460当我们设置值和查询值的时候都会计算slot并跳转到指定的服务器
bash
127.0.0.1:6379> set k1 v1
-> Redirected to slot [12706] located at 10.234.218.97:6379
OK
10.234.218.97:6379> get k1
"v1"其他
bash
$ redis-cli -h xxx.xxx.xxx.xxx -p 6001 -c # 加-c参数,节点之间就可以互相跳转
cluster slots # 查看节点的哈希槽编号范围
set sky blue # 设置键值
cluster keyslot sky # 查看name键的槽编号基于K8S部署Redis集群
前置:
K8S集群已搭建
有一个可动态供应的存储类
Redis配置
只是展示,实际上下面的资源清单已经列出来了
shell
# 关闭保护模式
protected-mode no
# 日志级别
loglevel warning
# 日志存放目录
logfile "/data/redis.log"
# 数据文件目录
dir /data
dbfilename dump.rdb
# 数据库数量
databases 16
# 保存数据库到数据文件
save 900 1
save 300 10
save 60 10000
# 集群相关配置
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 15000资源清单
yaml
apiVersion: v1
kind: Namespace
metadata:
name: redis
---
apiVersion: v1
data:
redis.conf: |-
# 关闭保护模式
protected-mode no
# 日志级别
loglevel warning
# 日志存放目录
logfile "/data/redis.log"
# 数据文件目录
dir /data
dbfilename dump.rdb
# 数据库数量
databases 16
# 保存数据库到数据文件
save 900 1
save 300 10
save 60 10000
# 集群相关配置
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 15000
kind: ConfigMap
metadata:
name: redis-cluster-config
namespace: redis
---
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: redis
labels:
app: redis
spec:
ports:
- port: 6379
name: redis
targetPort: 6379
nodePort: 30379
selector:
app: redis
type: NodePort
sessionAffinity: ClientIP
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
namespace: redis
spec:
selector:
matchLabels:
app: redis
serviceName: "redis"
replicas: 6
template:
metadata:
labels:
app: redis
spec:
terminationGracePeriodSeconds: 10
containers:
- command:
- "redis-server"
- "/usr/local/etc/redis.conf"
name: redis
# image: docker.io/library/redis:7.0.12
image: registry.cn-shenzhen.aliyuncs.com/xiaohh-docker/redis:7.0.12
ports:
- containerPort: 6379
name: redis
volumeMounts:
- name: redis-data
mountPath: /data
- name: redis-config
mountPath: /usr/local/etc
readOnly: true
volumes:
- name: redis-config
configMap:
name: redis-cluster-config
items:
- key: redis.conf
path: redis.conf
volumeClaimTemplates:
- metadata:
name: redis-data
namespace: redis
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
storageClassName: nfs-client初始化集群
由于部署的pod是statefulset类型的pod,所以访问pod的域名格式为 pod名字.service名字.命名空间.svc.cluster.local,所以我们在集群中访问六个redis的地址分别为:
bash
redis-0.redis.redis.svc.cluster.local:6379
redis-1.redis.redis.svc.cluster.local:6379
redis-2.redis.redis.svc.cluster.local:6379
redis-3.redis.redis.svc.cluster.local:6379
redis-4.redis.redis.svc.cluster.local:6379
redis-5.redis.redis.svc.cluster.local:6379接下来去到任意一个pod里,去执行一行命令,使用这行命令进入到第一个pod:
bash
# 注意修改你自己的命名空间和pod名字
$ kubectl exec -itn redis pod/redis-0 bash然后执行下面这行命令:
bash
$ redis-cli --cluster create --cluster-replicas 1 \
redis-0.redis.redis.svc.cluster.local:6379 \
redis-1.redis.redis.svc.cluster.local:6379 \
redis-2.redis.redis.svc.cluster.local:6379 \
redis-3.redis.redis.svc.cluster.local:6379 \
redis-4.redis.redis.svc.cluster.local:6379 \
redis-5.redis.redis.svc.cluster.local:6379它问这样的一个分配方式行不行,这里直接输入yes然后回车,接下来看到类似下面这个内容代表集群配置成功:
bash
$ redis-cli --cluster create --cluster-replicas 1 \
redis-0.redis.redis.svc.cluster.local:6379 \
redis-1.redis.redis.svc.cluster.local:6379 \
redis-2.redis.redis.svc.cluster.local:6379 \
redis-3.redis.redis.svc.cluster.local:6379 \
redis-4.redis.redis.svc.cluster.local:6379 \
redis-5.redis.redis.svc.cluster.local:6379
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica redis-4.redis.redis.svc.cluster.local:6379 to redis-0.redis.redis.svc.cluster.local:6379
Adding replica redis-5.redis.redis.svc.cluster.local:6379 to redis-1.redis.redis.svc.cluster.local:6379
Adding replica redis-3.redis.redis.svc.cluster.local:6379 to redis-2.redis.redis.svc.cluster.local:6379
M: 49e3016a3f43204b529b525b4c0928b715bd64f9 redis-0.redis.redis.svc.cluster.local:6379
slots:[0-5460] (5461 slots) master
M: 3ed97a777289a8e76ebf33e9dae2e17ef4a88ffe redis-1.redis.redis.svc.cluster.local:6379
slots:[5461-10922] (5462 slots) master
M: 0f86a10fc4dd069662284061bc1aa77a2d436043 redis-2.redis.redis.svc.cluster.local:6379
slots:[10923-16383] (5461 slots) master
S: 9781650f40619fe8e0c586b0b814186e392d6f5d redis-3.redis.redis.svc.cluster.local:6379
replicates 0f86a10fc4dd069662284061bc1aa77a2d436043
S: acbf4c8121684b7caec9e28a0d5f4210aae0aec3 redis-4.redis.redis.svc.cluster.local:6379
replicates 49e3016a3f43204b529b525b4c0928b715bd64f9
S: 82df33dce884985e1106b65ecbfa1fe07f09c17b redis-5.redis.redis.svc.cluster.local:6379
replicates 3ed97a777289a8e76ebf33e9dae2e17ef4a88ffe
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 redis-0.redis.redis.svc.cluster.local:6379)
M: 49e3016a3f43204b529b525b4c0928b715bd64f9 redis-0.redis.redis.svc.cluster.local:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 9781650f40619fe8e0c586b0b814186e392d6f5d 10.234.218.98:6379
slots: (0 slots) slave
replicates 0f86a10fc4dd069662284061bc1aa77a2d436043
M: 3ed97a777289a8e76ebf33e9dae2e17ef4a88ffe 10.234.218.96:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: acbf4c8121684b7caec9e28a0d5f4210aae0aec3 10.234.218.99:6379
slots: (0 slots) slave
replicates 49e3016a3f43204b529b525b4c0928b715bd64f9
M: 0f86a10fc4dd069662284061bc1aa77a2d436043 10.234.218.97:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 82df33dce884985e1106b65ecbfa1fe07f09c17b 10.234.218.100:6379
slots: (0 slots) slave
replicates 3ed97a777289a8e76ebf33e9dae2e17ef4a88ffe
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.进入集群,查看集群里的节点
bash
$ redis-cli -c
CLUSTER NODES可以看到是三master三node的redis集群
bash
127.0.0.1:6379> CLUSTER NODES
9781650f40619fe8e0c586b0b814186e392d6f5d 10.234.218.98:6379@16379 slave 0f86a10fc4dd069662284061bc1aa77a2d436043 0 1724720400319 3 connected
3ed97a777289a8e76ebf33e9dae2e17ef4a88ffe 10.234.218.96:6379@16379 master - 0 1724720402329 2 connected 5461-10922
acbf4c8121684b7caec9e28a0d5f4210aae0aec3 10.234.218.99:6379@16379 slave 49e3016a3f43204b529b525b4c0928b715bd64f9 0 1724720401000 1 connected
0f86a10fc4dd069662284061bc1aa77a2d436043 10.234.218.97:6379@16379 master - 0 1724720401324 3 connected 10923-16383
82df33dce884985e1106b65ecbfa1fe07f09c17b 10.234.218.100:6379@16379 slave 3ed97a777289a8e76ebf33e9dae2e17ef4a88ffe 0 1724720399000 2 connected
49e3016a3f43204b529b525b4c0928b715bd64f9 10.234.218.95:6379@16379 myself,master - 0 1724720400000 1 connected 0-5460集群操作
主节点添加
对的3主3从进行扩容成4主4从,准备好两个新的redis节点,并配置好配置文件,启动服务
添加节点
bash
# 使用如下命令即可添加节点将一个新的节点添加到集群中
# -a 密码认证(没有密码不用带此参数)
# --cluster add-node 添加节点 新节点IP:新节点端口 任意存活节点IP:任意存活节点端口
$ redis-cli -a passwd --cluster add-node yyy.yyy.yyy.yyy:6379 xxx.xxx.xxx.xxx:6379查看槽位信息
bash
$ redis-cli -c
# 槽位信息
CLUSTER SLOTS
# 节点信息
CLUSTER NODES在输出中,每个元素都是一个包含三个/四个子元素的列表【好像有版本区别】:
- 第一个子元素是槽位的起始编号。
- 第二个子元素是槽位的结束编号。
- 第三个子元素是一个包含三个元素的列表,分别表示管理这个槽位范围的节点的IP地址、端口号和节点ID。
- 第四个子元素是对于从节点信息
例如:
bash127.0.0.1:6379> CLUSTER SLOTS 1) 1) (integer) 0 2) (integer) 5460 3) 1) "10.234.218.95" 2) (integer) 6379 3) "49e3016a3f43204b529b525b4c0928b715bd64f9" 4) (empty array) 4) 1) "10.234.218.99" 2) (integer) 6379 3) "acbf4c8121684b7caec9e28a0d5f4210aae0aec3" 4) (empty array) 2) 1) (integer) 5461 2) (integer) 10922 3) 1) "10.234.218.96" 2) (integer) 6379 3) "3ed97a777289a8e76ebf33e9dae2e17ef4a88ffe" 4) (empty array) 4) 1) "10.234.218.100" 2) (integer) 6379 3) "82df33dce884985e1106b65ecbfa1fe07f09c17b" 4) (empty array) 3) 1) (integer) 10923 2) (integer) 16383 3) 1) "10.234.218.97" 2) (integer) 6379 3) "0f86a10fc4dd069662284061bc1aa77a2d436043" 4) (empty array) 4) 1) "10.234.218.98" 2) (integer) 6379 3) "9781650f40619fe8e0c586b0b814186e392d6f5d" 4) (empty array)
槽位迁移
bash
# 使用如下命令将其它主节点的分片迁移到当前节点中
# -a 密码认证(没有密码不用带此参数)
# --cluster reshard 槽位迁移 从 节点IP:节点端口 中迁移槽位到当前节点中
$ redis-cli --cluster reshard xxx.xxx.xxx.xxx:6379遇到如下内容,表示要拆分多少槽位出来给新节点【后面写上数量就行,如500】
bashHow many slots do you want to move (from 1 to 16384)?遇到如下内容,表示要将这些槽位给哪个节点ID【后面写新节点的ID即可,ID会在此提示往上一点点显示,找到对应的复制即可】
bashWhat is the receiving node ID?遇到如下内容,表示要从哪儿拆出来槽位出来给新节点【后面写all/done】
bashPlease enter all the source node IDs. Type 'all' to use all the nodes as source nodes for the hash slots. all 命令表示从每一个有槽位的节点取一部分出来移动到这个新节点中 Type 'done' once you entered all the source nodes IDs. done 输入后跟着需要输入ID,会从指定的ID中直接取600槽位给到新节点 Source node #1:输入完成后会打印一片执行计划,输入yes就会把槽位与数据全部迁移到新节点了
迁移完毕后再查看集群信息可以看到新节点已经添加了槽位了
从节点添加
添加节点
bash
# 使用如下命令即可添加节点将一个新的节点添加到集群中
# -a 密码认证(没有密码不用带此参数)
# --cluster add-node 添加节点 新节点IP:新节点端口 任意存活节点IP:任意存活节点端口
$ redis-cli -a passwd --cluster add-node yyy.yyy.yyy.yyy:6379 xxx.xxx.xxx.xxx:6379通过节点信息可以查看到新节点已经添加进去了,但是任何的节点添加都是主节点,接下来需要把新节点改成从节点
配置节点
使用客户端命令连接到刚刚新添加的节点的上,并且为其设置一个主节点,设置完毕后再次查看节点信息,可以看到新节点已经是对应主节点的从节点了
bash
# 连接需设为从节点的Redis服务
$ redis-cli -a passwd -p 6379
# CLUSTER REPLICATE 需要设置从节点的主节点ID
# 将当前节点分配为 8cf44439390dc9412813ad27c43858a6bb53365c 的从节点
CLUSTER REPLICATE 8cf44439390dc9412813ad27c43858a6bb53365c删除主节点
主节点删除就那么首先需要对槽进行迁移,如当前需要移除某个节点,那么首先需要把这个节点槽位移动到别的节点中,才能删除
bash
# 使用如下命令移动某节点槽位到其他节点中
# -a 密码认证(没有密码不用带此参数)
# --cluster reshard 非迁移节点IP:非迁移节点端口 <非迁移节点指不删除或用于接收槽位的节点信息>
$ redis-cli -a passwd --cluster reshard xxx.xxx.xxx.xxx:6379移完后,确认对应节点没有槽位了,就可以删除节点了
bash
# 执行如下命令删除节点
# -a 密码认证(没有密码不用带此参数)
# --cluster del-node 连接任意一个存活的节点IP:连接任意一个存活的节点端口 要删除节点ID
$ redis-cli -a passwd --cluster del-node xxx.xxx.xxx.xxx:6379 8cf44439390dc9412813ad27c43858a6bb53365c删除从节点
从节点删除比较简单,直接删除即可
bash
# -a 密码认证(没有密码不用带此参数)
# --cluster del-node 连接任意一个存活的节点IP:连接任意一个存活的节点端口 要删除节点ID
$ redis-cli -a passwd --cluster del-node xxx.xxx.xxx.xxx:6379 71cb4fe842e83252f0ffabdc2b31eddb98fd4c89删除成功后可以看到对应节点已经在集群中消失了
重新分配槽位
重新分配槽位慎用!!!,该功能可以让集群的槽位重新平均分配,但是由于涉及到槽位大量迁移,会导致整个Redis阻塞停止处理客户端的请求。
bash
# -a 密码认证(没有密码不用带此参数)
# --cluster rebalance 重新分配集群中的槽位
$ redis-cli -a passwd --cluster rebalance 任意存活节点IP:任意存活节点端口