docker 哨兵模式和集群模式安装Redis7.0.12
docker 哨兵模式和集群模式安装Redis7.0.12
1.下载镜像
1.1 配置阿里云加速源
墙外能访问https://hub.docker.com/_/redis 的可跳过
https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
登录后选择左侧的镜像工具=>镜像加速器,获取加速器地址,根据自己的系统选择对照操作文档操作
命令如下:
针对Docker客户端版本大于 1.10.0 的用户您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{"registry-mirrors": ["https://你的加速地址前缀.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
1.2 拉取镜像
docker pull redis:7.0.12docker images

2.配置主从复制
本次操作是在一台物理机上,分别开启redis-6379,redis-6380,redis-6381三个容器,如果有多个物理机或者云服务器,可均使用6379端口,要保证网络能互相ping通,防火墙端口开放或安全组规则开放端口
2.1 redis.conf 配置文件修改
# 是否后台程序,如果选择的是物理机或者虚拟机安装,这个地方是yes,docker场景下是no,因为使用-d命令了,这里避免冲突直接改成no
daemonize no # 绑定的ip,配置文件里写的是注释了就监听所有ip,这个默认是没有注释的,要注释掉
#bind 127.0.0.1 #protected-mode默认情况下是启用的(protected-mode yes),这意味着只允许通过本地回环接口(127.0.0.1)访问Redis服务器。这是为了提供一定的安全性,防止未经授权的外部访问,这个改成no
protected-mode no #port 端口,只有一台机器的情况下需要更改端口和其他实例区分,这里slave 节点分别配置成6380,6381,多个机器可以都保持6379
port 6379 #我这里设置容器进入的工作空间为/data/redis-6379,根据情况设置,但要和挂载的路径保持一致,slave节点分别是/data/redis-6380,/data/redis-6381
dir /data/redis-6379 #pidfile 进程id文件,根据情况设置,为了区分slave节点分别是 /var/run/redis_6380.pid ,/var/run/redis_6381.pid
pidfile /var/run/redis_6379.pid#logfile 日志文件,这里巨坑,**如果日志文件和启动文件同级,这里可以配置为./6379.log,否则这里一定要写绝对路径,是个巨坑!!!**
#我的工作空间dir是/data/redis-6379,我可以写成./logs/redis.log,但我还是用绝对路径,
slave节点分别是/data/redis-6380/logs/redis.log,/data/redis-6381/logs/redis.log
logfile "/data/redis-6379/logs/redis.log"#requiredpass 密码,这自己定义,别太简单,我司安全部门有漏洞扫描,太简单会被扫出来,回头还要改,麻烦
requiredpass xxxxxx #dbfilename 持久化rdb文件名称,默认即可,别改
dbfilename dump.rdb#appendonly 开启aof持久化
appendonly yes#appendfilename aof持久化的文件名,别改,默认即可
appendfilename "appendonly.aof"#appenddirname aof持久化的目录。没必要改,默认即可
appenddirname "appendonlydir"#masterauth slave访问master的通行密码,非哨兵模式master不用配置,哨兵模式都需要配置,因为master可能变成slave
masterauth xxxxxx# replicaof <masterip> <masterport> 配置是谁的副本 replicaof 主库IP 主库端口 master节点不用配置
replicaof 192.168.240.10 6379
2.2 启动redis实例
–net=host 参数用于将容器与主机共享网络命名空间,说白了,不使用docker内部的网络,容器将使用与主机相同的网络配置
–restart=always 自动重启
-p 6379:6379 外部端口6379映射到容器内部端口6379,同理6380:6380,6381:6381
–name redis-6379 实例名称
-v /data/redis-6379/data:/data/redis-6379/data 将容器内部的data目录挂载到外部,以防实例销毁数据丢失
-v /data/redis-6379/conf/redis.conf:/etc/redis/redis.conf 外置配置文件
-v /data/redis-6379/logs/redis.log:/data/redis-6379/logs/redis.log 外置日志文件方便查看
-d 后台运行,别和daemonize yes 一起使用
redis:7.0.12 镜像
redis-server bin程序
/etc/redis/redis.conf 容器内部的配置文件
docker run --net=host --restart=always -p 6379:6379 --name redis-6379 \
-v /data/redis-6379/data:/data/redis-6379/data \
-v /data/redis-6379/conf/redis.conf:/etc/redis/redis.conf \
-v /data/redis-6379/logs/redis.log:/data/redis-6379/logs/redis.log \
-d redis:7.0.12 redis-server /etc/redis/redis.confdocker run --net=host --restart=always -p 6380:6380 --name redis-6380 \
-v /data/redis-6380/data:/data/redis-6380/data \
-v /data/redis-6380/conf/redis.conf:/etc/redis/redis.conf \
-v /data/redis-6380/logs/redis.log:/data/redis-6380/logs/redis.log \
-d redis:7.0.12 redis-server /etc/redis/redis.confdocker run --net=host --restart=always -p 6381:6381 --name redis-6381 \
-v /data/redis-6381/data:/data/redis-6381/data \
-v /data/redis-6381/conf/redis.conf:/etc/redis/redis.conf \
-v /data/redis-6381/logs/redis.log:/data/redis-6381/logs/redis.log \
-d redis:7.0.12 redis-server /etc/redis/redis.conf
启动完成,docker ps

使用docker 命令进入容器或者登录redis
docker exec -it redis-6379 redis-cli -p 6379
docker exec -it redis-6380 redis-cli -p 6380
docker exec -it redis-6381 redis-cli -p 6381
输入auth 密码登录redis
info replication #可以查看复制结点的主从关系和配置信息
对redis 进行写操作,可以看见slave节点可以同步master节点的数据,但是在slave节点写数据,是不被允许的
主从复制配置完毕
3.配置哨兵高可用
主从同步并不能保证高可用,哨兵模式则会进行主从切换,将其中一个slave作为新master
3.1 sentinel配置文件修改
#是否以后台daemon方式运行
daemonize:no#安全保护模式
protected-model:no#端口 26379 slave 26380 26381
port:26379#日志文件路径,slave节点同理
logfile "/data/sentinel-6379/logs/sentinel26379.log"#pid文件路径,slave节点同理
pidfile /var/run/redis-sentinel26379.pid#工作目录,slave节点同理
dir /data/sentinel-6379#设置要监控的master服务器quorum表示最少有几个哨兵认可客观下线,同意故障迁移的法定票数
#sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 192.168.240.10 6379 2#连接master服务的密码 sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster xxxxxx
其他参数,按需设置
| sentinel down-after-milliseconds | 指定多少毫秒之后,主节点没有应答哨兵,此时哨兵主观上认为主节点下线 |
|---|---|
| sentinel parallel-syncs | 表示允许并行同步的slave个数,当Master挂了后,哨兵会选出新的Master,此时,剩余的slave会向新的master发起同步数据 |
| sentinel failover-timeout | 故障转移的超时时间,进行故障转移时,如果超过设置的毫秒,表示故障转移失败 |
| sentinel notification-script | 配置当某一事件发生时所需要执行的脚本 |
| sentinel client-reconfig-script | 客户端重新配置主节点参数脚本 |
我在本机分别将实例放在了/data/redis-6379/conf/sentinel.conf,/data/redis-6380/conf/sentinel.conf,/data/redis-6380/conf/sentinel.conf,按需设置
3.2 启动sentinel实例
docker run --net=host --name sentinel-6379 \
-v /data/redis-6379/conf/sentinel.conf:/etc/sentinel-6379/sentinel.conf \
-v /data/redis-6379/logs/sentinel26379.log:/data/sentinel-6379/logs/sentinel26379.log \
-d redis:7.0.12 redis-sentinel /etc/sentinel-6379/sentinel.confdocker run --net=host --name sentinel-6380 \
-v /data/redis-6380/conf/sentinel.conf:/etc/sentinel-6380/sentinel.conf \
-v /data/redis-6380/logs/sentinel26380.log:/data/sentinel-6380/logs/sentinel26380.log \
-d redis:7.0.12 redis-sentinel /etc/sentinel-6380/sentinel.confdocker run --net=host --name sentinel-6381 \
-v /data/redis-6381/conf/sentinel.conf:/etc/sentinel-6381/sentinel.conf \
-v /data/redis-6381/logs/sentinel26381.log:/data/sentinel-6381/logs/sentinel26381.log \
-d redis:7.0.12 redis-sentinel /etc/sentinel-6381/sentinel.conf
使用docker 命令进入容器或者登录redis-cli
docker exec -it sentinel-6379 redis-cli -p 26379
docker exec -it sentinel-6380 redis-cli -p 26380
docker exec -it sentinel-6380 redis-cli -p 26381
进入后查看哨兵信息
info Sentinel

进入redis-6389,先登录
info replication

如图所示,6379role是maser,有两个slave
salve节点6380,6381



3.3 测试高可用
1.模拟主节点挂掉
docker stop redis-6379

2.分别查看redis-6380,redis-6381(等30秒,心跳是30秒),可以通过sentinel down-after-milliseconds mymaster 30000 设置
重新登录redis-6380,redis-6381,发现redis-6381变成了主节点,只有一个slave节点6380
docker exec -it redis-6380 redis-cli -p 6380
docker exec -it redis-6381 redis-cli -p 6381
info replication


3.重启redis-6379节点,发现redis-6379变成slave节点
docker start redis-6379

docker exec -it redis-6379 redis-cli -p 6379

4.多次反复stop master节点,发现master节点挂掉之后会将另外的slave节点选举为主节点
至此哨兵模式高可用配置完毕
4.主从复制原理
4.1 slave启动,同步首清
slave启动成功连接到master后会发送一个sync命令
slave首次全新连接master,一次完全同步(全量复制)将被自动执行,slave自身原有数据会被master数据覆盖清除
4.2 首次连接,全量复制
master节点收到sync命令后会开始在后台保存快照(即RDB持久化,主从复制时会触发RDB),同时收集所有接收到的用于修改数据集的命令并缓存起来,master节点执行RDB持久化完后,master将RDB快照文件和所有缓存的命令发送到所有slave,以完成一次完全同步
而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中,从而完成复制初始化
4.3 心跳持续,保持通信
master 发出ping心跳周期默认是10秒 通过 repl-ping-replica-period 10 可以设置
4.3 进入平稳,增量复制
master继续将新的所有收集到的修改命令自动依次传送给slave,完成同步
4.4 从机下线,重连续传
master会检查backlog里面的offset,master和slave都会保存一个复制的offset还有一个masterId,offset是保存在backlog中的。
master只会把已经缓存的offset后面的数据复制给slave,类似断点续传
4.5 复制的缺点
复制延时,信号衰减
由于所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。
5.哨兵模式高可用原理
当一个主从配置中master失效后,sentinel可以选举出一个新的master用于自动接替原master的工作,主从配置中的其他redis服务器自动指向新的master同步数据,一般建议sentinel采取奇数台,防止某一台sentinel无法连接到master导致误切换
三个哨兵监控一主二从,正常运行中

5.1 下线依据
SDown主观下线(Subjectively Down)
1. SDOWN(主观不可用)是单个sentinel自己主观上检测到的关于master的状态,从sentinel的角度来看,如果发送了PING心跳后,在一定时间内没有收到合法的回复,就达到了SDOWN的条件。
2. sentinel配置文件中的down-after-milliseconds设置了判断主观下线的时间长度
ODown客观下线(Objectively Down)
1.ODOWN需要一定数量的sentinel,多个哨兵达成一致意见 才能认为一个master客观上已经宕机
2. sentinel配置文件中的 sentinel monitor <master-name> <ip> <redis-port> <quorum> 设置法定票数,这个参数是进行客观下线的一个依据,法定人数/法定票数意思是至少有quorum个sentinel认为这个master有故障才会对这个master进行下线以及故障转移。因为有的时候,某个sentinel节点可能因为自身网络原因导致无法连接master,而此时master并没有出现故障,所以这就需要多个sentinel都一致认为该master有问题,才可以进行下一步操作,这就保证了公平性和高可用。
5.2 选举流程
- 启动哨兵:在 Redis Sentinel 集群中,每个哨兵都会运行一个独立的进程。
- 哨兵监控主服务器:每个哨兵会定期向主服务器发送心跳检测。
- 发现主服务器故障:当一个哨兵检测到主服务器无响应,并在配置的时间内未收到心跳回复时,它会将主服务器标记为故障。
- 哨兵进入选举状态:一旦哨兵确认主服务器故障,它会与其他哨兵进行通信以达成共识,确定新的主服务器。
- 选举领导者:哨兵之间会通过PAXOS算法或Raft算法等共识算法来选举新的主服务器。选举过程中,哨兵会交换信息,比较主服务器的配置纪元(config epoch)、优先级(priority)等属性来决定新的主服务器。
- 选举结果通知客户端:一旦新的主服务器选出,哨兵会将选举结果广播给所有的客户端和其他哨兵。
- 客户端重定向:在选举完成后,被选举为主服务器的哨兵会将新的主服务器信息通知给连接到其他哨兵的客户端,这样客户端就可以与新的主服务器建立连接。
- 故障恢复:一旦选举完成,被选为主服务器的哨兵会尝试对故障主服务器进行故障恢复,如进行自动故障转移等操作。
6.哨兵使用建议
- 哨兵节点的数量应为多个,哨兵本身应该集群,保证高可用
- 哨兵节点的数量应该是奇数
- 各个哨兵节点的配置应一致
- 如果哨兵节点部署在Docker等容器里面,尤其要注意端口的正确映射
- 哨兵集群+主从复制,并不能保证数据零丢失,所以需要使用集群
7.集群模式
7.1 实例创建
新建六个redis 实例,以6382为例,其他几个配置一样
bind 0.0.0.0
daemonize yes
protected-mode no
port 6381
logfile "/data/redis-6382/logs/redis.log"
pidfile /var/run/redis_cluster_6382.pid
dir /myredis/cluster
dbfilename dump.rdb
appendonly yes
appendfilename "appendonly.aof"
requirepass tan!@#
masterauth tan!@#cluster-enabled yes
#每个集群节点都有一个集群配置文件。这个文件不应手动编辑。它是由Redis节点创建和更新的,看注释,所以这里你只需要取个名就好,不能重复
cluster-config-file nodes-6382.conf
cluster-node-timeout 5000
7.2 启动实例
docker run --net=host --restart=always -p 6382:6382 --name redis-6382 \
-v /data/redis-6382/data:/data/redis-6382/data \
-v /data/redis-6382/conf/redis.conf:/etc/redis/redis.conf \
-v /data/redis-6382/logs/redis.log:/data/redis-6382/logs/redis.log \
-d redis:7.0.12 redis-server /etc/redis/redis.confdocker run --net=host --restart=always -p 6383:6383 --name redis-6383 \
-v /data/redis-6383/data:/data/redis-6383/data \
-v /data/redis-6383/conf/redis.conf:/etc/redis/redis.conf \
-v /data/redis-6383/logs/redis.log:/data/redis-6383/logs/redis.log \
-d redis:7.0.12 redis-server /etc/redis/redis.confdocker run --net=host --restart=always -p 6384:6384 --name redis-6384 \
-v /data/redis-6384/data:/data/redis-6381/data \
-v /data/redis-6384/conf/redis.conf:/etc/redis/redis.conf \
-v /data/redis-6384/logs/redis.log:/data/redis-6384/logs/redis.log \
-d redis:7.0.12 redis-server /etc/redis/redis.confdocker run --net=host --restart=always -p 6385:6385 --name redis-6385 \
-v /data/redis-6385/data:/data/redis-6381/data \
-v /data/redis-6385/conf/redis.conf:/etc/redis/redis.conf \
-v /data/redis-6385/logs/redis.log:/data/redis-6385/logs/redis.log \
-d redis:7.0.12 redis-server /etc/redis/redis.confdocker run --net=host --restart=always -p 6386:6386 --name redis-6386 \
-v /data/redis-6386/data:/data/redis-6381/data \
-v /data/redis-6386/conf/redis.conf:/etc/redis/redis.conf \
-v /data/redis-6386/logs/redis.log:/data/redis-6386/logs/redis.log \
-d redis:7.0.12 redis-server /etc/redis/redis.confdocker run --net=host --restart=always -p 6387:6387 --name redis-6387 \
-v /data/redis-6387/data:/data/redis-6381/data \
-v /data/redis-6387/conf/redis.conf:/etc/redis/redis.conf \
-v /data/redis-6387/logs/redis.log:/data/redis-6387/logs/redis.log \
-d redis:7.0.12 redis-server /etc/redis/redis.conf

7.3 构建集群关系
通过redis-cli 命令为6台机器构建集群关系
–cluster- replicas 1 表示为每个master创建一一个slave节点
进入其中一个客户端
docker exec -it redis-6382 redis-cli -p 6382
输入密码
auth tan!@#
输入cluster nodes
集群本身只有自己,切换6383 6384 ... 6387 结果一致


进入容器内部
docker exec -it redis-6382 /bin/bash
复制以下命令加入集群,这里-a 密码,我这里用了!@#,要用单引号包着
redis-cli -a 'tan!@#' --cluster create --cluster-replicas 1 192.168.240.10:6382 192.168.240.10:6383 192.168.240.10:6384 192.168.240.10:6385 192.168.240.10:6386 192.168.240.10:6387

上面的图可以看到集群的对应关系
6382 负责槽位:[0-5460] (5461 slots) master 副本6386
6383 负责槽位:[5461-10922] (5462 slots) master 副本6387
6384 负责槽位:[10923-16383] (5461 slots) master 副本6385
再次进入redis客户端
docker exec -it redis-6382 redis-cli -p 6382 -a 'tan!@#'

7.4 集群读写
docker exec -it redis-6382 redis-cli -p 6382 -a 'tan!@#'
写入 set k1 v1,我在6382 和6383 均不能让写入,提示moved … 6384 ,进入6384客户端,却提示成功

docker exec -it redis-6384 redis-cli -p 6384 -a 'tan!@#'

是因为做了集群后每个master负责不同的槽位

客户端加-c 表示集群模式即可解决,不用自己找到对应的客户端
docker exec -it redis-6382 redis-cli -p 6382 -a 'tan!@#' -c

查看某个key该属于对应的槽位值
cluster keyslot 键名称

7.5 主从切换
容错切换迁移
主6382和从机切换,先停止主机6382,6386作为从机上位,以实际情况为准,7.3里是6386作为6382的从机
docker stop redis-6382
stop之前集群的信息在7.4中可以看到
查看集群信息
docker exec -it redis-6384 redis-cli -p 6384 -a 'tan!@#' -ccluster nodes

6382 原来是master 但是状态是fail,6386角色变成了master
节点恢复
docker start redis-6382
进入客户端,6382虽然恢复了,但是并不会是master,是slave角色

从属调整
cluster failover
在Redis Cluster中,failover指的是当主节点(master)不可用时,自动切换为使用备份节点(slave)作为新的主节点的过程。这是一种高可用性机制,旨在确保Redis Cluster在主节点故障时仍然能够继续正常运行。当主节点故障或不可用时,Redis Cluster中的其他备份节点会通过一个集体决策的过程选举出一个新的主节点。选举的过程通常基于内部的集群状态信息和算法来进行,选举完成后,新的主节点会接管主节点的角色,提供读写操作的服务。在Redis Cluster中,failover是自动进行的,集群中的节点会自动检测主节点的故障,并且在必要时进行选举和切换。这意味着当主节点故障时,Redis Cluster可以快速自动地恢复,并继续处理客户端的请求,从而实现高可用性和持续的服务可用性。需要注意的是,当发生failover时,会产生一定的服务中断(通常是几毫秒到几秒钟),直到新的主节点选举完成并开始提供服务。这是因为在切换期间,正在执行的操作需要被暂时中断,以便进行状态同步和重新分配数据的过程。总结起来,Redis Cluster中的failover是指在主节点故障时,自动选择并切换为备份节点作为新的主节点,以确保系统的高可用性和持续的服务可用性。
docker exec -it redis-6382 redis-cli -p 6382 -a 'tan!@#' -c

7.5 主从扩容
1.新增6388,6389 两个实例。配置文件和7.1保持一致即可
docker run --net=host --restart=always -p 6388:6388 --name redis-6388 \
-v /data/redis-6388/data:/data/redis-6388/data \
-v /data/redis-6388/conf/redis.conf:/etc/redis/redis.conf \
-v /data/redis-6388/logs/redis.log:/data/redis-6388/logs/redis.log \
-d redis:7.0.12 redis-server /etc/redis/redis.confdocker run --net=host --restart=always -p 6389:6389 --name redis-6389 \
-v /data/redis-6389/data:/data/redis-6389/data \
-v /data/redis-6389/conf/redis.conf:/etc/redis/redis.conf \
-v /data/redis-6389/logs/redis.log:/data/redis-6389/logs/redis.log \
-d redis:7.0.12 redis-server /etc/redis/redis.conf
2.进入客户端,将新增的6388作为master节点加入集群,后面的6382是集群中的主节点,可以换成其他主节点
docker exec -it redis-6388 /bin/bash
redis-cli -a 'tan!@#' -p 6388 --cluster add-node 192.168.240.10:6388 192.168.240.10:6382或者先登录到6388
redis-cli -a 'tan!@#' -p 6388
然后使用metting命令,参考7.7.2其他命令,cluster meet <ip> <port> :将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。
cluster meet 192.168.240.10 6382

3.查看集群信息,6388加入了集群,并成为主节点

4.重新分派槽位(reshard)
docker exec -it redis-6382 /bin/bash
redis-cli -a 'tan!@#' -p 6382 --cluster reshard 192.168.240.10:6382

5.查看集群信息
6388作为master已经负责有槽位
#docker exec -it redis-6382 /bin/bash
redis-cli -a 'tan!@#' -p 6382
cluster info

6.为6388分配从节点
docker exec -it redis-6389 /bin/bash
redis-cli -a 'tan!@#' --cluster add-node 192.168.240.10:6389 192.168.240.10:6388 --cluster-slave --cluster-master-id 3ccda8f593a4bd86a268824479449c2d00b41ec9

7.检查集群信息
redis-cli -a 'tan!@#' --cluster check 192.168.240.10:6389

7.6 主从缩容
1.将6388 和6389下线
先将6389从集群中移除
docker exec -it redis-6389 /bin/bash
redis-cli -a 'tan!@#' --cluster del-node 192.168.240.10:6389 3ccda8f593a4bd86a268824479449c2d00b41ec9

提示节点有数据,需要重新分配槽位,将6388的槽号清空,重新分配,将清出来的槽号都给6382
docker exec -it redis-6388 /bin/bash
redis-cli -a 'tan!@#' --cluster reshard 192.168.240.10:6382
输入是选择接受节点为6382
参考7.5.4

#6388的槽位数为0时可以移除节点
redis-cli -a 'tan!@#' --cluster del-node 192.168.240.10:6388 3ccda8f593a4bd86a268824479449c2d00b41ec9redis-cli -a 'tan!@#' --cluster del-node 192.168.240.10:6389 c3b0fccc9934e08681a5073dc69bf184b67b4e2c
再次检查集群信息
redis-cli -a 'tan!@#' --cluster check 192.168.240.10:6382

缩容完毕,停止redis-6388,redis-6389
docker stop redis-6388 redis-6389
7.7 其他命令
#集群修复
redis-cli -a 'tan!@#' --cluster fix 192.168.240.10:6382
#设置集群超时
redis-cli -a 'tan!@#' --cluster set-timeout 192.168.240.10:6382 10000
#查看集群信息
redis-cli -a 'tan!@#' --cluster info 192.168.240.10:6382
#检查集群状态
redis-cli -a 'tan!@#' --cluster check 192.168.240.10:6382#集群的任意一节点进行平衡集群节点slot数量
redis-cli -a 'tan!@#' --cluster rebalance 192.168.240.10:6382
#槽位平衡,指定源节点和目标节点
redis-cli -a 'tan!@#' --cluster reshard 192.168.240.10:6382 \--cluster-from a6a0b1be77ac380f1b8e430593d58d52603af096 \--cluster-to 6d9b8b70caf659c702e3fea245a48cfa46755437 \--cluster-slots 1000 --cluster-yes --cluster-pipeline 10 --cluster-replace
7.7.1 –cluster-help
redis-cli --cluster help
Cluster Manager Commands:create host1:port1 ... hostN:portN #创建集群--cluster-replicas <arg> #从节点个数check host:port #检查集群--cluster-search-multiple-owners #检查是否有槽同时被分配给了多个节点info host:port #查看集群状态fix host:port #修复集群--cluster-search-multiple-owners #修复槽的重复分配问题reshard host:port #指定集群的任意一节点进行迁移slot,重新分slots--cluster-from <arg> #需要从哪些源节点上迁移slot,可以逗号隔开从多个源节点完成迁移,参数是nodeid#还可以直接传递--from all这样源节点就是集群的所有节点不传递该参数,则会在迁移过程中提示用户输入--cluster-to <arg> #slot需要迁移的目的节点nodeid,目的节点只能填写一个,不传递该参数,则会在迁移过程中提示用户输入--cluster-slots <arg> #需要迁移的slot数量,不传递该参数的话,则会在迁移过程中提示用户输入。--cluster-yes #指定迁移时的确认输入--cluster-timeout <arg> #设置migrate命令的超时时间--cluster-pipeline <arg> #定义cluster getkeysinslot命令一次取出的key数量,不传的话使用默认值为10--cluster-replace #是否直接replace到目标节点rebalance host:port #指定集群的任意一节点进行平衡集群节点slot数量 --cluster-weight <node1=w1...nodeN=wN> #指定集群节点的权重--cluster-use-empty-masters #设置可以让没有分配slot的主节点参与,默认不允许--cluster-timeout <arg> #设置migrate命令的超时时间--cluster-simulate #模拟rebalance操作,不会真正执行迁移操作--cluster-pipeline <arg> #定义cluster getkeysinslot命令一次取出的key数量,默认值为10--cluster-threshold <arg> #迁移的slot阈值超过threshold,执行rebalance操作--cluster-replace #是否直接replace到目标节点add-node new_host:new_port existing_host:existing_port #添加节点,把新节点加入到指定的集群,默认添加主节点--cluster-slave #新节点作为从节点,默认随机一个主节点--cluster-master-id <arg> #给新节点指定主节点del-node host:port node_id #删除给定的一个节点,成功后关闭该节点服务call host:port command arg arg .. arg #在集群的所有节点执行相关命令set-timeout host:port milliseconds #设置cluster-node-timeoutimport host:port #将外部redis数据导入集群--cluster-from <arg> #将指定实例的数据导入到集群--cluster-copy #migrate时指定copy--cluster-replace #migrate时指定replacehelp For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.
7.7.2 Redis Cluster
(客户端命令:redis-cli -c -p port -h ip)
redis-cli -c -p 6382 -h 192.168.240.10 -a 'tan!@#'
192.168.10.240.10:6382> #登录redis后,在里面可以进行下面命令操作
#集群
cluster info #打印集群的信息
cluster nodes #列出集群当前已知的所有节点( node),以及这些节点的相关信息。
#节点
cluster meet <ip> <port> #将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。
cluster forget <node_id> #从集群中移除 node_id 指定的节点。
cluster replicate <master_node_id> #将当前从节点设置为 node_id 指定的master节点的slave节点。只能针对slave节点操作。
cluster saveconfig #将节点的配置文件保存到硬盘里面。
#槽(slot)
cluster addslots <slot> [slot ...] #将一个或多个槽( slot)指派( assign)给当前节点。
cluster delslots <slot> [slot ...] #移除一个或多个槽对当前节点的指派。
cluster flushslots #移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
cluster setslot <slot> node <node_id> #将槽slot指派给node_id指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽,然后再进行指派。
cluster setslot <slot> migrating <node_id> #将本节点的槽 slot 迁移到 node_id 指定的节点中。
cluster setslot <slot> importing <node_id> #从 node_id 指定的节点中导入槽 slot 到本节点。
cluster setslot <slot> stable #取消对槽 slot 的导入( import)或者迁移( migrate)。
#键
cluster keyslot <key> #计算键 key 应该被放置在哪个槽上。
cluster countkeysinslot <slot> #返回槽 slot 目前包含的键值对数量。
cluster getkeysinslot <slot> <count> #返回 count 个 slot 槽中的键 。
8.集群总结
8.1 Redis Cluster特点
- 多主多从,去中心化:从节点作为备用,复制主节点,不做读写操作,不提供服务
- 不支持处理多个key:因为数据分散在多个节点,在数据量大高并发的情况下会影响性能;
- 支持动态扩容节点:这是我认为算是Rerdis Cluster最大的优点之一;
- 节点之间相互通信,相互选举,不再依赖sentinel:准确来说是主节点之间相互“监督”,保证及时故障转移
8.2 其它集群模式的区别
- 相比较sentinel模式,多个master节点保证主要业务(比如master节点主要负责写)稳定性,不需要搭建多个sentinel实例监控一个master节点;
- 相比较一主多从的模式,不需要手动切换**,具有自我故障检测,故障转移的特点**;
- 相比较其他两个模式而言,对数据进行分片(sharding),不同节点存储的数据是不一样的;
- 从某种程度上来说,Sentinel模式主要针对高可用(HA),而Cluster模式是不仅针对大数据量,高并发,同时也支持HA。
8.3集群的故障转移流程
当一个从节点发现自己正在复制的主节点下线时,从节点将开始对下线主节点进行故障转移:
1) 在该下线主节点的所有从节点中,选择一个做主节点
2) 被选中的从节点会执行SLAVEOF no one命令,成为新的主节点;
3) 新的主节点会撤销对所有对已下线主节点的槽指派,并将这些槽全部派给自己。
4) 新的主节点向集群广播一条PONG消息,让其他节点知道“我已经变成主节点了,并且我会接管已下线节点负责的处理的槽”;
5) 新主节点开始接收和自己负责处理的槽有关的命令请求,故障转移完成。
8.4 master的选举流程
1)集群配置纪元是一个自增计数器,它的初始值为0;
2)当集群里的某个节点开始一次故障转移时,集群配置纪元的值会被增加1
3)对于每个配置纪元,集群里的每个负责处理槽的主节点都有一次投票的机会,而第一个向主节点要求投票的从节点将获得主节点的投票。
4)当从节点发现自己正在复制的主节点进入已下线状态时从节点会向集群广播消息:要求所有收到这条消息、并且具有投票权的主节点向这个从节点投票。
5)如果一个主节点具有投票权并且这个主节点尚未投票跟其它从节点,那么主节点将要求投票的从节点返回一条ACK消息表示支持该从节点成为新的主点。
6)每个主节点只有一次投票机会,有N个主节点的话,那么具有大于N/2+1张支持票的从节点只有一个。
7)如果在一个配置纪元里没有从节点能收集到足够多的支持票,那么集群进入一个新的配置纪元,并再次进行选举,直到选出新的主节点为止。
总结:这跟sentinel模式下的选举类似,两个都是基于Raft算法的领头选举方法来实现。
8.5 集群的故障检测
集群中每个节点都会定期地向集群中的其他节点发送PING消息,以此检测对方是否在线;如果接收PING消息的节点没有在规定的时间内,向发送PING消息的节点返回PONG消息,那么发送PING消息的节点就会将PING消息节点标记为疑似下线(possible fail,PFAIL)。
如果在集群中,超过半数以上负责处理槽的主节点都将某个节点X标记为PFAIL,则某个主节点就会将这个主节点X就会被标记为已下线(FAIL),并且广播到这条消息,这样其他所有的节点都会立即将主节点X标记为FAIL。

假设:
- Redis Cluster有四个主节点:7000-7003,两个从节点:7004与7005
- 此时7000已下线,并且主节点7001认为主节点7000进入PFAIL
- 同时主节点7002、7003也认为主节点7000进入下线状态
这样一来超过半数的主节点都认为7000节点FAIL,那么7001便会标记7000为FAIL状态,并向集群广播主节点7000已经FAIL消息。

参考文章
1.一致性哈希算法原理详解
2.Hash一致性算法是如何解决数据倾斜问题的?
3.redis6 redis-cli cluster的使用总结
4.认识Redis集群——Redis Cluster - JJian - 博客园 (cnblogs.com)
5.Redis集群原理详解_张维鹏的博客-CSDN博客
6.尚硅谷阳哥redis7
相关文章:
docker 哨兵模式和集群模式安装Redis7.0.12
docker 哨兵模式和集群模式安装Redis7.0.12 1.下载镜像 1.1 配置阿里云加速源 墙外能访问https://hub.docker.com/_/redis 的可跳过 https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors 登录后选择左侧的镜像工具>镜像加速器,获取加速器地址&#…...
go nil 与零值
go nil 与零值 区别描述: 在Go语言中,nil和零值是两个不同的概念,它们在处理空值或未初始化值时有不同的应用场景。 nil: 在Go语言中,nil表示指针类型的零值或者interface、function、map、slice、channel、error类…...
puppeteer监听response并封装为express服务调用
const express require(express); const puppeteer require(puppeteer); const app express(); let browser; // 声明一个全局变量来存储浏览器实例app.get(/getInfo, async (req, res) > {try {const page_param req.query.page; // 获取名为"page"的查询参数…...
kubernetes之Ingress
一、背景 Ingress是k8s中实现7层负载的实现方式,是公开集群外部流量到集群内服务的HTTP和HTTPS路由 二、Ingress基础 通常Ingress实现由Ingress 控制器和Ingress组成,Ingress控制器负责具体实现反向代理及负载均衡,Ingress负责定义匹配规则和…...
前端实现打印1 - 使用 iframe 实现 并 分页打印
目录 打印代码对话框预览打印预览 打印代码 <!-- 打印 --> <template><el-dialogtitle"打印":visible.sync"dialogVisible"width"50%"top"7vh"append-to-bodyclose"handleClose"><div ref"print…...
MIAOYUN获评“2023年度一云多芯稳定安全运行优秀案例”
2023年7月25日至26日,由中国信息通信研究院(简称“中国信通院”)、中国通信标准化协会主办的以“云领创新,算启新篇”为主题的“2023可信云大会”在北京成功举办。会上公布了多项前瞻领域的评估结果和2023年度最佳实践案例&#x…...
论文代码学习—HiFi-GAN(4)——模型训练函数train文件具体解析
文章目录 引言正文模型训练代码整体训练过程具体训练细节具体运行流程 多GPU编程main函数(通用代码)完整代码 总结引用 引言 这里翻译了HiFi-GAN这篇论文的具体内容,具体链接。这篇文章还是学到了很多东西,从整体上说,…...
安防视频综合管理合平台EasyCVR可支持的视频播放协议有哪些?
EasyDarwin开源流媒体视频EasyCVR安防监控平台可提供视频监控直播、云端录像、云存储、录像检索与回看、智能告警、平台级联、云台控制、语音对讲、智能分析等能力。 视频监控综合管理平台EasyCVR具备视频融合能力,平台基于云边端一体化架构,具有强大的…...
一张表格讲明白white-space属性。html如何识别\n\r,让这些特殊换行符换行。
大多数标签在展示文本内容的时候都会默认把文本中的空白和换行符去掉,这的确大大的使得文本的排版更加美观了,也怎加了区域的利用率,可是就有一些需求是需要原原本本的展示出原汁原味的文本格式。那该如何展示出文本的内在格式呢?…...
【Linux】编写shell脚本将项目前一天打印的日志进行提取,并且单独保存
业务场景:又到了熟悉的业务场景环节,其实应用上有很多,我们为了方便提取日志中部分关键的内容,对接给其他人也好,方便自己统计也罢,都会比每次我们都去服务器上及时查看,或者下载全部日志再筛选…...
快速搭建单机RocketMQ服务(开发环境)
一、什么是RocketMQ RocketMQ是阿里巴巴开源的一个消息中间件,在阿里内部历经了双十一等很多高并发场景的考验,能够处理亿万级别的消息。2016年开源后捐赠给Apache,现在是Apache的一个顶级项目。 早期阿里使用ActiveMQ,…...
Centos7搭建Apache Storm 集群运行环境
文章目录 1. 安装 Java2. 下载并解压 Storm3. 配置环境变量4. 配置 ZooKeeper5. 配置 Stormstorm.yaml自定义 storm.yamlstorm-env.shlogback/cluster.xml 6. 启动 Storm 集群7. 验证 1. 安装 Java Storm 运行在 Java 平台上,因此需要先安装 Java。你可以使用以下命…...
C语言假期作业 DAY 12
一、选择题 1、请阅读以下程序,其运行结果是( ) int main() { char cA; if(0<c<9) printf("YES"); else printf("NO"); return 0; } A: YES B: NO C: YESNO D: 语句错误 答案解析 正确答案: A 0<c&l…...
2.4在运行时选择线程数量
在运行时选择线程数量 C标准库中对此有所帮助的特性是std::thread::hardware_currency()。这个函数返回一个对于给定程序执行时能够真正并发运行的线程数量的指示。例如,在多核系统上它可能是CPU 核心的数量。它仅仅是一个提示,如果该信息不可用则函数可…...
element-ui中Notification 通知自定义样式、按钮及点击事件
Notification 通知用于悬浮出现在页面角落,显示全局的通知提醒消息。 一、自定义html页面 element-ui官方文档中说明Notification 通知组件的message 属性支持传入 HTML 片段,但是示例只展示了简单的html片段,通常不能满足开发中的更深入需要…...
无头单向非循环单链表、带头双向循环链表
文章内容 1. 链表的概念及结构 2. 链表的分类 3.链表实现 4.代码 文章目录 1. 链表的概念及结构 概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表 中的指针链接次序实现的 。 现实中 数据结构中 链表和顺序表…...
UE4/5C++多线程插件制作(二十、源码)
目录 头文件 MultiThreadPlugins.uplugin MultiThreadPlugins.Build.cs MultiThreadPlugins.h MTPPlatform.h MTPManage.h RTPAgendy.h MTPThreadTaskManage.h...
构建稳健的PostgreSQL数据库:备份、恢复与灾难恢复策略
在当今数字化时代,数据成为企业最宝贵的资产之一。而数据库是存储、管理和保护这些数据的核心。PostgreSQL,作为一个强大的开源关系型数据库管理系统,被广泛用于各种企业和应用场景。然而,即使使用了最强大的数据库系统࿰…...
查看本地mysql账号密码
使用Navicat工具打开本地mysql,新建查询输入下面查询语句 SELECT user, authentication_string FROM mysql.user WHERE userroot将authentication_string 中的加密密码复制出来打开链接: Magic Data 5输入加密的密码,和验证码,点…...
数据结构:顺序表详解
数据结构:顺序表详解 一、 线性表二、 顺序表概念及结构1. 静态顺序表:使用定长数组存储元素。2. 动态顺序表:使用动态开辟的数组存储。三、接口实现1. 创建2. 初始化3. 扩容4. 打印5. 销毁6. 尾插7. 尾删8. 头插9. 头删10. 插入任意位置数据…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...
解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...
