Redis 内容及相关实验
Redis 就像一个请了个「24 小时不睡觉、记忆力还超群」的数据管家:你把数据丢给它,它直接放在内存里,随取随用,快得离谱。
目录
- [Redis 简介](#Redis 简介)
- [Redis 安装部署](#Redis 安装部署)
- [Redis 主从复制](#Redis 主从复制)
- [Redis 哨兵模式 Sentinel](#Redis 哨兵模式 Sentinel)
- [Redis Cluster 集群](#Redis Cluster 集群)
- 三种高可用方案对比小结
- 总结
一、Redis 简介
1.1 Redis 是什么
Redis(Remote Dictionary Server) 是一个开源的、基于内存 的键值对(Key-Value)数据库。它把所有数据放在内存里,因此读写速度能达到 10 万+ QPS;同时通过 RDB / AOF 把数据落地到磁盘,宕机后也能恢复,所以它既快又不怕丢。
它和 MySQL 这种"把数据放硬盘、用的时候再读"的传统关系型数据库不一样:MySQL 是"仓库",规整但取货慢;Redis 是"手边的保险柜",随手就能拿。
典型使用场景:
| 场景 | 说明 |
|---|---|
| 缓存(Cache) | 把热点数据放 Redis,挡在数据库前面,扛住高并发读 |
| 数据库(DB) | 直接当主存储,配合持久化保证数据不丢 |
| 消息队列 / 发布订阅 | 用 List、Stream 做轻量队列、用 Pub/Sub 做消息广播 |
| 排行榜 / 计数器 | 用 ZSet、incr 做实时排名、访问计数 |
| 分布式锁 | 用 SET key value NX 实现跨进程互斥 |
1.2 为什么这么快
- 数据在内存:没有磁盘 IO 瓶颈;
- 单线程模型:避免了多线程上下文切换和锁竞争(6.0 后引入多线程 IO,但命令执行仍是单线程);
- IO 多路复用(epoll):一个线程就能同时hold住海量连接;
- 高效的数据结构:SDS、跳表、哈希表等底层结构都为性能量身设计。
1.3 数据类型
Redis 的 key 都是字符串,value 支持多种结构。记住"五大基础类型 + 扩展类型"就够了:
- String(字符串) :最常用,可存文本、数字、序列化对象,支持
incr自增; - List(列表):双向链表,可做队列 / 栈;
- Hash(哈希):键值对集合,适合存对象属性(如用户资料);
- Set(集合):无序去重,支持交集/并集,做共同好友、抽奖;
- ZSet(有序集合):带分数的有序集合,做排行榜神器;
- 扩展类型:Bitmaps(位图,在线状态)、HyperLogLog(UV 统计)、Geospatial(地理附近的人)、Streams(消息流)。
1.4 持久化:RDB 与 AOF
内存数据断电即失,所以 Redis 提供两种持久化方式,生产环境建议两个都开:

- RDB(快照) :定时把内存全量数据 dump 成
.rdb二进制文件。文件小、恢复快,适合备份;缺点是可能丢最后一次快照之后的数据。 - AOF(日志) :把每一条写命令追加到
.aof文件。数据更安全(可配置每秒/每次刷盘),文件大、恢复稍慢。 - 重启时 Redis 优先用 AOF 恢复(数据更全),RDB 主要用来做快速备份和主从全量同步。
二、Redis 安装部署(实验)
实验环境:3 台机器
redis-node1/2/3(IP 分别为172.25.254.10/20/30),系统已配置好主机名解析。以下以 node1 为例,其余节点同样操作。
2.1 安装依赖
bash
[root@redis-node1 ~]# dnf install make gcc initscripts -y
2.2 源码编译安装
bash
[root@redis-node1 ~]# wget https://download.redis.io/releases/redis-7.4.8.tar.gz
[root@redis-node1 ~]# tar zxf redis-7.4.8.tar.gz
[root@redis-node1 ~]# cd redis-7.4.8/
[root@redis-node1 redis-7.4.8]# make && make install
2.3 用脚本生成服务(install_server.sh)
Redis 自带 utils/install_server.sh,可以一键生成 systemd 可管理的服务。systemd 环境下脚本默认会退出,需要先把它的 systemd 检测注释掉:
bash
[root@redis-node1 redis-7.4.8]# cd utils/
[root@redis-node1 utils]# vim install_server.sh
# 把下面这段 systemd 检测注释掉(否则脚本直接 exit)
#_pid_1_exe="$(readlink -f /proc/1/exe)"
#if [ "${_pid_1_exe##*/}" = systemd ]
#then
# echo "This systems seems to use systemd."
# ...
#fi
[root@redis-node1 utils]# ./install_server.sh
交互提示一路回车用默认值,关键配置如下:
Please select the redis port for this instance: [6379]
Please select the redis config file name [/etc/redis/6379.conf] /etc/redis/redis.conf
Please select the redis log file name [/var/log/redis_6379.log]
Please select the data directory for this instance [/var/lib/redis/6379]
Please select the redis executable path [/usr/local/bin/redis-server]
...
Installation successful!
2.4 放开监听并启动
编辑配置文件,关闭保护模式、允许所有网卡监听:
bash
[root@redis-node1 utils]# vim /etc/redis/redis.conf
# 约 89 行:允许所有 IP 监听
bind * -::*
# 约 113 行:关闭保护模式(实验环境,生产请配合密码/防火墙)
protected-mode no
[root@redis-node1 utils]# systemctl daemon-reload
[root@redis-node1 utils]# systemctl start redis_6379.service
[root@redis-node1 utils]# systemctl status redis_6379.service
2.5 验证端口监听
bash
[root@redis-node1 ~]# netstat -antlpe | grep redis
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN ... redis-server
tcp 0 0 ::1:6379 :::* LISTEN ... redis-server
看到 6379 端口处于 LISTEN,说明 Redis 已经跑起来了。node2、node3 用同样的步骤安装即可。
三、Redis 主从复制
3.1为什么需要主从复制
单节点 Redis 有两个痛点:单点故障 (挂了就全完)和读压力集中。主从复制让一个 Master 把数据同步给多个 Slave:
- 读写分离:Master 负责写,Slave 负责读,分摊压力;
- 数据冗余:Slave 是 Master 的备份;
- 复制方式:首次是全量复制(RDB 快照),之后是增量复制(命令流)。
注意:默认 Slave 是只读的,不能在从节点上写数据。
3.2 实验:搭建一主两从
① 配置主节点(node1)
bash
[root@redis-node1 ~]# vim /etc/redis/redis.conf
#bind 127.0.0.1 -::1
bind * -::*
protected-mode no
[root@redis-node1 ~]# systemctl restart redis_6379.service
② 配置两个从节点(node2、node3)
bash
# 在 redis-node2 节点
[root@redis-node2 ~]# vim /etc/redis/redis.conf
#bind 127.0.0.1 -::1
bind * -::*
protected-mode no
replicaof 172.25.254.10 6379 # 指向主节点 IP + 端口
[root@redis-node2 ~]# systemctl restart redis_6379.service
# 在 redis-node3 节点
[root@redis-node3 ~]# vim /etc/redis/redis.conf
#bind 127.0.0.1 -::1
bind * -::*
protected-mode no
replicaof 172.25.254.10 6379
[root@redis-node3 ~]# systemctl restart redis_6379.service
3.3 验证复制状态
主节点查看(node1)
bash
[root@redis-node1 ~]# redis-cli
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.25.254.20,port=6379,state=online,offset=391,lag=0
slave1:ip=172.25.254.30,port=6379,state=online,offset=391,lag=1
master_replid:e5f5cddc017ab0d5223213592d0482b832d3af77
master_repl_offset:391
看到 role:master 且 connected_slaves:2,两个 slave 都是 online,说明主从建立成功。
从节点查看(node2)
bash
[root@redis-node2 ~]# redis-cli
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:172.25.254.10
master_port:6379
master_link_status:up # 与主节点连接正常
slave_read_only:1 # 从节点只读
3.4 测试数据同步 & 从节点只读
在主节点写数据,从节点立刻能读到:
bash
# 主节点 node1 写入
[root@redis-node1 ~]# redis-cli
127.0.0.1:6379> set name lee
OK
127.0.0.1:6379> get name
"lee"
# 从节点 node2 / node3 读取
[root@redis-node2 ~]# redis-cli
127.0.0.1:6379> get name
"lee"
尝试在从节点写入,会被拒绝:
bash
[root@redis-node3 ~]# redis-cli
127.0.0.1:6379> get name
"lee"
127.0.0.1:6379> set test 123
(error) READONLY You can't write against a read only replica.
✅ 主从复制 + 读写分离验证通过。
四、Redis 哨兵模式 Sentinel
4.1主从的短板靠哨兵补
主从复制解决了"读压力"和"数据备份",但 Master 挂了没人自动顶上 。哨兵(Sentinel)就是来干这活的------一组哨兵进程专门盯着 Master,发现它真挂了,自动把一个 Slave 提升为新 Master,并让其他节点改认新主。
几个关键概念:
- 监控(Monitoring):哨兵持续 ping 主从节点;
- 主观下线(sdown):某个哨兵自己觉得节点连不上了;
- 客观下线(odown) :达到
quorum个哨兵都认为下线,才确认真挂了; - 故障转移(failover):选举领头哨兵 → 选一个 Slave 提升 → 通知其余节点;
- quorum :认定主节点下线的票数(实验中设为 2,即至少 2 个哨兵同意)。

4.2 实验:搭建哨兵
① 主节点复制并编辑哨兵配置
bash
[root@redis-node1 ~]# cd redis-7.4.8/
[root@redis-node1 redis-7.4.8]# cp -p sentinel.conf /etc/redis/
[root@redis-node1 ~]# vim /etc/redis/sentinel.conf
protected-mode no # 关闭保护模式
port 26379 # 哨兵监听端口
daemonize no # 前台运行(方便看日志)
pidfile /var/run/redis-sentinel.pid
loglevel notice
sentinel monitor mymaster 172.25.254.10 6379 2 # 监控 mymaster,quorum=2
sentinel down-after-milliseconds mymaster 10000 # 10 秒连不上视为下线
sentinel parallel-syncs mymaster 1 # 故障转移后同时同步新主的 slave 数
sentinel failover-timeout mymaster 180000 # 故障切换超时 3 分钟
⚠️ 原参考文档此处写的是
172.25.254.100,应为实际 master 的172.25.254.10,本文已修正,否则哨兵会监控一个不存在的地址。
② 从节点也关闭保护模式
bash
[root@redis-node2 ~]# vim /etc/redis/redis.conf
protected-mode no
[root@redis-node2 ~]# systemctl restart redis_6379.service
[root@redis-node3 ~]# vim /etc/redis/redis.conf
protected-mode no
[root@redis-node3 ~]# systemctl restart redis_6379.service
③ 把哨兵配置发给两个从节点,三台一起启动
bash
[root@redis-node1 ~]# scp /etc/redis/sentinel.conf root@172.25.254.20:/etc/redis/
[root@redis-node1 ~]# scp /etc/redis/sentinel.conf root@172.25.254.30:/etc/redis/
# 三台节点都执行:
[root@redis-node1 ~]# redis-sentinel /etc/redis/sentinel.conf
启动后日志里能看到哨兵发现了 master 和两个 slave,以及彼此:
bash
# +monitor master mymaster 172.25.254.10 6379 quorum 2
* +slave slave 172.25.254.20:6379 ... @ mymaster 172.25.254.10 6379
* +slave slave 172.25.254.30:6379 ... @ mymaster 172.25.254.10 6379
* +sentinel sentinel 28f2f3da... 172.25.254.20 26379 @ mymaster ...
* +sentinel sentinel 89568283... 172.25.254.30 26379 @ mymaster ...
4.3 实验:测试故障切换
① 干掉主节点
bash
[root@redis-node1 ~]# redis-cli
127.0.0.1:6379> SHUTDOWN
not connected>
② 观察哨兵日志(故障转移过程)
bash
# +sdown master mymaster 172.25.254.10 6379 # 主观下线
# +odown master mymaster 172.25.254.10 6379 #quorum 2/2 # 客观下线
# +try-failover master mymaster ...
# +vote-for-leader d0780e7f... 1 # 投票选领头哨兵
# +selected-slave slave 172.25.254.20:6379 ... # 选中 .20 提升
# +promoted-slave slave 172.25.254.20:6379 ... # 提升为 master
# +failover-end master mymaster 172.25.254.10 6379
# +switch-master mymaster 172.25.254.10 6379 172.25.254.20 6379 # 主切换到 .20
③ 在 node3 上确认已认新主
bash
[root@redis-node3 ~]# redis-cli
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:172.25.254.20 # 已经指向新主 .20
master_port:6379
master_link_status:up
④ 恢复原主节点(node1)
bash
[root@redis-node1 ~]# /etc/init.d/redis_6379 start
原主重启后变成新主的从节点,在 node2 上能看到:
bash
[root@redis-node2 ~]# redis-cli
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.25.254.30,port=6379,state=online,...
slave1:ip=172.25.254.10,port=6379,state=online,... # 原主 .10 已成为从
✅ 哨兵自动故障转移验证通过。
五、Redis Cluster 集群
5.1 理论:集群解决了什么
哨兵解决了"主挂了自动切换",但它只有一个 Master 写 ,写能力和存储容量都有上限。Redis Cluster 是分布式方案:
- 数据分片 :把数据按
slot = CRC16(key) % 16384分到 16384 个哈希槽,槽平均分配到多个 Master; - 无中心化 :客户端连任意节点,节点算槽后命中自己就处理,否则返回
MOVED重定向; - 内置高可用 :每个 Master 配 Slave,Master 宕机其 Slave 自动接管槽,不需要哨兵;
- 在线扩缩容:槽可以在节点间迁移,集群不中断。
5.2 实验环境
6 台机器:172.25.254.10 ~ 60,其中 .10/.20/.30 为 Master,.40/.50/.60 为对应 Slave。
5.3 配置集群节点
6 台节点都执行以下配置(先设主从认证、开启 cluster):
bash
[root@redis-node1 ~]# vim /etc/redis/6379.conf
masterauth "123456" # 集群主从认证密码
cluster-enabled yes # 开启 cluster 功能
cluster-config-file nodes-6379.conf # 集群配置文件
cluster-node-timeout 15000 # 节点超时(ms)
[root@redis-node1 ~]# /etc/init.d/redis_6379 stop
[root@redis-node1 ~]# /etc/init.d/redis_6379 start
# 首次搭建先清掉旧数据(已有数据时必须)
[root@redis-node1 ~]# redis-cli
127.0.0.1:6379> flushall
127.0.0.1:6379> CLUSTER RESET HARD
5.4 创建集群
一条命令拉起 3 主 3 从(--cluster-replicas 1 表示每个 Master 配 1 个 Slave):
bash
[root@redis-node1 ~]# redis-cli --cluster create \
172.25.254.10:6379 172.25.254.20:6379 172.25.254.30:6379 \
172.25.254.40:6379 172.25.254.50:6379 172.25.254.60:6379 \
--cluster-replicas 1
输出关键片段(自动分配槽位和主从):
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.25.254.50:6379 to 172.25.254.10:6379
Adding replica 172.25.254.60:6379 to 172.25.254.20:6379
Adding replica 172.25.254.40:6379 to 172.25.254.30:6379
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
[OK] All nodes agree about slots configuration.
5.5 验证集群状态
bash
# 集群信息总览
[root@redis-node1 ~]# redis-cli --cluster info 172.25.254.10:6379
172.25.254.10:6379 -> 0 keys | 5461 slots | 1 slaves.
172.25.254.30:6379 -> 0 keys | 5461 slots | 1 slaves.
172.25.254.20:6379 -> 0 keys | 5462 slots | 1 slaves.
[OK] 0 keys in 3 masters.
# 集群自身状态
[root@redis-node1 ~]# redis-cli cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_known_nodes:6
cluster_size:3
# 健康检查
[root@redis-node1 ~]# redis-cli --cluster check 172.25.254.10:6379
[OK] All 16384 slots covered.
cluster_state:ok 且 All 16384 slots covered 说明集群健康。拓扑如下:

5.6集群扩容(加一主一从)
业务增长要加机器,集群支持在线扩容。
① 加入新主节点 .70
bash
[root@redis-node1 ~]# redis-cli --cluster add-node 172.25.254.70:6379 172.25.254.10:6379
[root@redis-node1 ~]# redis-cli --cluster check 172.25.254.10:6379
172.25.254.70:6379 -> 0 keys | 0 slots | 0 slaves. # 新主还没槽
② 迁移槽给新主(reshard 4096 个)
bash
[root@redis-node1 ~]# redis-cli --cluster reshard 172.25.254.10:6379
How many slots do you want to move (from 1 to 16384)? 4096
What is the receiving node ID? dfabfe07170ac9b5d20a5a7a70c836877bd64504 # .70 的 ID
Please enter all the source node IDs.
Source node #1: all # 从所有现有 master 取槽
Source node #2: done
Ready to move 4096 slots.
迁移后 .70 分到 4096 个槽(从三个老 master 各取一部分):
M: dfabfe07170ac9b5d20a5a7a70c836877bd64504 172.25.254.70:6379
slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master
③ 给新主挂从节点 .80
bash
[root@redis-node1 ~]# redis-cli --cluster add-node 172.25.254.80:6379 172.25.254.10:6379 \
--cluster-slave --cluster-master-id dfabfe07170ac9b5d20a5a7a70c836877bd64504
扩容后变成 4 主 4 从,槽自动均摊到每主 4096 个。
5.7集群缩容(删一主一从)
① 把 .70 的槽迁回 .10
bash
[root@redis-node1 ~]# redis-cli --cluster reshard 172.25.254.10:6379
How many slots do you want to move (from 1 to 16384)? 4096
What is the receiving node ID? 8db833f3c3bc6b8f93e87111f13f56d366f833a0 # .10 的 ID
Source node #1: dfabfe07170ac9b5d20a5a7a70c836877bd64504 # .70 的 ID
Source node #2: done
② 删除节点(先删从 .80,再删主 .70)
bash
[root@redis-node1 ~]# redis-cli --cluster del-node 172.25.254.10:6379 1176ee294e6b5071ca57e93374d04ac22028daed
>>> Sending CLUSTER FORGET messages to the cluster...
[root@redis-node1 ~]# redis-cli --cluster del-node 172.25.254.10:6379 dfabfe07170ac9b5d20a5a7a70c836877bd64504
[root@redis-node1 ~]# redis-cli --cluster check 172.25.254.10:6379
[OK] All 16384 slots covered.
缩容完成,恢复为 3 主 3 从。⚠️ 删除主节点前必须先把它的槽全部迁走,否则会丢数据。
六、三种高可用方案对比小结
| 方案 | 写能力 | 存储上限 | 自动故障转移 | 是否需要哨兵 | 适用场景 |
|---|---|---|---|---|---|
| 主从复制 | 单 Master | 单节点 | ❌ 手动 | 否 | 读多写少、要备份 |
| 哨兵 Sentinel | 单 Master | 单节点 | ✅ 自动 | 是 | 高可用、写量不大 |
| Cluster 集群 | 多 Master | 横向扩展 | ✅ 自动 | 否(内置) | 大数据量、高并发写 |
七、总结
- Redis 是什么:基于内存的 KV 数据库,快、支持持久化、数据类型丰富;
- 主从复制:一主多从做读写分离和数据备份,但 Master 挂了要人手动顶;
- 哨兵模式:哨兵自动监控 + 故障转移,解决主从的"单点"问题,但仍只有一个 Master 写;
- Cluster 集群:数据分 16384 槽、多 Master 分片,既能横向扩容又能自动故障转移,是大规模场景的终极方案;
- 持久化:RDB + AOF 都开,重启优先 AOF,RDB 做备份。