Redis集群的三种方式
1:Windows下内置主从模式
1:基本介绍
在主从复制中,一个主节点可以有多个从节点,但是一个从节点只能对应一个主节点。这样,当一个slave宕机时,不会影响其他slave的读取和master的读写;但是,重启之前宕机的slave的服务后,会从自动master同步数据(前提是配置文件上配置了主从复制。如果通过命令设置了主从复制,则没有不管哪个宕机重启,都会变成普通的单机redis,默认是master)。在主从模式下,只有一个主节点可以读写,而从节点只能读,所以通常主节点负责写,从节点负责读(因为读操作是最频繁的) )。但是,当唯一的master挂掉时,slave的读操作不会受到影响,但是当前主从复制redis服务的写操作会受到影响。 Redis 将不会再次提供写入服务,直到 master 重新启动(前提是配置文件中配置了主从复制)

2:主从复制的优缺点
优势:
1:支持主从复制,主机(Master)的数据会自动同步到从机(Slave),读写分离是可能的
2:为了负载分担 Master 读操作压力, Slave 服务端可以为客户端提供只读操作服务,而写服务仍然必须由服务端 Master 来完成
3:Slave Others 也可以接受 Slaves 的连接和同步请求,可以有效分担 Master 同步压力的负载。
4:Master Server 以非阻塞的方式 Slaves 提供服务。所以在 Master-Slave 同步期间,客户端仍然可以提交查询或修改请求。
5:Slave Server 也以非阻塞方式完成数据同步。同步过程中,如果客户端提交查询请求,Redis会返回同步前的数据
缺点:
1:Redis没有自动容错和恢复功能,主机和从机宕机会导致前端部分读写请求失败。需要等待机器重启或者手动切换前端IP才能恢复。
2:当主机宕机时,部分数据在关机前无法及时同步到从机,切换到IP之后,会引入数据不一致的问题,降低了系统的可用性。
3:Redis 难以支持在线扩容。当集群容量达到上限时,在线扩容会变得非常复杂。
3:配置主从模式
为了方便windows下的主从拷贝操作(Linux和这里的windows操作基本一样,都是解压后拷贝出来的)
注:如果不是Redis Redis下如何创建文档请参考Redis基本操作
环境科学:
Redis:解压三份Redis Application(这里我以6.2.5为例)
解压文件夹:
redis6379 用于配置主机Master
redis6380 用来配置slave从1
redis6381 用于配置slave从机2
修改redis6379,redis6380,redis6381 下redis配置
**注意:Windows中的Redis配置文件一般下面是“redis.windows.conf”
注意:Windows下的Redis配置文件一般下面是“redis.conf”
**
1:redis6379主配置文件修改
Redis 中的各种配置如果不了解,请参考“”
进入redis6379 Master节点Master文件夹下修改基本配置
1:指定Redis主节点端口(端口不能冲突)
端口:6379
2:指定一个新的PID文件路径(windows(不在windows下)
pidfile /var/run/redis_6379.pid
3:日志文件位置,当指定为“空字符串”时为标准输出。作为redis作为守护进程运行,日志会输出到“/dev/null”
日志文件“redisLog_6379.log”
4:RDB 持久化快照的文件名
dbfilename dump6379.rdb
5:设置redis连接密码
** 要求通过 1234 **
6:保护模式,默认开启,拒绝外部访问,建议关闭 -- 设置为:否
** 保护模式是的**
2:redis6380从节点(Slave1)配置文件修改
进入redis6380 Slave节点Slave1修改文件夹下的基本配置
1:指定Redis主节点端口(端口不能冲突)
端口:6380
2:指定一个新的PID文件路径(windows(不在windows下)
** pidfile /var/run/redis_6380.pid**
3:日志文件位置,当指定为“空字符串”时为标准输出。作为redis作为守护进程运行,日志会输出到“/dev/null”
日志文件“redisLog_6380.log”
4:RDB 持久化快照的文件名
** dbfilename dump6380.rdb**
5:设置redis连接密码
** 要求通过 1234 **
6:保护模式,默认开启,拒绝外部访问,建议关闭 -- 设置为:否
** 保护模式是的**
配置master 主地址
1:主从复制,使用replicaof来表示Master主节点地址,默认关闭
127.0.0.1 6379的副本
2:如果 Master 如果需要密码认证,这里设置。默认不设置
masterauth 1234
3:redis6381从节点(Slave 2)配置文件修改
进入redis6381 Slave节点Slave2修改文件夹下的基本配置
1:指定Redis主节点端口(端口不能冲突)
** 端口:6381**
2:指定一个新的PID文件路径(windows(不在windows下)
** pidfile /var/run/redis_6381.pid**
3:日志文件位置,当指定为“空字符串”时为标准输出。作为redis作为守护进程运行,日志会输出到“/dev/null”
日志文件“redisLog_6381.log”
4:RDB 持久化快照的文件名
** dbfilename dump6381.rdb**
5:设置redis连接密码
需要通过 1234
6:保护模式,默认开启,拒绝外部访问,建议关闭 -- 设置为:否
保护模式是的
配置master 主地址
1:主从复制,使用replicaof来表示Master主节点地址,默认关闭
127.0.0.1 6379的副本
2:如果 Master 如果需要密码认证,这里设置。默认不设置
** masterauth 1234**
4:启动主从模式
启动三个 Redis Server
注意:配置文件和服务放在一个目录下
建立bat脚本文件:redis服务startup.bat
@HO 关闭
rem 设置我们 redis 目录位置 打开 Redis Server
设置 redis_homeu003dC:\Users\xiaof\Desktop\redis
启动 cmd /k "cd /d %redis_home%\redis6379 && redis-server.exe redis.windows.conf"
启动 cmd /k "cd /d %redis_home%\redis6380 && redis-server.exe redis.windows.conf"
启动 cmd /k "cd /d %redis_home%\redis6381 && redis-server.exe redis.windows.conf"
退出
建立bat脚本文件:redis Client startup.bat
@HO 关闭
rem 设置我们 redis 目录位置 打开 Redis 客户端
设置 redis_homeu003dC:\Users\xiaof\Desktop\redis
开始 cmd /k "cd /d %redis_home%\redis6379 && redis-cli.exe -h 127.0.0.1 -p 6379 -a 1234"
开始 cmd /k "cd /d %redis_home%\redis6380 && redis-cli.exe -h 127.0.0.1 -p 6380 -a 1234"
开始 cmd /k "cd /d %redis_home%\redis6381 && redis-cli.exe -h 127.0.0.1 -p 6381 -a 1234"
退出
建立bat脚本文件:redis Server客户端shutdown.bat
@HO 关闭
启动 cmd /k "taskkill /f /t /im redis-server.exe && taskkill /f /t /im cmd.exe"
退出
5:测试主从复制
此时即使我们成功设置了主从复制,在宿主机上使用set命令会同步到其他从机,但是从机上不会有写命令
info replication 属性说明:
角色
当前 Redis 服务器角色(会有 Master 和 slave)
** 已连接_slaves**
当前 Redis 服务器下连接的从机数量
** 奴隶(N)**
slave stateu003donline的连接状态信息代表在线状态
** master_failover_state**
主节点的故障转移状态。可选值如下:
no-failover:当前没有正在协调的故障转移。
waiting-for-sync:主节点正在等待副本获取其副本数据偏移值。
正在进行的故障转移:主节点已降级并尝试将所有权转移到目标副本。
** 主_replid**
每次重启 redis 都会生成一个 40 位的 ID,用于主从复制。一个标识增量的标识符
** 主_主机,主_端口**
连接主节点IP+端口号
主\链接\状态
已连接主节点状态 up 代表连接 down 代表未连接
Master Host 配置视图:
127.0.0.1:6379> 信息复制
复制
角色:主人
已连接_slaves:2
slave0:ip\u003d127.0.0.1,portu003d6381,stateu003donline,offsetu003d438,lagu003d0
slave1:ip\u003d127.0.0.1,portu003d6380,stateu003donline,offsetu003d438,lagu003d0
master_failover_state:no-failover
主_replid:e96c06dc1ffde9d13cb7791bdfba36dd26b89794
主_replid2:0000000000000000000000000000000000000000
主_repl_offset:438
第二_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl\backlog\first\byte\offset:1
repl_backlog_histlen:438
从机查看从机配置:
127.0.0.1:6380> 信息复制
复制
角色:奴隶
主_主机:127.0.0.1
主_端口:6379
主\链接\状态:向上
主_last_io_seconds_ago:11
主\同步\在\进度:0
从_repl_offset:410
从_优先级:100
从_read_only:1
副本_宣布:1
已连接_slaves:0
master_failover_state:no-failover
主_replid:e96c06dc1ffde9d13cb7791bdfba36dd26b89794
主_replid2:0000000000000000000000000000000000000000
主_repl_offset:410
第二_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl\backlog\first\byte\offset:1
repl_backlog_histlen:410
6:使用命令模式配置主从复制
不建议这样配置主从,只能用于测试,因为这样配置的主从不会持久化,每次关闭都会变成单机关闭并重新启动
以上面的配置文件构建案例为例。 Redis服务关闭后,注意host和slave的配置文件中配置的#replicaof、masterauth和requirepass
此时脚本启动的Redis服务都是单Master主机
此时我们可以看到 Master 原来的主节点中没有从节点。接下来,我将6380和6381设置为从机
127.0.0.1:6379> 信息复制
复制
角色:主人
已连接_slaves:0
主_failover_state:无故障转移
主_replid:a0b02f9a1a0e6a2b24c90a19a7d9c2e5e1f2c96c
主_replid2:0000000000000000000000000000000000000000
主_repl_offset:0
第二_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl\backlog\first\byte\offset:0
repl_backlog_histlen:0
将 Redis6380 设置为从节点Slave1:
127.0.0.1:6380> 从 127.0.0.1 6379
将 Redis6381 设置为从节点 Slave2:
127.0.0.1:6381> 从 127.0.0.1 6379
此时主从6379设置为Master Master节点;6380,6381由Slave Slave节点
如果其中一个slave想要与主机断开连接,执行以下步骤:slaveof no one
如果主节点宕机了,不会影响从机的读,但是主节点的缺失意味着没有写功能
如果slave宕机后重启,之前配置为slave的配置会被初始化,启动后默认为单主机
7:简单介绍主从复制的原理
**全同步:**一般发生在Slave连接主机后的初始化阶段,此时Slave需要将Master上的所有数据复制
1:要从服务器连接到主服务器,先发送一条消息 SYNC 命令;
2:主服务器收到 SYNC 命名后,主服务器开始执行 bgsave 命令生成 RDB 文件,并使用缓冲区记录此后执行的所有写命令;
3:主服务器bgsave命令执行后,将快照文件发送给所有从服务器,并继续记录发送过程中主服务器执行的写命令;
4:从服务器接收到快照文件后,丢弃所有旧数据,加载接收到的快照;
5:从主服务器发送快照后,开始向从服务器发送缓冲区中的写命令;
6:完成从服务器加载快照,开始接收命令请求,从主服务器缓冲区执行写入命令;
完成以上步骤后,从服务器初始化数据的所有操作就完成了。此时,服务器可以接收到用户的读取请求。
**增量同步:**Redis增量复制是指Slave初始化后开始正常工作时,将主服务器的写操作同步到从服务器的过程。
增量复制的主要过程是主服务器每次执行写命令时,都会向从服务器发送相同的写命令,从服务器接收并执行接收到的写命令。
2:Linux下的主从复制
通过以上Windows下的构建操作,这里就不罗嗦了。我可以直接开始施工
如果不熟悉如何在Linux上搭建单机Redis,请参考:Redis介绍及环境搭建
主从复制完成后是这样的:

如果想根据我的目录快速搭建主从复制,可以直接复制如下代码:
**具体步骤:
1:拿着redis-6.2.6.tar.gz 把压缩包放到home目录下解压
rz -y
tar -zxvf redis-6.2.6.tar.gz
2:解压后进入redis目录下编译安装,
cd redis-6.2.6/
make && make PREFIXu003d/home/redis6379 安装
3:拷贝成三份(主从拷贝6379主、6380、6381从)
cp -r redis 6379 redis 6380
cp -r redis 6379 redis 6381
4:为每个redis创建profile目录并复制redis配置文件
mkdir /home/redis6379/conf
mkdir /home/redis6380/conf
mkdir /home/redis6381/conf
cp /home/redis-6.2.6/redis.conf /home/redis6379/conf/redis6379.conf
cp /home/redis-6.2.6/redis.conf /home/redis6380/conf/redis6380.conf
cp /home/redis-6.2.6/redis.conf /home/redis6381/conf/redis6381.conf
5:编辑每个 Redis 目录 redis63*.conf 配置文件
详见上文 Windows 下,设置主从复制第 3 节中的文件配置
6:编写启动脚本:startRedis.sh 和 stopRedis.sh
光盘 /home/
猫 > startRedis.sh <<EOF
#!/bin/sh
/home/redis6379/bin/redis-server /home/redis6379/conf/redis6379.conf 2>&1 &
/home/redis6380/bin/redis-server /home/redis6380/conf/redis6380.conf 2>&1 &
/home/redis6381/bin/redis-server /home/redis6381/conf/redis6381.conf 2>&1 &
回显“redis 已启动”
EOF
猫 > stopRedis.sh <<EOF
#!/bin/sh
#停止redis
ps -ef|grep redis |grep -v grep|awk '{print }'|xargs kill
回显“redis 已停止”
EOF
chmod 744 startRedis.sh stopRedis.sh**
下一步是开始测试。可以根据上述测试进行测试。启动时,启动命令!
Redis 客户端启动:
/home/redis6379/bin/redis-cli -h 127.0.0.1 -p 6379 -a 1234
/home/redis6380/bin/redis-cli -h 127.0.0.1 -p 6380 -a 1234
/home/redis6381/bin/redis-cli -h 127.0.0.1 -p 6381 -a 1234
然后通过:info replication 命令查看具体的主从服务
通过tail -f XXX Conf 实时刷新日志视图
3:Linux下构建的哨兵模式
1:基本介绍
引入主从复制后,我们知道slave成为master的slave节点后,一旦master主节点宕机,我们可以选择一个正常的slave成为新的master节点,然后再连接其他slave节点到新的主节点,实现手动故障恢复。但人工干预效率低,容易出错,故障感知滞后,不具备生产实用性。一个能够自动感知系统故障并自动进行故障转移的可靠组件一定是生产环境中最需要的。为此,Redis 官方提供了一个高可用的解决方案——Sentinel,可以用来构建一个高可用的 Redis 分布式系统,即使不需要干预也能抵抗某些类型的故障。
Sentry 是 Redis 的一种运行模式。重点监控Redis实例(主节点和从节点)的运行状态,可以在主节点故障时通过一系列机制实现主节点选择和主从切换,从而实现故障转移,保证主节点的可用性。整个 Redis 系统。
Redis Sentinel 官方文档
Redis 官方称Redis Sentinels有以下功能:
监视器(监控):
持续监控 Redis 主节点和从节点是否处于预期的工作状态。
通知(通知):
Sentry 可以将 Redis 实例 API 的运行故障信息通知监控系统或其他应用程序。
自动故障恢复(自动故障转移):
当主节点出现故障时,Sentry会启动故障自动恢复过程:一个从节点升级为主节点,其他从节点使用新的主节点进行主从复制,
通知客户端使用新的主节点。
配置中心(配置提供者):
哨兵可以作为客户端服务发现的授权源。客户端连接哨兵请求给定服务Redis Master节点地址的授权。如果发生故障转移,哨兵将通知新地址。
这里注意:Sentinels 不是 Redis Proxy,它只是为客户端提供主从节点的 Redis 地址信息。
Sentinel 分布式特点:
Redis Sentinel 是一个分布式系统,基于一组配置设计,多个sentinel 实例协同工作。多实例协作具有以下优点:
1:主节点系统故障在多个实例联合识别时完成,大大降低了误报概率。
2:即使不是所有的sentinel实例都正常运行,sentinel集群也可以正常工作(除非所有的sentinel实例都down了),大大增加了系统的稳定性和健壮性。
2:哨兵模式的作用
Sentinel 发送命令让 Redis 服务器(Master 服务器和 Slave 服务器)恢复到当前运行状态;当哨兵检测到Master宕机时,哨兵服务会自动将Slave切换为Master,然后通过发布订阅的方式通知其他Slave服务器修改配置文件让他们切换主机;但是,如果有哨兵进程服务监控 Redis 服务器,也可能会出现停机。因此,我们可以使用多个哨兵进行监控。每个哨兵也会被监控,形成多哨兵模式。即使一个sentinel进程宕机了,后续的sentinel也可以继续工作
优势:
Sentinel 模式基于主从模式。哨兵模式具有主从模式的所有优点
主从自动切换,使系统更健壮,更可用
缺点:
Redis 难以支持在线扩容。当集群容量达到上限时,在线扩容会变得非常复杂
3:故障转移过程
假设Master服务器宕机,哨兵A首先检测到这个结果,不会立即进行故障转移过程。只有哨兵A主观认为Master服务器不可用,成为主观下线现象(不确定Master宕机)。当哨兵B、哨兵C、哨兵D在后面也检测到Master服务器不可用,而当多个哨兵服务主观认为Master宕机且数量主观认为达到一定值时,A投票将在哨兵之间举行,投票结果将由一个哨兵发起故障转移。切换成功后,每个哨兵都会通过发布订阅方式从服务器切换主机。这个过程叫做objective offline(Master确实宕机了)。这样,一切对客户来说都是透明的。
4:哨兵模式的工作原理

1:每个哨兵(哨兵进程以每秒一次的频率向整个集群中的主服务器(Master)、从服务器(Slave)、哨兵(Sentinel)进程发送信息
发送 PING 命令。
2:如果一个实例(instance)最后一次有效回复 PING 命令时间超过了 down-after-milliseconds 选项指定的值(默认为 30 秒),
这个实例将被标记为离线的哨兵进程(SDOWN)
3:如果有一个Master被标记为主观下线(SDOWN),正在监控这个Master的所有Sentinel进程应该每秒确认一次Master
你有没有进入主观离线状态
4:当有足够的 Sentinel 进程(大于等于配置文件中指定的值)在指定的时间范围内确认 Master 进入主观下线状态(SDOWN),
那么主主会被标记为离线(ODOWN)
5:一般情况下,每个 Sentinel 进程每 10 秒向集群中的所有 Master 主服务器 Slave 发送消息,从服务器发送 INFO 命令,
目的是寻找从节点,确定主从关系。
6:当 Master 覆盖 Sentinel Process 标记为离线(ODOWN)时,Sentinel Process 下线 Master 所有的 Slave 发出 INFO 命令的频率会从
10 从每秒一次变为每秒一次。
7:如果 Sentinel Process 协议没有足够的 Master 下线,则 Master 的客观下线状态会被移除。如果之前标记为 Master 则返回 Sentinel 进程
发送 PING 命令返回有效回复,Master 主服务器的主观离线状态将被移除。
5:构建哨兵模式
哨兵模式是基于主从复制模式的,所以你要准备一个主从模式基本的一主两从模式环境
注意:这里的主从构建完全使用第二节Linux目录配置中的主从副本在下一个构建中
这里我使用多哨兵模式(都在127).0.0.1(机内):
./redisSentinel26379 哨兵存放在这个文件夹A端口:26379
./redisSentinel26380 哨兵存放在这个文件夹B端口:26380
./redisSentinel26381 哨兵存放在这个文件夹C端口:26381
1:为哨兵模式创建文件夹
mkdir /home/sentinel
2:3份Redis程序作为哨兵程序,拷贝哨兵配置文件(这里我是直接从原master拷贝6379到拷贝主机)
cp -r /home/redis6379 /home/sentinel/redisSentinel26379
cp -r /home/redis6379 /home/sentinel/redisSentinel26380
cp -r /home/redis6379 /home/sentinel/redisSentinel26381
rm -rf /home/sentinel/redisSentinel26379/conf/*
rm -rf /home/sentinel/redisSentinel26380/conf/*
rm -rf /home/sentinel/redisSentinel26381/conf/*
cp /home/redis-6.2.6/sentinel.conf /home/sentinel/redisSentinel26379/conf/sentinel26379.conf
cp /home/redis-6.2.6/sentinel.conf /home/sentinel/redisSentinel26380/conf/sentinel26380.conf
cp /home/redis-6.2.6/sentinel.conf /home/sentinel/redisSentinel26381/conf/sentinel26381.conf
3:编写哨兵启动脚本
cd /home/哨兵
猫 > startRedisSentinel.sh << EOF
#!/bin/sh
/home/sentinel/redisSentinel26379/bin/redis-sentinel /home/sentinel/redisSentinel26379/conf/sentinel26379.conf 2>&1 &
/home/sentinel/redisSentinel26380/bin/redis-sentinel /home/sentinel/redisSentinel26380/conf/sentinel26380.conf 2>&1 &
/home/sentinel/redisSentinel26381/bin/redis-sentinel /home/sentinel/redisSentinel26381/conf/sentinel26381.conf 2>&1 &
echo "redis sentinel 已启动"
EOF
chmod 744 startRedisSentinel.sh

6:更改配置文件
注意:每个哨兵的配置文件必须一致。处理端口和日志文件之间存在差异。其他人监控主机
1:保护模式,默认开启,拒绝外部访问,建议关闭 -- 设置为:否
保护模式无
2:指定一个新的PID文件路径(windows(不在windows下)
pidfile /var/run/redis-sentinel26379.pid
3:日志文件位置
日志文件“./redisSentinelLog26379.log”
4:工作目录(存放运行时文件)
目录 /home/sentinel
5:配置主服务器进行监听。这里哨兵监控代表监控
-- mymaster 代表服务器名,可以自定义
-- 127.0.0.1 6379 代表被监控的主服务器IP和端口
-- 2 表示只有当两个或多个哨兵认为主服务器不可用时才会进行故障转移
哨兵监控 mymaster 127.0.0.1 6379 2
6:定义连接主服务密码(搭建的主从服务密码必须一致,否则会出问题)
-- mymaster 服务名(对应上面) 1234 是密码
哨兵 auth-pass mymaster 1234
7:开始哨兵测试
注意:必须先启动主从复制机。确认没有问题后,再次启动多哨机
执行前脚本启动:/startRedisSentinel.sh
开始哨兵日志打印:
启动26379、26380、26381的哨兵服务(对于26379的日志,三个日志是一样的)
~# oO0OoO0OoO0Oo Redis 正在启动 oO0OoO0OoO0Oo
~# Redis versionu003d6.2.6, bitsu003d64, commitu003d00000000, modifiedu003d0, pidu003d9099, 刚开始
~# 配置加载
~* 将打开文件的最大数量增加到 10032(最初设置为 1024)。
~* 单调时钟:POSIX 时钟_gettime
~* 运行模式u003dsentinel,端口u003d26379。
~# WARNING: TCP backlog 设置无法强制执行 511,因为 /proc/sys/net/core/somaxconn 设置为较低的值 128。
~# Sentinel ID 为 ae12e9902494e32aa77172ad7900dafb83b29ea4
**~# +monitor master mymaster 127.0.0.1 6379 quorum 2
~* +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
~* +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
~* +sentinel sentinel dbeba218078a3400c04c0fb2247861be0167e2b8 127.0.0.1 26381 @ mymaster 127.0.0.1 6379
~* +哨兵哨兵 335d08176477f79734a60420f0b1890303c9aec1 127.0.0.1 26380 @ mymaster 127.0.0.1 6379**
使用客户端连接哨兵服务:
/home/sentinel/redisSentinel26379/bin/redis-cli -h 127.0.0.1 -p 26379
哨兵基本命令:
平
回复 PONG。
哨兵大师
显示所有被监控的主机及其状态
哨兵大师 <主人名称>
显示指定监控的master的信息和状态;如果我们将名称设置为 mymaster
哨兵奴隶 <主人名称>
显示分配主机所有从机及其状态
sentinel get-master-addr-by-name <master name>
返回指定master的ip和端口,如果正在进行failover或者failover已经完成,
将显示提升为 ip 和端口的 slave 的 master。
哨兵重置<模式>
重置所有匹配正则表达式的名字 master 的状态信息,并且知道之前的状态信息,和 slaves 信息
哨兵故障转移 <主名称>
force sentinel 实施故障转移,而且你不需要征得其他任何 sentinel 的同意。
然而failover 最新的配置会被发送给其他用户哨兵。
主机停机模拟:
强杀主节点6379服务器30秒后,哨兵会进行主节点选举
Sentinel 26379 日志打印:
~# +sdown master mymaster 127.0.0.1 6379
~# +odown master mymaster 127.0.0.1 6379 #quorum 2/2
~# +new-epoch 1
~# +try-failover master mymaster 127.0.0.1 6379
~# +投票给领导 ae12e9902494e32aa77172ad7900dafb83b29ea4 1
~# dbeba218078a3400c04c0fb2247861be0167e2b8 投给 ae12e9902494e32aa77172ad7900dafb83b29ea4 1
~# 335d08176477f79734a60420f0b1890303c9aec1 投给 ae12e9902494e32aa77172ad7900dafb83b29ea4 1
~# +elected-leader master mymaster 127.0.0.1 6379
~# +failover-state-select-slave master mymaster 127.0.0.1 6379
~# +selected-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
~* +failover-state-send-slaveof-noone slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
~* +failover-state-wait-promotion slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
~# +promoted-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
~# +failover-state-reconf-slaves master mymaster 127.0.0.1 6379
~* +slave-reconf-sent 从属 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
~* +slave-reconf-inprog 从属 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
~* +slave-reconf-done 从属 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
~# -odown master mymaster 127.0.0.1 6379
~# +failover-end master mymaster 127.0.0.1 6379
~# +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380
~* +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
~* +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
~# +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
哨兵26380和26381日志打印(两者相同)
~# +sdown master mymaster 127.0.0.1 6379
~# +new-epoch 1
~# +投票给领导 ae12e9902494e32aa77172ad7900dafb83b29ea4 1
~# +odown master mymaster 127.0.0.1 6379 #quorum 3/2
~# 下一次故障转移延迟:我不会在 2022 年 1 月 14 日星期五 01:16:10 之前启动故障转移
~# +config-update-from sentinel ae12e9902494e32aa77172ad7900dafb83b29ea4 127.0.0.1 26379 @ mymaster 127.0.0.1 6379
~# +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380
~* +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
~* +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
~# +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
从上面的日志可以看出6379宕机了,但是哨兵选择了6380作为主机,从主机连接到6380作为主机
原主机宕机后在线模拟:
命令切换到主目录:/home/redis6379/bin/redis server/home/redis6379/conf/redis6379 conf 2>&1 &
**但是,启动6379后,日志拼命打印如下日志,发现无法连接到哨兵选举的主机(在Redis(如果服务器有密码的话)
~* 正在使用 SYNC 重试...
~# MASTER 中止复制并出现错误:需要 NOAUTH 身份验证。
~* 失败后重新连接到 MASTER 127.0.0.1:6381
~* MASTER <-> REPLICA 同步开始
~* SYNC 的非阻塞连接触发了该事件。
~* 大师回复PING,复制可以继续...
~* (Noncritical) Master 不理解 REPLCONF 监听端口:-NOAUTH 需要认证。
~* (Noncritical) Master 不理解 REPLCONF capa: -NOAUTH 需要认证。
~* 部分重新同步不可能(没有缓存的主)
~# 主机对 PSYNC 的意外回复:-**NOAUTH 需要身份验证。
**此时你要杀6379 Redis 简单配置后服务redis6379.conf 里面找到masterauth 配置主机密码
主认证** **1234
此配置可以配置从master复制到slave时的密码**
Sentinel 26380 日志打印:
~# -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
~* +convert-to-slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
~# +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
~* +重启从机 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
~# -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
哨兵26379和26381日志打印(两者相同)
~# -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
~# +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
~* +重启从机 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
~# -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
此时6379的Redis服务会作为slave指向6380哨兵选举的Redis主机
8:哨兵日志输出状态说明
@
字符后面的内容用于指定主服务器。这些内容是可选的,它们仅在@Specified 字符前可用
当实例不是主服务器时使用
+奴隶
新的从服务器已被 Sentinel 识别和关联。
+减速
给定实例现在处于主观离线状态。
-sdown
给定的实例不再处于主观离线状态。
+向下
给定的实例现在离线。
-odown
给定的实例不再处于目标离线状态。
+新纪元
当前时代(纪元)已更新。
+尝试故障转移
一个新的故障转移操作正在进行中,等待被大多数 Sentinel Select( 等待被替换
由多数选举产生)
+reset-master
主服务器已重置
+显示器
主节点已被监控器监控
+故障转移状态重新配置从属设备
故障转移状态切换到 reconf-slaves 状态。
+检测到故障转移
另一台 Sentinel 启动故障转移操作,或将一台服务器从服务器转换为主服务器。
+slave-reconf-sent
Lead(leader)of Sentinel 发送到实例[SLAVEOF](/commands/slaveof.html)订单,
为实例设置一个新的主服务器。
+slave-reconf-inprog
实例正在将自己设置为指定主服务器的从服务器,但相应的同步过程尚未完成。
+从属重新配置完成
从服务器已成功完成新主服务器的同步。
-dup-sentinel
一个或多个监视给定主服务器的 Sentinel 已因重复而被删除 - 当 Sentinel 真实时
当实例重新启动时会发生这种情况。
+哨兵
已识别并添加了监控给定主服务器 Sentinel 的新服务器。
+民选领袖
在指定时代的选举中获胜后,可以进行故障转移操作。
+故障转移状态选择从属
故障转移操作现在处于 select-slave 状态—— Sentinel 寻找可以升级为主服务器的从服务器。
不好的奴隶
Sentinel 操作未能找到合适的从服务器进行升级。 Sentinel 会在一段时间后再次尝试找到合适的
从服务器升级,或直接放弃故障转移操作。
selected-slave
Sentinel 成功找到适合升级的从服务器。
故障转移-状态-发送-slaveof-noone
Sentinel 将指定的从服务器升级为主服务器,等待升级功能完成。
failover-end-for-timeout
故障转移因超时而中止,但最终所有从服务器将开始复制新的主服务器
(slave 最终将被配置为与新的 master 复制)
故障转移结束
故障转移操作成功完成。所有从服务器都已开始复制新的主服务器。
+开关主机
配置改变,主服务器IP和地址发生了变化。这是大多数外部用户关心的信息。
+倾斜
进入倾斜模式。
-倾斜
退出倾斜模式。
4:Linux集群模式下搭建(重点)
Redis 是我们目前大规模使用的缓存中间件。因其强大、高效、便捷的功能而被广泛使用。单节点redis实现了高性能。为了提高可用性,我们使用主从复制到哨兵,然后到更强大的redis集群。
Redis Cluster是Redis 3.0引入的分布式存储系统; Redis Cluster是一个可以在多个redis节点之间共享数据的工具。但是Redis Cluster不支持需要同时处理多个key的redis命令(比如mset、hmset...),因为这些命令需要在多个redis节点之间移动数据,而且在高负载下,这些命令会降低 Redis Cluster 的性能并导致不可预测的错误。
接下来,我将详细介绍Redis集群。主从和哨兵的构建只是为了了解集群的演进。本节适用于 Redis 版本 3.0 ~ 6.0
1:Redis集群介绍
Redis Cluster 通过分区(partition)来提供一定程度的可用性(availability);
即使集群中的某些节点发生故障或无法通信,集群也可以继续处理命令请求。
**Redis Clustering 提供以下两个好处:
自动数据分片(split)连接多个节点的能力,也就是下文提到的数据分片。
当集群中的某些节点发生故障或无法通信时,它们仍然可以继续处理命令请求。**
2:数据切片
Redis集群没有使用一致性哈希,而是引入了哈希槽的概念,用于实现数据分片;一个 redis 集群包含 16384 个哈希槽。经过计算,数据库中的每个key都会在16384个hash slot中的一个;对于集群中的slot位置计算,使用公式CRC16(key)% 16384来计算key属于哪个slot。 CRC16(key) 语句用于计算密钥的 CRC16 校验和。
集群中的每个节点都负责处理一部分哈希槽。例如,如果一个集群中有 3 个 Master 主节点,它最多可以有 3 个哈希槽,包括:
节点 A 负责处理散列槽 0 到 5460。[5461 个槽点]
节点 B 负责处理哈希槽 5461 到 10922。[5462 个槽点]
节点 C 负责处理哈希槽 10923 到 16383。[5461 个槽点]
这种将哈希槽分配到不同节点的方法使用户可以轻松地向集群添加或删除节点。
因为要添加一个集群Master节点,我只需要把前三个Master节点上的slots中的slot点取出来,分发到新添加的Master节点上的slots中即可;删除几乎相同。只需要提前提取Master节点上所有需要删除的slot点,分发到其他Master节点上的slot,然后删除Master节点
这时候想添加一个key key,例如:set a key 叫MyName u003d u003d> set MyName antLaddie
根据Redis Cluster的hash slot算法,CRC16('MyName') u003d 45121; 45121% 16384 u003d 12353,那么这个key分配给节点C;同理,当我连接任意一个节点(A,B,C),想要获取密钥MyName时,我会去节点C;如果用户将A新节点d添加到集群中,则集群只需将节点A、B、C中的一些槽移动到节点D。添加A D节点的结果可能如下(将ABC槽点分成几部分到d ):
节点 A 覆盖 1365-5460
节点 B 覆盖 6827-10922
节点 C 覆盖 12288-16383
节点D覆盖0-13645461-682610923-1228
同理,如果用户想从集群中移除节点A,集群只需要将节点A中的所有hash槽移动到节点B和节点C,然后移除空白(不包括任何hash槽)节点A,因为移动A hash slot 从一个节点到另一个节点不会造成节点阻塞,因此,无论添加新节点、移除现有节点,还是改变 A 节点包含的 hash slot 数量,集群都不会下线。
3:集群主从复制模型
为了保证在部分节点离线或无法与集群大部分节点通信时集群仍能正常运行,Redis集群对节点使用了主从复制功能;集群中的每个节点都有一到 n 个副本,其中一个是主副本,其他 N-1 个副本是从副本。在前面列举的节点A、B、C的例子中,如果节点B下线(没有slave节点),集群将无法正常运行,因为集群找不到A节点来处理从5461到10922的hash slot。手,如果我们在创建集群的时候(或者至少在节点B下线之前)将从节点B1添加到主节点B,那么当主节点B下线时,集群会将B1设置为新的主节点并让它替换离线master节点B继续处理从5461到10922的hash slot,这样集群就不会因为Primary节点B离线而无法正常运行。但是,如果节点B和B1都离线,则Redis 集群仍将停止工作。
一般来说,当负责指定slot的Master节点下线,并且在负责该slot的主从模型中找不到slave来替代Master节点时,整个集群会被设置为不可用状态;但是这个限制可以通过cluster require full coverage no来关闭,也就是说除了offline的slot,其他slot都可以正常读写
4:Redis一致性保证
Redis 不保证数据的强一致性。这意味着在实践中,集群在某些条件下可能会丢失写操作
第一个原因是集群使用异步复制。写操作流程:
1: Client to master B 写一个命令。
2:主节点B向客户端回复命令状态(成功或失败)。
3:主节点将写操作复制到当前主从副本B1,B2,B3...下的从节点
主节点返回命令状态回复后复制命令,因为如果主节点每次处理命令请求都需要等待复制操作完成,主节点处理命令请求的速度
会大大减少;我们必须在性能和一致性之间做出权衡。**注意:Redis 集群未来可能会提供同步写入的方法。
第二个原因是 Redis 集群可能会丢失命令的情况是集群有网络分区并且一个客户端与包括至少一个主节点在内的少数实例隔离:**
假设集群包含 A,B,C,A1,B1,C1 六个节点,其中 A,B,C 主节点,A1,B1,C1 由 A,B,C 有一个从节点和一个客户端 Z1 假设
如果集群发生网络分区,集群可能会分成两方,其中大部分包含节点 A,C,A1,B1,C1 ,一小部分一方包含节点 B 和客户端 Z1。
Z1 仍然可以连接到主节点 B 写入,如果短时间内出现网络分区,那么集群会继续正常运行,如果分区时间足够,大部分一方会被 B1 选为新的
master,即Z1写入B中的数据丢失。
注意在网络分片时,客户端 Z1 可以向主节点 B 申请发送写命令的最长时间是有限的,
这个时间限制称为节点超时(node timeout),是 Redis 集群的一个重要配置选项
5:Redis集群搭建准备
搭建 Redis 集群,至少需要准备三个 Master 节点和三个 Slave 节点。一共六个节点可以搭建一个Redis集群。因为六台机器成本太高,换成伪集群,部署在一台机器上;这里我将介绍Redis3 0~6.0两种方式搭建集群
注意:如果不需要直接使用5.0+版本,可以直接使用redis官方的cli-C来操作集群。您无需下载 Ruby 脚本
1:节点说明
127.0.0.1:8001[Master 主节点] 127.0.0.1:8004 [Slave 从节点]
127.0.0.1:8002[Master 主节点] 127.0.0.1:8005 [Slave 从节点]
127.0.0.1:8003[Master 主节点] 127.0.0.1:8006 [Slave 从节点]
127.0.0.1:8007[后面用来测试扩容]
127.0.0.1:8008[后面用来测试扩容]
127.0.0.1:8009 [后面用来测试扩容]
127.0.0.1:8010[后面用来测试扩容]
2:搭建基础环境和BaseRedis(是单机版Redis)
光盘 / 主页
yum -y install cpp binutils glibc glibc-kernheaders glibc-common glibc-devel gcc make gcc-c++ libstdc++-devel tcl
通过 rz -y 上传 Redis 压缩包 redis-3.2.9.tar.gz 或 redis-6.2.6.tar.gz
tar -zxvf redis-3.2.9.tar.gz
cd redis-3.2.9/
mkdir -p /usr/local/redisCluster/redisBase/bin
make && make PREFIXu003d/usr/local/redisCluster/redisBase 安装
这里我们有一个基本的Redis程序,你可以使用这个redisBase中的命令,用不同的配置文件批量启动集群
批量创建集群节点文件夹
mkdir -p /usr/local/redisCluster/redis8001 /usr/local/redisCluster/redis8001/etc
mkdir -p /usr/local/redisCluster/redis8002 /usr/local/redisCluster/redis8002/etc
mkdir -p /usr/local/redisCluster/redis8003 /usr/local/redisCluster/redis8003/etc
mkdir -p /usr/local/redisCluster/redis8004 /usr/local/redisCluster/redis8004/etc
mkdir -p /usr/local/redisCluster/redis8005 /usr/local/redisCluster/redis8005/etc
mkdir -p /usr/local/redisCluster/redis8006 /usr/local/redisCluster/redis8006/etc
mkdir -p /usr/local/redisCluster/redis8007 /usr/local/redisCluster/redis8007/etc
mkdir -p /usr/local/redisCluster/redis8008 /usr/local/redisCluster/redis8008/etc
mkdir -p /usr/local/redisCluster/redis8009 /usr/local/redisCluster/redis8009/etc
mkdir -p /usr/local/redisCluster/redis8010 /usr/local/redisCluster/redis8010/etc
每个节点文件夹下放一个Redis配置文件
cp /home/redis-3.2.9/redis.conf /usr/local/redisCluster/redis8001/etc/redisNodes_8001.conf
cp /home/redis-3.2.9/redis.conf /usr/local/redisCluster/redis8002/etc/redisNodes_8002.conf
cp /home/redis-3.2.9/redis.conf /usr/local/redisCluster/redis8003/etc/redisNodes_8003.conf
cp /home/redis-3.2.9/redis.conf /usr/local/redisCluster/redis8004/etc/redisNodes_8004.conf
cp /home/redis-3.2.9/redis.conf /usr/local/redisCluster/redis8005/etc/redisNodes_8005.conf
cp /home/redis-3.2.9/redis.conf /usr/local/redisCluster/redis8006/etc/redisNodes_8006.conf
cp /home/redis-3.2.9/redis.conf /usr/local/redisCluster/redis8007/etc/redisNodes_8007.conf
cp /home/redis-3.2.9/redis.conf /usr/local/redisCluster/redis8008/etc/redisNodes_8008.conf
cp /home/redis-3.2.9/redis.conf /usr/local/redisCluster/redis8009/etc/redisNodes_8009.conf
cp /home/redis-3.2.9/redis.conf /usr/local/redisCluster/redis8010/etc/redisNodes_8010.conf
基础文件创建完成后,我们需要修改各个节点的配置文件,然后一键启动脚本
1:修改各个节点下的配置文件,如下例所示。其他文件只需要应用此配置即可批量替换8001*
具体替换vim命令:%s/源字符串/目标字符串/g
端口号
端口 8001
# 设置任何外部IP都可以连接,或者设置指定IP连接用“-”隔开
绑定 0.0.0.0 或 * 新版本设置:绑定 * -::*
后台启动
守护是
指定数据文件的存储和分发位置。必须指定不同的目录位置,否则会丢失一些运行数据,例如日志、持久化文件等
目录 /usr/local/redisCluster/redis8001
指定一个新的PID进程文件路径(windows(no) when daemonize yes 是daemon时必须设置
pidfile /var/run/redisNodes_8001.pid
日志文件名
日志文件“/usr/local/redisCluster/redis8001/redisNodes_8001.log”
RDB 持久化快照的文件名
dbfilename dumpNodes_8001.rdb
open aof 注意:同时打开 AOF 和 RDB 当 Redis 重启时,会优先使用 AOF 文件来恢复数据集。如果考虑性能,可以关闭aof
仅附加是
#aof 文件路径
附加文件名“appendonly_8001.aof”
启动集群(必须开启)
启用集群是
#Cluster 节点配置文件
集群配置文件节点-8001.conf
集群连接超时
集群节点超时 5000
2:建立Redis Cluster启动脚本RedisClusterStart.sh 这里的8007 8008 8009 8010虽然启动了,但是没有用到。稍后用于扩容
猫 > RedisClusterStart.sh << EOF
#!/bin/sh
/usr/local/redisCluster/redisBase/bin/redis-server /usr/local/redisCluster/redis8001/etc/redisNodes_8001.conf
/usr/local/redisCluster/redisBase/bin/redis-server /usr/local/redisCluster/redis8002/etc/redisNodes_8002.conf
/usr/local/redisCluster/redisBase/bin/redis-server /usr/local/redisCluster/redis8003/etc/redisNodes_8003.conf
/usr/local/redisCluster/redisBase/bin/redis-server /usr/local/redisCluster/redis8004/etc/redisNodes_8004.conf
/usr/local/redisCluster/redisBase/bin/redis-server /usr/local/redisCluster/redis8005/etc/redisNodes_8005.conf
/usr/local/redisCluster/redisBase/bin/redis-server /usr/local/redisCluster/redis8006/etc/redisNodes_8006.conf
/usr/local/redisCluster/redisBase/bin/redis-server /usr/local/redisCluster/redis8007/etc/redisNodes_8007.conf
/usr/local/redisCluster/redisBase/bin/redis-server /usr/local/redisCluster/redis8008/etc/redisNodes_8008.conf
/usr/local/redisCluster/redisBase/bin/redis-server /usr/local/redisCluster/redis8009/etc/redisNodes_8009.conf
/usr/local/redisCluster/redisBase/bin/redis-server /usr/local/redisCluster/redis8010/etc/redisNodes_8010.conf
回显“redis 已启动”
EOF
chmod 744 RedisClusterStart.sh

这时候,我们启动10个节点的Redis。这时候Redis是以集群模式启动的,但是它们之间没有集群关联
6:Redis集群关联(原生)
集群的建立可以分为四个步骤:
1:启动节点:以集群方式启动节点。此时节点是独立的,没有连接;[上一节开始]
2:节点握手:将独立节点连接成一个网络;
3:分配槽位:为主节点分配16384个槽位;
4:指定主从关系:指定主节点为从节点。
注意:我这里只使用8001~8006 包括8001~8003 by Master 主节点分配槽,8004~8006 由Slave Slave节点
1:节点握手
以上10个节点启动后,相互独立,不知道其他节点的存在;需要节点握手来形成独立节点的网络。节点握手通过命令“cluster meet {ip} {port}”实现。例如在8001节点执行cluster meet 10.200.157.126 8002,完成8001节点和8002节点的握手;注意ip使用的是局域网ip,而不是localhost或者127.0.0.1,这样其他机器上的节点或者客户端也可以访问。可以使用集群节点查看
集群模式连接8001个节点:(这里必须加)-c(集群模式启动)
/usr/local/redisCluster/redisBase/bin/redis-cli -c -h 10.200.157.126 -p 8001
查看当前节点:(此时8001为单节点集群)
10.200.157.126:8001> 集群节点
3a00331cad40d52e5755c22699668574e090fa7e :8001 我自己,master - 0 0 0 connected
在8001节点下使用Cluster meet 命令将所有节点加入集群,完成节点握手:
集群满足 10.200.157.126 8002
集群满足 10.200.157.126 8003
集群满足 10.200.157.126 8004
集群满足 10.200.157.126 8005
集群满足 10.200.157.126 8006
2:分配槽
在 Redis 集群中,数据分区是借助 slot 实现的。集群有16384个槽位,是数据管理和迁移的基本单元。当数据库中16384个slot被分配节点时,集群处于online状态(ok);如果没有节点分配给任何插槽,集群将失败。 cluster info 命令可以查看集群状态。 slot分配前的状态为fail;
未分配(或未分配)的槽点:
10.200.157.126:8001> 集群信息
cluster_state:fail [集群状态失败失败正常[成功]
cluster_slots_assigned:0 [目前分配给整个集群的slots数量达到16384后才能启动]
采用 redis_cli 客户端命令为 8001 ~ 8003 分配槽位[随机分配点到各个段的槽位,我这里平均分配]
/usr/local/redisCluster/redisBase/bin/redis-cli -p 8001 集群添加槽 {0..5460}
/usr/local/redisCluster/redisBase/bin/redis-cli -p 8002 集群添加槽 {5461..10922}
/usr/local/redisCluster/redisBase/bin/redis-cli -p 8003 集群添加槽 {10923..16383}
分配后的槽点正常显示:
10.200.157.126:8001> 集群信息
集群_状态:好的
集群_slots_assigned:16384
3:指定主从关系
集群中指定主从关系时,不再使用slaveof命令,而是使用集群复制命令;参数使用节点 ID
从分配slot的时候就已经确定了master节点 Master 因为只有master节点才能分配slot,所以我将slave连接到主机
主 8001 --> 从 8004
主机 8002 --> 从机 8005
主机 8003 --> 从机 8006
**输入任意集群节点查询当前所有集群ID,用于分配主从关系。这里我去节点8001查看
**
开始分配主从:
cd /usr/local/redisCluster/redisBase/bin/
./redis-cli -p 8004 集群复制 3a00331cad40d52e5755c22699668574e090fa7e
./redis-cli -p 8005 集群复制 72cfe73954d8dc94f3ba0a3910885fccf1a26aba
./redis-cli -p 8006 集群复制 372db80734eaf94f4edeab82ab3b8e5ba4bc40d6
测试:
10.200.157.126:8001> 设置名称张三
-> 重定向到位于 10.200.157.126:8002 的插槽 [5798]
好的
[↑↑此时计算出来的name属于5798槽点,所以在8002时自动切换到8002节点保存]
10.200.157.126:8002> 设置年龄 22
-> 重定向到位于 10.200.157.126:8001 的插槽 [741]
好的
[↑↑此时计算age属于741槽点,所以在8001自动切换到8001节点保存]
7:Redis集群关联(Ruby脚本构建的redis trib)
redis trib命令详解(引用别人的文章)
除了使用native方式,我们还可以使用Ruby脚本来搭建集群,但是搭建前需要下载依赖Ruby和rubygems;下载后我们可以使用redis trib RB的Ruby脚本文件实现集群的自动构建
1:下载依赖ruby和rubygems:**yum -**y install ruby rubygems
2:安装redis和ruby界面:gem install redis
Redis5.0.0 以上版本不推荐使用此方法,因为有更好的方法redis-cli mode
遇到这种情况时,需要按以下步骤解决:
[root@MiWiFi-IR1200G-srv redisCluster]# gem install redis
获取:redis-4.5.1.gem (100%)
错误:安装redis时出错:
redis 需要 Ruby 版本 >u003d 2.4.0。 [我说的是Ruby需要2.4和2.4以上的[版本]
解决方案:
1:安装curl
百胜安装卷曲
2:安装rvm
卷曲-L get.rvm.io | bash -s 稳定
这个时候可能会出现问题:
curl: (7) 连接 raw.githubusercontent.com:443 失败;连接被拒绝
我们需要修改 hosts 文件:sudo vim /etc/hosts
然后把 199.232.28.133 raw.githubusercontent.com 复制 add hosts 最后一行文件
然后执行 curl -L get.rvm.io | bash -s 稳定
3:刷新rvm文件
源 /usr/local/rvm/scripts/rvm
5:见 rvm 库中已知的 ruby 版
rvm 列表已知
6:安装一个 ruby 版本
rvm 安装 2.6.3
7:使用一个 ruby 版本并设置为默认版本
rvm 使用 2.6.3
红宝石--版本
8:卸载已知版本
rvm 删除 2.0.0
9:安装最初出错的命令
[root@MiWiFi-IR1200G-srv redisCluster]# gem install redis
获取 redis-4.5.1.gem
成功安装redis-4.5.1
redis-4.5.1 的解析文档
为 redis-4.5.1 安装 ri 文档
0 秒后完成 redis 文档安装
1 个宝石已安装
我们现在可以使用 redis-trib.rb 来构建集群
解压编译 redis 里面的 redis-trib.rb 文件复制到我们的 redisBase 基本命令文件夹中
cp /home/redis-3.2.9/src/redis-trib.rb /usr/local/redisCluster/redisBase/bin/
注意:不允许有空格
/usr/local/redisCluster/redisBase/bin/redis-trib.rb 创建--replicas 1 10.200.157.126:8001 10.200.157.126:8002 10.200.157.126:8003 10.200.157.126:8004 10.200752157.20.6:10.200.157.126:8003 :8006
解释:
create:这表示我们要创建一个新的集群
--replicas 1:表示比例,即主节点数/从节点比例
1:代表1/1u003d1 注1 Master 1Slave 假设20个Redis节点代表集群中有10个主从节点Master下面有1个Slave
0.5:代表1/2 注1 Master 2Slave 假设15个Redis节点代表集群中有5个主从节点,每个节点在Master以下有2个Slave
集群按顺序创建。比如1,上面的例子是前3个Master,后三个是Slave,对应前面的一一对应
搭建成功,记得测试!
! zoz100077](https://programming.vip/images/doc/b442d126bc36abb772fd5f6c68c61d88.jpg)
8:Redis集群关联(redis官方cli工具搭建)
如果 Redis 是 5.0 以上版本,构建 Redis 集群会容易很多。我们可以直接使用 Redis cli 快速搭建集群;
注:redis5 0 使用上述方法 redis trib rb
**[root@MiWiFi-IR1200G-srv redisCluster]# cd /usr/local/redisCluster/redisBase/bin/
[root@MiWiFi-IR1200G-srv bin]# ./redis-cli --cluster create --cluster-replicas 1 192.168.31.51:8001 192.168.31.51:8002 192.168.31.51:8003 192.168.31.51:8004 192.168 .31.51:8005 192.168.31.51:8006**
基本参数介绍:
--集群
指定用于创建集群的环境
** --集群副本**
用于指定主节点上的从节点数量。 1代表1主1从,2代表1主2从;
注意:主机数量必须大于等于三。设置2个slave意味着至少准备9个节点,3个1master和2个slave
-a
如果有密码,使用这个设置(前提是一样的)
{IP}:{端口}...
代表哪些簇组成一个簇
我们也可以使用:/redis cli --cluster check 127.0.0.1:8001 查看集群状态
9:Redis集群基本连接和节点下线
这里我们使用官方的redis cli连接集群,但是注意一定要加-c参数,表示我们连接在一个集群中。这里我用8001测试一下
#连接8001主节点端口(Slave节点Slave不能写,所以测试未连接)
[root@MiWiFi-IR1200G-srv bin]# ./redis-cli -c -h 127.0.0.1 -p 8001
127.0.0.1:8001> 设置名称张三
-> 重定向到位于 192.168.31.51:8002 的插槽 [5798]
好的
[↑↑此时计算出来的name属于5798槽点,所以在8002时自动切换到8002节点保存]
192.168.31.51:8002> 设置年龄 22
-> 重定向到位于 192.168.31.51:8001 的插槽 [741]
好的
[↑↑此时计算age属于741槽点,所以在8001自动切换到8001节点保存]
192.168.31.51:8001> 键 *
- “年龄”
[↑↑此时在8001槽位,所以只能查询8001槽位下的所有数据]
192.168.31.51:8001> 设置高度 180
-> 重定向到位于 192.168.31.51:8002 的插槽 [8223]
好的
[↑↑此时计算高度属于8223槽点,所以在8002中自动切换到8002节点保存]
192.168.31.51:8002> 键 *
1)“高度”
- “名称”
[↑↑此时在8001槽位,所以只能查询8001槽位下的所有数据]
192.168.31.51:8002> 获取年龄
-> 重定向到位于 192.168.31.51:8001 的插槽 [741]
“22”
[↑↑计算年龄关键在8001以下,所以跳转到过去的值]
192.168.31.51:8001> 获取名称
-> 重定向到位于 192.168.31.51:8002 的插槽 [5798]
"张三"
[↑↑计算年龄关键在8002以下,所以跳转到过去的值]
192.168.31.51:8002>
[↑↑ [8002节点下]
测试8001的Master节点宕机
在这种情况下,我们的集群由三个主节点[8001~8003]和三个从节点[8004~8006]组成;这时候,我关闭了8001,所以8004是主机从上面的机会
**1:使用 kill 强行杀死一个 8001 节点 RedisCluster
2:使用 redis-trib.rb 来查看当前集群的状态(注意:必须连接在线的主从节点)**
[root@MiWiFi-IR1200G-srv bin]# /usr/local/redisCluster/redisBase/bin/redis-trib.rb 检查127.0.0.1:8006
执行集群检查(使用节点 127.0.0.1:8006)
S: 9b868e59ccf602258d079339aa51d7335d637e8d 127.0.0.1:8006
插槽:(0 个插槽)从属
复制 0a8967caa61cc159a99d409ebe61a73c7ade16cf
S: 2293234155950a91541f1a3a64884a89fce6c469 192.168.31.51:8005
插槽:(0 个插槽)从属
复制 51ede3997f64d139fb66810df132c67fc1fffe2f
M: 51ede3997f64d139fb66810df132c67fc1fffe2f 192.168.31.51:8002
插槽:5461-10922(5462 个插槽)主控
1 个额外的副本
M: 0a8967caa61cc159a99d409ebe61a73c7ade16cf 192.168.31.51:8003
插槽:10923-16383(5461 个插槽)主控
1 个额外的副本
**M: e7f4ae2d2a7f7c48b37b4273de572405caec9f91 192.168.31.51:8004
插槽:0-5460(5461 个插槽)主控
0 个额外的副本**
[OK] 所有节点都同意插槽配置。
检查空位...
检查插槽覆盖率...
[OK] 覆盖所有 16384 个插槽。
**initial S代表Slave M代表Master 8001 下线后发现8004主动承担了master节点的责任
注意:如果没有 redis-trib.rb 可以使用 redis-cli 程序连接查看状态
/usr/local/redisCluster/redisBase/bin/redis-cli -c -h 127.0.0.1 -p 8006
127.0.0.1:8006>集群节点**
测试8001的主节点是否在线
1:使用8001配置文件启动8001节点
[root@MiWiFi-IR1200G-srv bin]# cd /usr/local/redisCluster/redisBase/bin/
[root@MiWiFi-IR1200G-srv bin]# **./redis-server /usr/local/redisCluster/redis8001/etc/redisNodes_8001.conf
2:查看集群状态**
[root@MiWiFi-IR1200G-srv bin]# /usr/local/redisCluster/redisBase/bin/redis-trib.rb 检查127.0.0.1:8006
执行集群检查(使用节点 127.0.0.1:8006)
S: 9b868e59ccf602258d079339aa51d7335d637e8d 127.0.0.1:8006
插槽:(0 个插槽)从属
复制 0a8967caa61cc159a99d409ebe61a73c7ade16cf
S: 2293234155950a91541f1a3a64884a89fce6c469 192.168.31.51:8005
插槽:(0 个插槽)从属
复制 51ede3997f64d139fb66810df132c67fc1fffe2f
M: 51ede3997f64d139fb66810df132c67fc1fffe2f 192.168.31.51:8002
插槽:5461-10922(5462 个插槽)主控
1 个额外的副本
M: 0a8967caa61cc159a99d409ebe61a73c7ade16cf 192.168.31.51:8003
插槽:10923-16383(5461 个插槽)主控
1 个额外的副本
**S: 3b5a75e7f60745a59864aa4600e454be49b5d240 192.168.31.51:8001
插槽:(0 个插槽)从属
复制 e7f4ae2d2a7f7c48b37b4273de572405caec9f91**
男:e7f4ae2d2a7f7c48b37b4273de572405caec9f91 192.168.31.51:8004
插槽:0-5460(5461 个插槽)主控
1 个额外的副本
[OK] 所有节点都同意插槽配置。
检查空位...
检查插槽覆盖率...
[OK] 覆盖所有 16384 个插槽。
此时8001节点上线只能做slave,因为之前8004节点谋权篡位,8004节点下线后8001才会成为master节点
测试8004主节点和8001从节点都down了
通过 ps -ef | 查看进程grep redis 并使用 kill 关闭 8001 和 8004 节点。此时,按照默认配置,集群无法正常使用。此时只有人可以参与并启动下机;或者把宕机的slot转移到其他好的primary节点上,这样集群就会有两个primary节点;

这就是为什么我们需要重启8001和8004。为了方便,我直接将所有Redis进程杀掉,重新执行脚本
# 杀死所有 Redis 进程
杀死 -9 `ps -ef | grep redis | grep -v grep | awk '{print $2}'`
# 启动脚本启动所有Redis(包括)
/usr/local/redisCluster/RedisClusterStart.sh
下面开始介绍两种操作集群的方式:redis trib(3.0>u003dredis<5.0)和redis cli(redis>u003d5.0);推荐使用 Redis cli
老版本使用redis trib,新版本使用redis cli(推荐)
10:添加主节点到集群(redis trib模式)
可以看到我之前一直在启动8007~8010这四台机器,为后续的扩容做准备。这时候我将8007加入集群并设置Master节点;我们可以通过redis trib的add node指令来添加节点
# 使用redis trib add of RB-node 指令
redis-trib.rb add-node {待添加到集群IP:port} {集群中任何节点已经存在IP:port}
[root@localhost redisCluster]# cd /usr/local/redisCluster/redisBase/bin/
[root@localhost bin]# ./redis-trib.rb add-node 10.200.157.141:8007 10.200.157.141:8001
此时我们已经将master节点添加到集群中,8007 Master是一个(slots: (0 slots) master);所以如果要使用,必须先分配slots,
**从 8001~8003 给 8007 任何部分;分配使用 redis-trib.rb 的 reshard 命令重新分片;
注意:这个IP可以连接任何端口,只要能进入集群
[root@localhost bin]# ./redis-trib.rb reshard 10.200.157.141:8005**
您要移动多少个插槽(从 1 到 16384)?第4096章
**(提示我们要移动多少槽(从1到16384);我们可以平均分配16384/4u003d4096所以我们将填写4096。如果还有小数,我们将取一个整数)
(建议分布尽量均匀。如果相差太大,可能会出问题(相差几十个就可以了)。这是我的一点小建议,如果有问题,总是麻烦)**
接收节点 ID 是什么? d9859d6acf261106cd1c8d5d7ce47c0425250dff [[回车]
(提示我们将这 4096 个插槽点分配给那个 MasterID)
请输入所有源节点 ID。
键入“all”以将所有节点用作哈希槽的源节点。
输入所有源节点 ID 后,输入“完成”。
源节点 #1:所有 [Enter]
**(提醒我们 redis-trib.rb 你会被问到re shard的源节点(source node),也就是说4096个hash slot应该从哪个节点中取出并移动
到节点8007。如果我们不打算从特定节点取出指定数量的hash slot,我们可以redis-trib input all,这样的话集群中的所有primary节点
会成为源节点,redis-trib.rb从每个源节点中取出一部分hash槽,加起来就是4096,然后移动到7006节点)**
是否要继续提议的重新分片计划(是/否)?是 [[回车]
** (是否要继续提议的重新分片计划
**
11:添加主节点到集群(redis cli方式)
这里需要添加一个8007Node。默认添加为主节点 Master
[root@MiWiFi-IR1200G-srv bin]# ./redis-cli --cluster add-node 192.168.31.51:8007 192.168.31.51:8002
add-node {待添加IP}:{待添加端口} {已经存在IP}:{端口已经存在}
将槽分配给 8007[平均分配]
[root@MiWiFi-IR1200G-srv bin]# ./redis-cli --cluster rebalance --cluster-threshold 1 --cluster-use-empty-masters 192.168.31.51:8007
分配[手动分配]
./redis-cli --cluster reshard --cluster-from all --cluster-to {需要分配槽点ID} --cluster-slots {分配槽点} --cluster-yes 127.0.0.1: 8001
12:将slave节点加入集群(redis trib方式)
添加一个8008节点作为8007主节点的从节点
与添加主节点相同,但带--slave表示添加从节点;
**注意:但是没有指定在哪个主节点下添加,只配置了10个节点。200.157.141:8001 加入集群
此时redis-trib.rb 8008从节点会被添加到从节点较少的主节点Master上(这里明显添加到8007)Master(上)**
[root@localhost bin]# cd /usr/local/redisCluster/redisBase/bin/
[root@localhost bin]# **./redis-trib.rb add-node --slave 10.200.157.141:8008 10.200.157.141:8001
**
**但是话又说回来,我不想 redis-trib 将一个从节点分配给任何一个主节点,我需要手动将它分配给主节点 Master 下,
这里,我将8009个未分配到集群的节点分配给8003个master节点
还有--master-id 表示指定的master节点节点id
[root@localhost bin]# cd /usr/local/redisCluster/redisBase/bin/
[root@localhost bin]# ./redis-trib.rb add-node --slave --master-id aec1bb289da5fed2159ccb3217d2aec03ba47709 10.200.157.141:8009 10.200.157.141:8002
**
13:将slave节点加入集群(redis cli方式)
这里,我将8008添加到节点8007(8007是我们刚刚添加的主节点)
[root@MiWiFi-IR1200G-srv bin]# **./redis-cli --cluster add-node --cluster-slave --cluster-master-id a669b1cb86c103eb08e527fc6ff6a489f7fb2904 192.168.31.51:8009 192.168.31.51:8003
** ** --cluster-slave:加入从节点
--cluster-master-id:设置以后连接谁为主节点;在此处设置 ID**
14:从集群中移除一个主节点(redis trib模式)
我现在的需求是移除8007主节点,但是在移除主节点之前,我们必须先移除8007主节点中所有要移除的槽,也就是重新分区
这里,我将把8007中的所有槽移到8003主节点上
有 del-node 指令代表删除节点; d9859d6acf261106cd1c8d5d7ce47c0425250dff 表示移除的8007节点ID
**[root@localhost bin]# cd /usr/local/redisCluster/redisBase/bin/
[root@localhost bin]# ./redis-trib.rb del-node 10.200.157.141:8002 d9859d6acf261106cd1c8d5d7ce47c0425250dff
>>> 从集群 10.200.157.141:8002 中删除节点 d9859d6acf261106cd1c8d5d7ce47c0425250dff
[ERR] 节点 10.200.157.141:8007 不为空!重新分片数据,然后重试。
[报告错误>>> 从集群 10.200.157.141:8002 删除节点从 d9859d6acf261106cd1c8d5d7ce47c0425250dff]
[report errors[ERR] Node 10.200.157.141:8007 不为空(即节点8007有槽)!重新切片数据并重试。]**
#重新分区注意:任何IP和端口都可以连接,只要能进入集群即可
[root@localhost bin]# ./redis-trib.rb 重新分片 10.200.157.141:8002
您要移动多少个插槽(从 1 到 16384)? 4096
(我将在这里移动 4096 个插槽)
接收节点 ID 是什么? aec1bb289da5fed2159ccb3217d2aec03ba47709
(将4096槽点移到谁的主节点,这里我移到8003主节点)
请输入所有源节点 ID。
键入“all”以将所有节点用作哈希槽的源节点。
输入所有源节点 ID 后,输入“完成”。
源节点#1:d9859d6acf261106cd1c8d5d7ce47c0425250dff
源节点 #2:完成
**(就是我要从哪个主节点ID去分配这4096个槽点,如果全部设置的话,平均会抽出一点槽)
(但我明确指出,我们应该将槽从8007节点移动到8003节点;;完成(结束设置)**
是否要继续提议的重新分片计划(是/否)?是 [[回车]
! swz 100101 swz 100102 swz 100100
15:从集群中移除一个主/从节点(redis cli方式)
删除节点的逻辑同上一节
1:对当前集群进行重新分区,将主机上所有要删除的槽移到其他主节点上
** ./redis-cli --cluster reshard** {集群中的任何IP}:{集群中的任何端口}
u003du003d>参考上面和详细说明./redis-trib.rb reshard 10.200.157.141:8002 同样
2:删除节点(此处删除主节点的命令与从节点相同)
** ./redis-cli --cluster del-node {Any in the cluster IP}:{Any port in the cluster} {待删除ID}**
16:从集群中移除一个从节点(redis trib模式)
现在想去掉8009从节点,因为是从节点,没有slot,所以直接去掉就可以了
[root@localhost bin]# ./redis-trib.rb del-node 10.200.157.141:8002 7aab013e8257fce39bdcd36cad9320cd4265ef21
从集群 10.200.157.141:8002 中删除节点 7aab013e8257fce39bdcd36cad9320cd4265ef21
向集群发送 CLUSTER FORGET 消息...
关闭节点。
.
更多推荐

**


**
**
**
所有评论(0)