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.12
docker 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.conf
docker 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.conf
docker 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.conf
docker 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.conf
docker 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.conf
docker 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.conf
docker 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.conf
docker 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.conf
docker 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.conf
docker 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!@#' -c
cluster 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.conf
docker 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 3ccda8f593a4bd86a268824479449c2d00b41ec9
redis-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-timeout
import host:port #将外部redis数据导入集群
--cluster-from <arg> #将指定实例的数据导入到集群
--cluster-copy #migrate时指定copy
--cluster-replace #migrate时指定replace
help
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