3113 字
16 分钟

Redis 完全指南:从基础数据结构到集群部署与性能优化 | 2026最新实践

Redis 是当今最流行的内存数据库之一,广泛用于缓存、消息队列、分布式锁、排行榜等场景。2026 年,Redis 已成为现代 Web 应用的标配组件。本文从基础数据结构到集群部署,全面讲解 Redis 的完整知识体系。

Redis 完全指南

本文内容包括:

  • Redis 五大基础数据结构与使用场景
  • 高级特性:发布订阅、事务、Lua 脚本、Stream
  • 持久化机制:RDB 与 AOF 对比与配置
  • 主从复制与读写分离
  • 哨兵模式(Sentinel)自动故障转移
  • Cluster 集群部署与数据分片
  • 缓存策略:穿透/击穿/雪崩解决方案
  • 性能优化与监控
  • Python/Node.js 集成实战

一、Redis 数据结构#

1.1 String(字符串)#

Terminal window
# 基本操作
SET name "Alice"
GET name # "Alice"
DEL name
# 计数器
SET counter 100
INCR counter # 101
INCRBY counter 10 # 111
DECR counter # 110
# 过期时间
SET token "abc123" EX 3600 # 3600 秒后过期
TTL token # 查看剩余时间
PERSIST token # 移除过期时间
# 批量操作
MSET k1 "v1" k2 "v2" k3 "v3"
MGET k1 k2 k3
# Python 示例
import redis
r = redis.Redis(host='localhost', port=6379, db=0)
# 基本操作
r.set('name', 'Alice', ex=3600) # 带过期时间
name = r.get('name') # b'Alice'
# 计数器
r.set('counter', 100)
r.incr('counter') # 101
r.incrby('counter', 10) # 111

适用场景:缓存、计数器、分布式锁、Session 存储

1.2 List(列表)#

Terminal window
# 队列操作(先进先出)
LPUSH queue "msg1" "msg2" # 左侧插入
RPOP queue # 右侧弹出
# 栈操作(后进先出)
LPUSH stack "item1" "item2"
LPOP stack
# 查看列表
LRANGE queue 0 -1 # 查看所有元素
LLEN queue # 列表长度
# 阻塞式弹出(消息队列)
BRPOP queue 30 # 阻塞30秒等待消息

适用场景:消息队列、最新文章列表、操作日志

1.3 Hash(哈希表)#

Terminal window
# 存储对象
HSET user:1 name "Alice" age 30 email "alice@example.com"
HGET user:1 name # "Alice"
HGETALL user:1 # 所有字段和值
# 批量设置
HMSET user:2 name "Bob" age 25 email "bob@example.com"
# 数值字段操作
HINCRBY user:1 age 1 # age + 1
# 删除字段
HDEL user:1 email
# Python 示例
r.hset('user:1', mapping={
'name': 'Alice',
'age': 30,
'email': 'alice@example.com'
})
user = r.hgetall('user:1')
# {b'name': b'Alice', b'age': b'30', b'email': b'alice@example.com'}

适用场景:用户信息、商品属性、配置存储

1.4 Set(集合)#

Terminal window
# 集合操作
SADD tags "python" "redis" "docker"
SMEMBERS tags # 查看所有成员
SISMEMBER tags "python" # 判断是否存在
SCARD tags # 集合大小
# 集合运算
SADD set1 "a" "b" "c"
SADD set2 "b" "c" "d"
SINTER set1 set2 # 交集 {"b", "c"}
SUNION set1 set2 # 并集 {"a", "b", "c", "d"}
SDIFF set1 set2 # 差集 {"a"}

适用场景:标签系统、共同好友、去重

1.5 ZSet(有序集合)#

Terminal window
# 排行榜
ZADD ranking 100 "Alice" 85 "Bob" 92 "Charlie"
# 按分数排序
ZRANGE ranking 0 -1 WITHSCORES # 升序
ZREVRANGE ranking 0 -1 WITHSCORES # 降序
ZREVRANGE ranking 0 2 WITHSCORES # Top 3
# 分数操作
ZINCRBY ranking 10 "Bob" # Bob 分数+10
# 范围查询
ZRANGEBYSCORE ranking 80 100 # 80-100分之间
ZRANK ranking "Alice" # 排名(升序)
ZREVRANK ranking "Alice" # 排名(降序)
# Python 示例:游戏排行榜
r.zadd('game_ranking', {
'Alice': 100,
'Bob': 85,
'Charlie': 92
})
# 获取 Top 3
top3 = r.zrevrange('game_ranking', 0, 2, withscores=True)
# [(b'Alice', 100.0), (b'Charlie', 92.0), (b'Bob', 85.0)]
# 增加分数
r.zincrby('game_ranking', 10, 'Bob') # Bob: 95

适用场景:排行榜、延时队列、带权重的消息


二、高级特性#

2.1 发布订阅(Pub/Sub)#

Terminal window
# 终端1:订阅频道
SUBSCRIBE news
# 终端2:发布消息
PUBLISH news "Hello World"
# 模式订阅
PSUBSCRIBE news.*
# Python 发布者
r.publish('news', 'Hello World')
# Python 订阅者
pubsub = r.pubsub()
pubsub.subscribe('news')
for message in pubsub.listen():
if message['type'] == 'message':
print(message['data']) # b'Hello World'

2.2 事务#

Terminal window
# MULTI/EXEC 事务
MULTI
SET key1 "value1"
INCR counter
EXEC
# WATCH 实现乐观锁
WATCH counter
val = GET counter
MULTI
INCR counter
EXEC # 如果 counter 被其他客户端修改,EXEC 返回 nil

2.3 Lua 脚本#

Terminal window
# 原子性操作:分布式锁
EVAL "
if redis.call('get', KEYS[1]) == ARGV[1] then
return redis.call('del', KEYS[1])
else
return 0
end
" 1 lock_key "unique_value"
# Python 执行 Lua 脚本
lua_script = """
if redis.call('get', KEYS[1]) == ARGV[1] then
return redis.call('del', KEYS[1])
else
return 0
end
"""
# 分布式锁释放
r.eval(lua_script, 1, 'lock_key', 'unique_value')

2.4 Stream(消息流)#

Terminal window
# 生产消息
XADD stream1 "*" name "Alice" action "login"
# 消费消息
XREAD COUNT 10 STREAMS stream1 0
# 消费者组
XGROUP CREATE stream1 group1 0
XREADGROUP GROUP group1 consumer1 COUNT 10 STREAMS stream1 >
# Python Stream 示例
# 生产
r.xadd('events', {'name': 'Alice', 'action': 'login'})
# 消费
r.xread({'events': '0'}, count=10)

三、持久化机制#

3.1 RDB vs AOF#

特性RDBAOF
原理定时快照追加日志
文件二进制紧凑文本命令
恢复速度
数据安全可能丢失更安全
性能影响小(fork子进程)较大(每条写命令)

3.2 RDB 配置#

Terminal window
# redis.conf
# 快照策略:N 秒内 M 次修改触发
save 900 1 # 15分钟内1次修改
save 300 10 # 5分钟内10次修改
save 60 10000 # 1分钟内1万次修改
# 快照文件名
dbfilename dump.rdb
# 存储目录
dir /var/lib/redis
# 压缩
rdbcompression yes
# 手动触发快照
# redis-cli BGSAVE

3.3 AOF 配置#

Terminal window
# redis.conf
# 开启 AOF
appendonly yes
# 文件名
appendfilename "appendonly.aof"
# 刷盘策略
# always: 每条命令都刷盘(最安全,最慢)
# everysec: 每秒刷盘(推荐,平衡)
# no: 由操作系统决定(最快,可能丢失数据)
appendfsync everysec
# AOF 重写:压缩 AOF 文件
auto-aof-rewrite-percentage 100 # 文件大小翻倍时重写
auto-aof-rewrite-min-size 64mb # 最小重写大小

3.4 混合持久化(Redis 4.0+)#

Terminal window
# 混合持久化:RDB 做全量 + AOF 做增量
aof-use-rdb-preamble yes
# 重写时:前半部分 RDB 格式,后半部分 AOF 格式
# 恢复时:先加载 RDB(快速),再回放 AOF(补全)

四、主从复制#

4.1 架构图#

主从复制架构:
Master (读写)
┌──┴──┐
│ │
Slave1 Slave2 (只读)
特点:
- 读写分离:主节点写,从节点读
- 数据冗余:从节点保存数据副本
- 故障恢复:主节点故障可手动切换

4.2 配置#

Terminal window
# 从节点 redis.conf
replicaof 192.168.1.100 6379
# 从节点只读
replica-read-only yes
# 主节点认证密码
masterauth yourpassword
# 验证主从
redis-cli INFO replication
Terminal window
# 主节点信息
# role:master
# connected_slaves:2
# 从节点信息
# role:slave
# master_host:192.168.1.100
# master_port:6379

五、哨兵模式(Sentinel)#

5.1 架构图#

哨兵模式架构:
Sentinel1 Sentinel2 Sentinel3
│ │ │
└────────────┼────────────┘
┌───────┴───────┐
│ │
Master Slave
哨兵职责:
1. 监控:检测主从节点是否存活
2. 通知:通知运维人员故障
3. 自动故障转移:主节点故障时自动选举新主
4. 配置提供:客户端连接哨兵获取主节点地址

5.2 哨兵配置#

Terminal window
# sentinel.conf
# 监控主节点(名称 IP 端口 quorum)
sentinel monitor mymaster 192.168.1.100 6379 2
# 主节点密码
sentinel auth-pass mymaster yourpassword
# 判断主节点下线的超时时间(毫秒)
sentinel down-after-milliseconds mymaster 30000
# 故障转移时从节点数量
sentinel parallel-syncs mymaster 1
# 故障转移超时时间
sentinel failover-timeout mymaster 180000
Terminal window
# 启动哨兵
redis-sentinel /etc/redis/sentinel.conf
# 查看哨兵状态
redis-cli -p 26379 SENTINEL masters
redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster

六、Cluster 集群#

6.1 架构图#

Redis Cluster 架构(6个节点,3主3从):
节点A (master) ←→ 节点B (slave)
slot 0-5460
节点C (master) ←→ 节点D (slave)
slot 5461-10922
节点E (master) ←→ 节点F (slave)
slot 10923-16383
特点:
- 数据分片:16384 个 slot 分配到各节点
- 去中心化:节点间通过 Gossip 协议通信
- 自动故障转移:主节点故障,从节点升级
- 水平扩展:可动态添加/移除节点

6.2 集群搭建#

Terminal window
# 方法1:使用 redis-cli 快速创建(Redis 5.0+)
# 创建6个节点的配置文件
for port in 7000 7001 7002 7003 7004 7005; do
mkdir -p /redis/cluster/${port}
cat > /redis/cluster/${port}/redis.conf << EOF
port ${port}
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
dir /redis/cluster/${port}
EOF
done
# 启动所有节点
for port in 7000 7001 7002 7003 7004 7005; do
redis-server /redis/cluster/${port}/redis.conf &
done
# 创建集群(3主3从)
redis-cli --cluster create \
127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \
127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
--cluster-replicas 1
# 验证集群
redis-cli -p 7000 CLUSTER INFO
redis-cli -p 7000 CLUSTER NODES

6.3 集群操作#

Terminal window
# 集群模式连接
redis-cli -c -p 7000
# 自动路由到正确节点
SET key1 "value1" # 可能自动跳转到 7001
# 查看slot分配
CLUSTER KEYSLOT key1 # 计算key所属slot
# 添加新节点
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000
# 重新分片
redis-cli --cluster reshard 127.0.0.1:7000

七、缓存策略#

7.1 缓存穿透#

# 问题:查询不存在的数据,绕过缓存直接打到数据库
# 方案1:缓存空值
def get_user(user_id):
cache_key = f"user:{user_id}"
user = r.get(cache_key)
if user is not None:
if user == b'':
return None # 缓存的空值
return json.loads(user)
# 查询数据库
user = db.query("SELECT * FROM users WHERE id = %s", user_id)
if user is None:
# 缓存空值,短过期时间
r.setex(cache_key, 300, '')
else:
r.setex(cache_key, 3600, json.dumps(user))
return user
# 方案2:布隆过滤器
from redisbloom.client import Client
rb = Client()
rb.bfCreate('users_filter', 0.01, 1000000) # 错误率1%,容量100万
# 添加存在的用户ID
rb.bfAdd('users_filter', 'user_123')
def get_user_safe(user_id):
# 先检查布隆过滤器
if not rb.bfExists('users_filter', user_id):
return None # 一定不存在
# 再查缓存和数据库
return get_user(user_id)

7.2 缓存击穿#

# 问题:热点key过期瞬间,大量请求同时打到数据库
# 方案:互斥锁
import time
import uuid
def get_hot_data(key):
# 先查缓存
data = r.get(key)
if data is not None:
return json.loads(data)
# 获取互斥锁
lock_key = f"lock:{key}"
lock_value = str(uuid.uuid4())
# 尝试获取锁(设置过期时间防止死锁)
if r.set(lock_key, lock_value, nx=True, ex=10):
try:
# 查询数据库
data = db.query_hot_data(key)
# 写入缓存
r.setex(key, 3600, json.dumps(data))
return data
finally:
# 释放锁(Lua脚本保证原子性)
lua = """
if redis.call('get', KEYS[1]) == ARGV[1] then
return redis.call('del', KEYS[1])
else
return 0
end
"""
r.eval(lua, 1, lock_key, lock_value)
else:
# 等待后重试
time.sleep(0.1)
return get_hot_data(key)

7.3 缓存雪崩#

# 问题:大量key同时过期,请求全部打到数据库
# 方案1:过期时间加随机值
def cache_data(key, data, base_ttl=3600):
import random
# 过期时间加 0-300 秒随机值
ttl = base_ttl + random.randint(0, 300)
r.setex(key, ttl, json.dumps(data))
# 方案2:多级缓存
import functools
@functools.lru_cache(maxsize=1000) # 本地缓存
def get_data_l1(key):
# L2: Redis 缓存
data = r.get(key)
if data:
return json.loads(data)
# L3: 数据库
data = db.query(key)
if data:
cache_data(key, data)
return data

八、性能优化#

8.1 关键配置优化#

Terminal window
# redis.conf 性能相关
# 内存策略
maxmemory 4gb
maxmemory-policy allkeys-lru # LRU 淘汰策略
# 网络配置
tcp-keepalive 300
timeout 0
# 慢查询日志
slowlog-log-slower-than 10000 # 10ms
slowlog-max-len 128
# 客户端缓冲区限制
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
# 后台任务频率(清理过期key等)
hz 10

8.2 内存优化#

Terminal window
# 使用 Hash 替代多个 String
# 不推荐:1000个 String
SET user:1:name "Alice"
SET user:1:age "30"
# 推荐:1个 Hash
HSET user:1 name "Alice" age 30
# 使用 ziplist 编码(小数据量自动启用)
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64

8.3 Pipeline 批量操作#

# 不推荐:逐条执行
for i in range(1000):
r.set(f'key:{i}', i)
# 1000 次网络往返
# 推荐:Pipeline
pipe = r.pipeline()
for i in range(1000):
pipe.set(f'key:{i}', i)
pipe.execute()
# 1 次网络往返
# 事务型 Pipeline
pipe = r.pipeline(transaction=True)
pipe.set('key1', 'value1')
pipe.incr('counter')
pipe.execute()

8.4 监控指标#

Terminal window
# 关键监控指标
redis-cli INFO
# Server: 版本、运行时间
# Clients: 连接数
# Memory: 内存使用
# Stats: 命中率、QPS
# Replication: 主从状态
# 重要指标
used_memory_human # 内存使用
connected_clients # 客户端连接数
keyspace_hits # 缓存命中
keyspace_misses # 缓存未命中
hit_rate = hits / (hits + misses) # 命中率
# 查看慢查询
redis-cli SLOWLOG GET 10
# 大Key扫描
redis-cli --bigkeys
# 内存分析
redis-cli MEMORY STATS

九、Python/Node.js 集成#

9.1 Python(redis-py)#

import redis
import json
# 连接池
pool = redis.ConnectionPool(
host='localhost',
port=6379,
db=0,
max_connections=20,
decode_responses=True # 自动解码为字符串
)
r = redis.Redis(connection_pool=pool)
# 基本操作
r.set('key', 'value', ex=3600)
value = r.get('key')
# JSON 缓存
def cache_json(key, data, ttl=3600):
r.setex(key, ttl, json.dumps(data, ensure_ascii=False))
def get_json(key):
data = r.get(key)
return json.loads(data) if data else None
# 分布式锁
def acquire_lock(lock_name, timeout=10):
identifier = str(uuid.uuid4())
end = time.time() + timeout
while time.time() < end:
if r.set(lock_name, identifier, nx=True, ex=timeout):
return identifier
time.sleep(0.001)
return None
def release_lock(lock_name, identifier):
lua = """
if redis.call('get', KEYS[1]) == ARGV[1] then
return redis.call('del', KEYS[1])
else
return 0
end
"""
return r.eval(lua, 1, lock_name, identifier)

9.2 Node.js(ioredis)#

const Redis = require('ioredis');
// 连接集群
const redis = new Redis.Cluster([
{ host: '127.0.0.1', port: 7000 },
{ host: '127.0.0.1', port: 7001 },
{ host: '127.0.0.1', port: 7002 },
]);
// 基本操作
await redis.set('key', 'value', 'EX', 3600);
const value = await redis.get('key');
// Pipeline
const pipeline = redis.pipeline();
for (let i = 0; i < 1000; i++) {
pipeline.set(`key:${i}`, i);
}
const results = await pipeline.exec();
// 事务
const multi = redis.multi();
multi.set('key1', 'value1');
multi.incr('counter');
const results = await multi.exec();

十、总结#

Redis 应用场景速查#

场景数据结构关键命令
缓存StringSET/GET/SETEX
计数器StringINCR/INCRBY
排行榜ZSetZADD/ZREVRANGE
消息队列List/StreamLPUSH/BRPOP, XADD/XREAD
用户信息HashHSET/HGETALL
标签系统SetSADD/SINTER
分布式锁String+LuaSET NX + Lua
限流器ZSet/ListZADD/ZREMRANGEBYSCORE
地理位置GeoGEOADD/GEOSEARCH
签到统计BitmapSETBIT/BITCOUNT

部署建议#

小型项目:单机 Redis(开启持久化)
中型项目:主从 + 哨兵(高可用)
大型项目:Cluster 集群(水平扩展)
缓存场景:可关闭持久化,使用最大内存策略
数据重要:RDB + AOF 混合持久化

Redis 是现代应用不可或缺的基础设施。掌握数据结构选择、持久化配置、集群部署和缓存策略,是构建高性能应用的基础。从单机到集群,从缓存到消息队列,Redis 的应用场景远超想象。

Redis 完全指南:从基础数据结构到集群部署与性能优化 | 2026最新实践
https://971918.xyz/posts/docs/redis-complete-guide/
作者
九所长
发布于
2026-06-26
许可协议
CC BY-NC-SA 4.0