发布时间:2025-11-04 12:51:28 来源:技术快报 作者:应用开发
为什么要有集群
单个Redis存在不稳定性,工程当Redis服务宕机或硬盘故障,师培系统崩溃之后,集群就没有可用的种都掌服务了,还会造成数据的工程丢失
单个Redis的读写能力也是有限的
还由于互联网的三高架构,高并发,师培高性能,集群高可用
| 概念
通过添加服务器的种都掌数量,提供相同的工程服务,从而让服务器达到一个稳定,师培高效的集群状态
| 三种模式
主从模式
哨兵模式
Cluster模式
主从模式介绍

| 为什么要用主从复制
单机redis的风险与问题
问题一:机器故障
①硬盘故障,系统崩溃
②本质:数据丢失,种都掌可能对业务造成灾难性打击
问题二:容量瓶颈
①内存不足,工程一台redis内存是师培有限的
解决方案:
为了避免单点Redis服务器故障,准备多台服务器,集群互相联通,将数据复制多个副本保存在不同服务器上,连接在一起,并保证数据是同步的,即使有其中一台服务器宕机,云服务器其他服务器依然可以继续提供服务,实现Redis的高可用,同时实现数据冗余备份
| 工作原理

如上图所示,是Redis的工作原理,其对应的文字说明如下:
①replica库通过"SLAVEOF 172.200.1.201 6379"命令连接master库并发送"SYNC"给master
②master库收到"SYNC",会立即触发"BGSAVE"后台保存RDB快照,并将RDB快照发送给replica库;
③replica库接收后会应用RDB快照;
④master库会陆续将中间产生的新的操作保存并发送给replica库;
⑤到此我们master复制集就正常工作了;
⑥再此以后,master库只要发生新的操作,都会以命令传播的形式自动发送给replica库;
⑦所有复制相关信息,从info信息中都可以查到,即使重启任何节点,他的master-replica关系依然都在;
⑧如果发生master-replica关系断开时,replica库数据没有任何损坏,在下次重连之后,replica库发送"PSYNC
⑨master库只会将replica库缺失部分的数据同步给replica库应用,达到快速恢复master-replica架构的目的;
温馨提示:(可能面试时会问到):
1、在Redis 2.8版本之前,如果master-replica架构中replica库宕机将会再次触发"SYNC",从而全量拷贝主库的数据,这样效率明显很低
于是在Redis 2.8版本之后就新增了"PSYNC"指令以实现可以理解为"断点续传"的高防服务器功能
2、生产环境中,建议开启master库持久化功能,避免因主库意外重启而导致缓存丢失
举个例子,master库右1w条数据,replica库在某一时刻仅有9k数据,还有1k数据未来得及同步master库时,master库意外重启导致KEY为0,此时replica库同步master库数据会将replica库已有的9k缓存数据删除以达到和master库同步的目的
哨兵模式介绍

哨兵(sentinel)是一个分布式系统,用于对主从结构中的每台服务器进行监控,当出现故障时通过投票机制选择新的master并将所有slave连接到新的master
| 为什么有哨兵
主机宕机,如何能够高可用的恢复正常,不用人为进行干预
作用:
监控:不断地检查master和slave是否正常运行;master存活检测,master与slave运行清空检测
通知(提醒):当被监控地服务器出现问题时,向其他(哨兵、客户端)发送通知
自动故障转移:断开master与slave连接,选取一个slave作为master,将其他slave连接到新地master,并告知客户端新地服务器地址
注意:
哨兵也是一台redis服务器,只是不提供数据服务
通常哨兵配置数量为单数
Cluster模式介绍
redis最开始使用主从模式做集群,若master宕机需要手动配置slave转为master
后来为了高可用提出来哨兵模式,该模式下有一个哨兵监视master和slave,亿华云计算若master宕机可自动将slave转为master,但它也有一个问题,就是不能动态扩充,哨兵模式还是只有一个master
所以在3.x提出cluster集群模式
| 工作原理

Redis数据分片原理说明:
①redis会有多组分片构成,本篇笔记实验环境是3组;
②redis cluster使用固定个数的slot存储数据,一共16384是slot;
③每组分片分得1/3 slot个数,分别为"0-5460,5461-10921,10922-16383"
④基于CRC16(key) % 16384公式会得到一个"槽位号"(该编号范围在"0-16383"之间);
⑤根据计算得出的槽位值,找到相对应的分片节点的主节点,存储到相应槽位上;
⑥如果客户端当时连接的节点不是将来要存储的分片节点,分片集群会将客户端连接切换至真正存储节点进行数据存储;
综上所述,我们来举个例子,在Redis分布式集群中,假设我们执行了"SET name oldboy"这一条指令,那么数据该如何存储的呢?其大致的存储逻辑如下:
①使用"CRC16(KEY_NAME)"进行校验计算一个值,假设"CRC16(name)"的计算结果为"1234567890";
②再使用"CRC16(KEY_NAME)%16384"进行计算,从而得出该KEY_NAME被分配到哪个slot上,假设结果为"1234567890%16384=722",就表示数据被落到slot=722的分片上;
③而slot=722恰好在第一个分片上,因为我们第一个分片的slot范围就是"0-5460"
主从模式部署
| 为各个Redis实例创建数据和配置文件目
# 创建Redis的数据存储目录 mkdir -pv /oldboyedu/data/redis1637{0..2} # 创建Redis的配置文件存储目录 mkdir -pv /oldboyedu/softwares/redis1637{0..2}| 为各个Redis实例创建配置文件
1)为"redis16370"实例创建配置文件
# cat > /oldboyedu/softwares/redis16370/redis.conf <<EOF port 16370 daemonize yes pidfile /oldboyedu/data/redis16370/redis.pid loglevel notice logfile /oldboyedu/data/redis16370/redis.log dbfilename dump.rdb dir /oldboyedu/data/redis16370 bind 172.200.1.201 127.0.0.1 requirepass oldboyedu masterauth oldboyedu # 配置RDB持久化策略 save 900 1 save 300 10 save 60 10000 # 配置AOF持久化 appendonly yes appendfsync everysec EOF2)为"redis16371"实例创建配置文件
# cat > /oldboyedu/softwares/redis16371/redis.conf <<EOF port 16371 daemonize yes pidfile /oldboyedu/data/redis16371/redis.pid loglevel notice logfile /oldboyedu/data/redis16371/redis.log dbfilename dump.rdb dir /oldboyedu/data/redis16371 bind 10.0.0.112 127.0.0.1 requirepass oldboyedu masterauth oldboyedu # 配置RDB持久化策略 save 900 1 save 300 10 save 60 10000 # 配置AOF持久化 appendonly yes appendfsync everysec EOF3)为"redis16372"实例创建配置文件
cat > /oldboyedu/softwares/redis16372/redis.conf <<EOF port 16372 daemonize yes pidfile /oldboyedu/data/redis16372/redis.pid loglevel notice logfile /oldboyedu/data/redis16372/redis.log dbfilename dump.rdb dir /oldboyedu/data/redis16372 bind 10.0.0.112 127.0.0.1 requirepass oldboyedu masterauth oldboyedu # 配置RDB持久化策略 save 900 1 save 300 10 save 60 10000 # 配置AOF持久化 appendonly yes appendfsync everysec EOF温馨提示:
所有的requirepass建议设置为一致,这为我们"哨兵模式"做准备,很明显,"requirepass"表示配置当前实例的验证口令;
注意"masterauth"表示的含义是主库的验证口令;下面的模板你可以根据自己业务的实际需求进行改动即可
cat > /oldboyedu/softwares/redis16372/redis.conf <<EOF port 16372 daemonize yes pidfile /oldboyedu/data/redis16372/redis.pid loglevel notice logfile /oldboyedu/data/redis16372/redis.log dbfilename dump.rdb dir /oldboyedu/data/redis16372 bind 10.0.0.112 127.0.0.1 requirepass oldboyedu masterauth oldboyedu # 配置RDB持久化策略 save 900 1 save 300 10 save 60 10000 # 配置AOF持久化 appendonly yes appendfsync everysec EOF| 启动各个Redis实例
1)启动各个Redis实例
redis-server /oldboyedu/softwares/redis16370/redis.conf redis-server /oldboyedu/softwares/redis16371/redis.conf redis-server /oldboyedu/softwares/redis16372/redis.conf # 执行 ss -lnt 查看是否启动 ss -lnt
2)停止各个Redis实例运行,此步骤可跳过,因为我们暂时还不需要停止Redis,我们要用Redis实例做主从架构
redis-cli -p 16370 -a oldboyedu shutdown redis-cli -p 16371 -a oldboyedu shutdown redis-cli -p 16372 -a oldboyedu shutdown| 开启Redis的主从
实验说明:以 redis16370 实例为主库,以 redis16371 实例和 redis16372 实例为从库
# 从库实例开启主从 redis-cli -p 16371 -a oldboyedu SLAVEOF 10.0.0.112 16370 redis-cli -p 16372 -a oldboyedu SLAVEOF 10.0.0.112 16370| 主库实例查看主从信息
redis-cli -p 16370 -a oldboyedu INFO REPLICATION| 从库实例查看主从信息
在 "redis16371" 实例中查看主从状态信息:
信息
redis-cli -p 16371 -a oldboyedu INFO REPLICATION
在 "redis16372" 实例中查看主从状态信息:
redis-cli -p 16372 -a oldboyedu INFO REPLICATION
| 验证主从配置是否生效
在"redis16370"实例主库的11号数据库创建测试数据
# redis-cli -p 16370 -a oldboyedu -n 11 16370[11]> KEYS * (empty array) 16370[11]> SET name oldboyedu OK 16370[11]> SET age 18 OK 16370[11]> KEYS * 1) "name" 2) "age" 16370[11]> QUIT在"redis16371"实例从库的11号数据库查看是否同步主库的11号数据库
# redis-cli -p 16371 -a oldboyedu -n 11 16371[11]> KEYS * 1) "name" 2) "age" 16371[11]> GET name "oldboyedu" 16371[11]> GET age "18" 16371[11]> QUIT在"redis16372"实例从库的11号数据库查看是否同步主库的11号数据库
# redis-cli -p 16372 -a oldboyedu -n 11 16371[11]> KEYS * 1) "name" 2) "age" 16371[11]> GET name "oldboyedu" 16371[11]> GET age "18" 16371[11]> QUIT| 解除"redis16372"实例的主从关系
redis-cli -p 16372 -a oldboyedu SLAVEOF NO ONE
| 跨节点部署Redis集群实战案例
(0)主从架构设计 主库为: 10.0.0.108 从库: 10.0.0.106 10.0.0.107 (1)10.0.0.106的配置 install -d /oldboyedu/data/redis cat > /oldboyedu/softwares/redis/conf/redis.conf <<EOF port 8106 daemonize yes pidfile /oldboyedu/data/redis/redis.pid loglevel notice logfile /oldboyedu/data/redis/redis.log dbfilename oldboyedu_linux.rdb dir /oldboyedu/data/redis/ bind 10.0.0.106 requirepass oldboyedu masterauth oldboyedu # 配置RDB持久化策略 save 900 1 save 300 10 save 60 10000 EOF redis-server /oldboyedu/softwares/redis/conf/redis.conf (2)10.0.0.107的配置 install -d /oldboyedu/data/redis cat > /oldboyedu/softwares/redis/conf/redis.conf <<EOF port 8107 daemonize yes pidfile /oldboyedu/data/redis/redis.pid loglevel notice logfile /oldboyedu/data/redis/redis.log dbfilename oldboyedu_linux.rdb dir /oldboyedu/data/redis/ bind 10.0.0.107 requirepass oldboyedu masterauth oldboyedu # 配置RDB持久化策略 save 900 1 save 300 10 save 60 10000 EOF redis-server /oldboyedu/softwares/redis/conf/redis.conf (3)10.0.0.108的配置 install -d /oldboyedu/data/redis cat > /oldboyedu/softwares/redis/conf/redis.conf <<EOF port 8108 daemonize yes pidfile /oldboyedu/data/redis/redis.pid loglevel notice logfile /oldboyedu/data/redis/redis.log dbfilename oldboyedu_linux.rdb dir /oldboyedu/data/redis/ bind 10.0.0.108 requirepass oldboyedu masterauth oldboyedu # 配置RDB持久化策略 save 900 1 save 300 10 save 60 10000 EOF redis-server /oldboyedu/softwares/redis/conf/redis.conf (4)从库开启主从 # 10.0.0.106: redis-cli -p 8106 -h 10.0.0.106 -a oldboyedu SLAVEOF 10.0.0.108 8108 # 10.0.0.107: redis-cli -p 8107 -h 10.0.0.107 -a oldboyedu SLAVEOF 10.0.0.108 8108