摘要:Redis 是后端开发必会的技术栈之一。本文从零开始,系统梳理 Redis 的核心概念、五种数据类型、八大应用场景、RDB/AOF 持久化机制、主从复制、哨兵高可用、Cluster 集群部署以及 Docker 容器化实战,配合大量可复制的命令示例,适合初学者入门和老兵复习。


目录


一、Redis 是什么

Redis(Remote Dictionary Server)是一个开源的、基于内存的高性能 Key-Value 数据库,使用 C 语言编写,遵循 BSD 协议。

三个核心特点:

  1. 持久化:支持将内存数据保存到磁盘,重启后可重新加载
  2. 丰富的数据结构:不仅支持 String,还提供 List、Set、Zset、Hash 等
  3. 主从备份:支持 Master-Slave 模式的数据备份

二、Redis 为什么快

特性 说明
🚀 纯内存操作 数据存在内存中,微秒级响应,QPS 可达 10 万~100 万+
🧵 单线程模型 Redis 6.0 前核心网络 IO 为单线程,避免上下文切换和锁竞争
📡 IO 多路复用 基于 Linux epoll,一个线程管理多个 socket 连接
💾 高效数据结构 C 语言实现,数据结构设计简洁高效
📝 简单协议 RESP 协议解析成本极低

IO 多路复用 — 通俗理解

你去小吃街买饭:烧烤、饺子、炒菜。如果每样排队等(串行),耗时最长;三个人分别排(多线程),快但开销大;你跟每个老板说"好了叫我"(epoll),一个线程同时等三份——这就是 IO 多路复用。

Linux 上三套 API:select(轮询)→ poll(轮询升级版)→ epoll(事件通知,主流方案)。


三、五种核心数据类型

Redis 所有 Key 都是字符串,Value 支持以下五种类型:

3.1 String(字符串)

最基本类型,二进制安全,最大 512MB。

SET key value [EX seconds] [PX milliseconds] [NX|XX]
GET key
SETEX key seconds value        # 设置并指定过期时间
SETNX key value                # 仅当 key 不存在时设置(分布式锁)
INCR key / DECR key            # 原子递增 / 递减
INCRBY key increment           # 增加指定值
MSET k1 v1 k2 v2               # 批量设置
MGET k1 k2                     # 批量获取
STRLEN key                     # 字符串长度
APPEND key value               # 追加内容
GETSET key value               # 设置新值并返回旧值

SET 命令的可选参数EX(秒级过期)、PX(毫秒级过期)、NX(不存在才设)、XX(存在才设)。

# 基本操作
127.0.0.1:6379> SET name wang EX 100      # 100秒后过期
OK
127.0.0.1:6379> TTL name                   # 查看剩余时间
(integer) 95
127.0.0.1:6379> SETNX title ceo            # 仅当不存在时设置
(integer) 1
127.0.0.1:6379> SET title cto XX           # 仅当存在时覆盖
OK

3.2 List(列表)

有序可重复的字符串链表,支持左右两端操作,常用于消息队列。

LPUSH key value [value ...]     # 左侧插入
RPUSH key value [value ...]     # 右侧插入
LPOP key                        # 左侧弹出
RPOP key                        # 右侧弹出
BRPOP key timeout               # 阻塞式右侧弹出(秒)
LLEN key                        # 列表长度
LRANGE key start stop           # 按范围获取
LINDEX key index                # 按索引获取
LREM key count value            # 删除指定元素
127.0.0.1:6379> LPUSH queue "msg1" "msg2"
(integer) 2
127.0.0.1:6379> BRPOP queue 5              # 阻塞等待5秒
1) "queue"
2) "msg1"

3.3 Set(集合)

无序、不重复的字符串集合,支持交/并/差集运算。

SADD key member [member ...]    # 添加成员
SREM key member [member ...]    # 删除成员
SMEMBERS key                    # 列出所有成员
SISMEMBER key member            # 判断是否成员
SCARD key                       # 集合大小
SINTER key1 key2                # 交集
SUNION key1 key2                # 并集
SDIFF key1 key2                 # 差集
127.0.0.1:6379> SADD tags:1 "redis" "database" "nosql"
(integer) 3
127.0.0.1:6379> SADD tags:2 "redis" "cache"
(integer) 2
127.0.0.1:6379> SINTER tags:1 tags:2       # 共同标签
1) "redis"

3.4 Zset(Sorted Set,有序集合)

每个元素关联一个 Score,按 Score 自动排序。

ZADD key score member [score member ...]
ZRANGE key start stop [WITHSCORES]                        # 按索引范围(升序)
ZREVRANGE key start stop [WITHSCORES]                     # 按索引范围(降序)
ZREM key member [member ...]                              # 删除成员
ZSCORE key member                                         # 查询分数
ZRANK key member                                          # 查询排名(升序)
ZCOUNT key min max                                        # 按分数范围统计

🏆 典型应用:排行榜(商品销量、游戏积分、实时投票)。

127.0.0.1:6379> ZADD leaderboard 100 "player1" 200 "player2" 150 "player3"
(integer) 3
127.0.0.1:6379> ZREVRANGE leaderboard 0 -1 WITHSCORES
1) "player2"
2) "200"
3) "player3"
4) "150"
5) "player1"
6) "100"

3.5 Hash(哈希)

键值对集合,适合存储对象。

HSET key field value [field value ...]
HGET key field
HGETALL key
HDEL key field [field ...]
HEXISTS key field
HLEN key
HINCRBY key field increment
HKEYS key / HVALS key
127.0.0.1:6379> HSET user:1001 name "张三" age 25 city "北京"
(integer) 3
127.0.0.1:6379> HGET user:1001 name
"张三"
127.0.0.1:6379> HINCRBY user:1001 age 1
(integer) 26

四、八大应用场景

🗂️ 1. 热点数据缓存(Cache-Aside 模式)

读请求 → 查 Redis → 命中返回 / 未命中 → 查 DB → 回写 Redis → 返回

要点:合理 TTL、缓存键命名规范(product:info:1001)、空值缓存防止穿透。

🔒 2. 分布式锁

# 加锁:仅当 key 不存在时设置,30秒过期
SET lock:order:1001 unique_value NX PX 30000

# 解锁:Lua 脚本原子判断 + 删除
EVAL "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end" 1 lock:order:1001 unique_value

要点:加锁设过期 → 解锁用 Lua 保证原子性 → 长任务定时续期。

📊 3. 计数器与限流

INCR article:read:10086           # 阅读量 +1
INCR rate:api:/user:20240709      # 接口调用计数
EXPIRE rate:api:/user:20240709 60 # 每分钟最多 N 次

🏆 4. 排行榜系统

用 Zset 的 Score 排序,ZREVRANGE 取 Top N,ZRANK 查排名。

🔑 5. 分布式会话(Session)

多实例共享 Session,设置过期时间自动清理。

✉️ 6. 消息队列

List + LPUSH / BRPOP:生产者推入,消费者阻塞等待。

🗳️ 7. 位图(Bitmap)

用户签到、活跃统计、权限标记,极致节省空间。

📍 8. 地理位置(GEO)

附近的人 / 店铺查询,GEOADD + GEORADIUS


五、持久化:RDB 与 AOF

Redis 是内存数据库,一旦宕机数据即丢失。持久化机制将数据写入磁盘。

5.1 RDB(Redis DataBase)— 快照

定时将内存数据生成快照保存到 dump.rdb 文件。

触发方式

# 手动触发
SAVE      # 同步阻塞,主进程执行,生产禁用
BGSAVE    # 异步 Fork 子进程执行,推荐

# 配置文件自动触发
save 900 1      # 900秒内修改1个Key
save 300 10     # 300秒内修改10个Key
save 60 10000   # 60秒内修改10000个Key
SAVE BGSAVE
执行方式 主进程 Fork 子进程
是否阻塞 ✅ 阻塞所有请求 ❌ 仅 Fork 瞬间阻塞
适用场景 测试环境 生产环境

5.2 AOF(Append Only File)— 追加日志

记录每条写命令appendonly.aof 文件,重启时回放恢复数据。

# redis.conf
appendonly yes                          # 开启 AOF
appendfsync always                      # 每条命令都刷盘(最安全,最慢)
appendfsync everysec                    # 每秒刷盘一次(推荐,最多丢1秒数据)
appendfsync no                          # 由操作系统决定(最快,最不安全)
策略 安全性 性能 推荐
always 最高(不丢数据) 最低 极少用
everysec 高(最多丢1秒) 生产推荐
no 最高 不推荐

5.3 RDB vs AOF 对比

维度 RDB AOF
文件大小 小(压缩二进制) 大(文本命令)
恢复速度 慢(需回放命令)
数据安全 可能丢几分钟数据 最多丢1秒(everysec)
资源消耗 Fork 子进程,瞬间高 持续 IO 写入
推荐 AOF + RDB 混合使用

💡 最佳实践:生产环境同时开启 RDB 和 AOF(everysec),RDB 用于快速恢复,AOF 保证数据安全。


六、安装与配置

6.1 YUM 安装(CentOS 8)

# 安装
dnf install -y redis

# 启动并设置开机自启
systemctl enable redis --now

# 验证
ss -ntl | grep 6379
redis-cli ping          # 返回 PONG 即成功

6.2 源码编译安装(通用)

# 安装依赖
yum install -y tcl gcc gcc-c++

# 编译
tar zxvf redis-6.2.14.tar.gz -C /usr/local/
cd /usr/local/redis-6.2.14/
make && make install

# 后台启动
redis-server redis.conf &

6.3 多实例

redis-server --port 6380       # 启动第二个实例
redis-cli -p 6380              # 连接到第二个实例

6.4 关键配置项速查

配置项 默认值 说明
bind 127.0.0.1 127.0.0.1 绑定地址,远程访问改 0.0.0.0
port 6379 6379 监听端口
protected-mode yes yes 保护模式,无密码时仅本地连接
timeout 0 0 客户端空闲超时(0=不超时)
tcp-keepalive 300 300 TCP 心跳探测间隔(秒)
daemonize no no 是否后台运行
requirepass 连接密码
maxmemory 0 最大内存限制(0=不限制)

💡 6379 的冷知识:MERZ 是作者 antirez 和朋友用的俚语(形容"愚蠢"),在手机键盘上对应数字 6379。


七、主从复制

Redis 主从复制实现数据冗余读写分离

  • Master 可读可写,Slave 只读
  • 一个 Master 可以有多个 Slave
  • 数据流向:Master → Slave 单向

实验拓扑

角色 IP 主机名
Master 192.168.108.10 master
Slave01 192.168.108.11 slave01
Slave02 192.168.108.12 slave02

配置

# === 所有节点:配置 redis.conf ===
bind 0.0.0.0 -::1

# === Slave 节点额外配置:指向 Master ===
# redis.conf 方式:
replicaof 192.168.108.10 6379

# 命令行方式:
127.0.0.1:6379> REPLICAOF 192.168.108.10 6379

同步原理

1. Slave → Master: 发送 SYNC 命令
2. Master: 启动 BGSAVE 生成 RDB,同时缓冲新增写命令
3. Master → Slave: 传输 RDB 文件
4. Slave: 加载 RDB,完成首次全量同步
5. Master → Slave: 持续发送增量写命令(增量同步)

验证

# Master 查看复制状态
redis-cli INFO replication
# role:master
# connected_slaves:2

# Slave 查看
redis-cli INFO replication
# role:slave
# master_link_status:up        ← 关键:必须为 up

# 数据验证:Master 写入
127.0.0.1:6379> SET name laogao
OK
# Slave 读取
127.0.0.1:6379> GET name
"laogao"                        # ✅ 同步成功

取消主从

127.0.0.1:6379> REPLICAOF NO ONE

八、哨兵模式(Sentinel)

在主从基础上实现自动故障转移,是 Redis 原生高可用方案。

核心功能

功能 说明
监控 持续检查 Master 和 Slave 是否正常运行
通知 节点异常时通过 API 告警
自动故障转移 Master 宕机后,自动选举新 Master
配置提供者 客户端通过 Sentinel 获取最新 Master 地址

⚠️ Sentinel 本身不存储数据,只负责监控与协调。

哨兵判断流程

主观下线(SDOWN):一个 Sentinel 认为 Master 不可达
         ↓
客观下线(ODOWN):≥ quorum 个 Sentinel 都认为 Master 不可达
         ↓
选举 Leader Sentinel → 发起故障转移 → 提升 Slave 为新 Master

Sentinel 配置

# sentinel.conf
sentinel monitor mymaster 192.168.108.10 6379 2
#                     名称         Master IP    端口  quorum
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1

# quorum=2:至少2个哨兵认为挂了才算客观下线

启动哨兵

redis-sentinel sentinel.conf &

# 查看哨兵状态
redis-cli -p 26379
127.0.0.1:26379> INFO sentinel
# sentinel_masters:1
# master0:name=mymaster,status=ok,address=192.168.108.10:6379,slaves=2,sentinels=3

九、Redis Cluster 集群

哨兵解决高可用,Cluster 解决数据分片(水平扩展)

核心概念

  • Redis Cluster 将整个键空间划分为 16384 个哈希槽
  • 数据映射公式:slot = CRC16(key) % 16384
  • 每个节点负责一部分槽,支持在线迁移
┌─────────────┬──────────────┬──────────────┐
│  Master 1   │  Master 2    │  Master 3    │
│ slot 0-5460 │slot 5461-10922│slot 10923-16383│
│  Slave 1    │  Slave 2     │  Slave 3     │
└─────────────┴──────────────┴──────────────┘

创建 3 主 3 从集群

# 一键创建
redis-cli --cluster create \
  192.168.108.21:6379 \
  192.168.108.22:6379 \
  192.168.108.23:6379 \
  192.168.108.24:6379 \
  192.168.108.25:6379 \
  192.168.108.26:6379 \
  --cluster-replicas 1          # 每主1从

# 验证
redis-cli -c -h 192.168.108.21 -p 6379 cluster nodes
redis-cli -c -h 192.168.108.21 -p 6379 cluster info
# cluster_state:ok               ← 关键状态
# cluster_slots_assigned:16384

客户端连接(-c 模式)

redis-cli -c -h 192.168.108.21 -p 6379
127.0.0.1:6379> SET name wang
OK

127.0.0.1:6379> GET age
-> Redirected to slot [741] located at 192.168.108.21:6379
"18"

故障转移验证

关掉一个 Master,集群自动将对应 Slave 提升为新 Master:

# 关掉 master 1
[root@redis1 ~]# init 0

# 在存活的节点上查看
redis-cli -c -h 192.168.108.22 -p 6379 cluster nodes
# 原 slave 已被选举为新 master ✅
# cluster_state:ok                ← 集群仍然正常

十、Docker 容器化部署

# 启动 Redis 容器
docker run --name redis \
  -p 6379:6379 \
  -d \
  -v /data/redis:/data \
  redis

# 查看 Redis 信息
docker exec redis redis-cli INFO server

# 数据操作
docker exec redis redis-cli SET name wang
docker exec redis redis-cli GET name
# "wang"

# 持久化(数据保存在挂载的 /data/redis/dump.rdb)
docker exec redis redis-cli SAVE

十一、总结

技术选型参考

场景 方案
单机缓存 Redis 单实例
读写分离 + 数据冗余 主从复制(1 主 N 从)
自动故障转移 哨兵模式(≥ 3 个 Sentinel)
海量数据 + 水平扩展 Redis Cluster(≥ 6 节点,3 主 3 从)
开发 / 测试环境 Docker 一键部署

📖 本文基于个人 Redis 学习笔记整理,内容覆盖从入门到生产部署的完整链路。如有纰漏,欢迎评论区交流指正。

🔗 相关资源:Redis 官网 | Redis 中文文档 )

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐