运维与架构
一、Redis 部署架构演进
1.1 单机模式
架构:
┌─────────────┐
│ Application│
└──────┬──────┘
↓
┌─────────────┐
│ Redis 单机 │
└─────────────┘
优点:
- 架构简单,部署方便
- 成本低,资源占用少
- 适用于开发测试环境
缺点:
- 单点故障
- 数据可靠性低
- 性能受限于单机
适用场景:
- 开发环境
- 测试环境
- 小规模应用(QPS < 1000)
配置示例:
# redis.conf
port 6379
bind 0.0.0.0
daemonize yes
logfile /var/log/redis/redis.log
dir /var/lib/redis
1.2 主从复制模式
架构:
┌─────────────┐
│ Application│
└──────┬──────┘
↓
┌─────────────────────────────┐
│ Master (Write) │
└──────┬──────────┬───────────┘
↓ ↓
┌──────────┐ ┌──────────┐
│ Slave 1 │ │ Slave 2 │ (Read)
│ (Read) │ │ (Read) │
└──────────┘ └──────────┘
优点:
- 读写分离,提升读性能
- 数据备份,提高可靠性
- 故障切换(需要人工介入)
缺点:
- 主节点单点故障
- 主节点写压力大
- 故障切换需要人工介入
适用场景:
- 读多写少的场景
- 需要数据备份
- 中等规模应用(QPS 1000-10000)
Master 配置:
# 主节点配置
port 6379
bind 0.0.0.0
daemonize yes
logfile /var/log/redis/master.log
dir /var/lib/redis/master
# 持久化配置
save 900 1
save 300 10
save 60 10000
Slave 配置:
# 从节点配置
port 6380
bind 0.0.0.0
daemonize yes
logfile /var/log/redis/slave.log
dir /var/lib/redis/slave
# 复制配置
replicaof 192.168.1.100 6379
masterauth "your-password"
replica-serve-stale-data yes
replica-read-only yes
主从复制验证:
# 在 Master 上查看从节点
127.0.0.1:6379> INFO replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.1.101,port=6380,state=online,offset=123456
slave1:ip=192.168.1.102,port=6380,state=online,offset=123456
1.3 哨兵模式(Sentinel)
架构:
┌──────────────┐
│ Application │
└──────┬───────┘
↓
┌────────────────────────────────┐
│ Sentinel Cluster │
│ (自动故障检测与切换) │
└────────────────────────────────┘
↓
┌───────────────────────────────────────┐
│ Master (Write) │
└───┬──────────┬──────────┬──────────────┘
↓ ↓ ↓
┌────────┐ ┌────────┐ ┌────────┐
│Sentinel│ │Sentinel│ │Sentinel│
└────────┘ └────────┘ └────────┘
↓ ↓ ↓
┌────────┐ ┌────────┐ ┌────────┐
│ Slave 1│ │ Slave 2│ │ Slave 3│
└────────┘ └────────┘ └────────┘
优点:
- 自动故障检测
- 自动故障转移
- 自动配置更新
- 高可用性
缺点:
- 架构相对复杂
- 主节点写压力大
- 需要奇数个哨兵节点
适用场景:
- 需要高可用
- 不能容忍长时间服务中断
- 中大规模应用(QPS 10000-50000)
Sentinel 配置:
# sentinel.conf
port 26379
daemonize yes
logfile /var/log/redis/sentinel.log
dir /var/lib/redis/sentinel
# 监控主节点
sentinel monitor mymaster 192.168.1.100 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
# 认证
sentinel auth-pass mymaster your-password
# 故障转移配置
sentinel notification-script mymaster /var/redis/notify.sh
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
启动哨兵:
# 启动 3 个哨兵节点
redis-sentinel /etc/redis/sentinel-1.conf --port 26379
redis-sentinel /etc/redis/sentinel-2.conf --port 26380
redis-sentinel /etc/redis/sentinel-3.conf --port 26381
验证哨兵状态:
127.0.0.1:26379> SENTINEL masters
1) 1) "name"
2) "mymaster"
3) "ip"
4) "192.168.1.100"
5) "port"
6) "6379"
...
127.0.0.1:26379> SENTINEL slaves mymaster
1) 1) "name"
2) "192.168.1.101:6380"
...
1.4 Redis Cluster 集群模式
架构:
┌─────────────────────────────────────┐
│ Gossip Protocol │
│ (节点间通信与状态同步) │
└─────────────────────────────────────┘
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Master 1 │ │ Master 2 │ │ Master 3 │
│ Slot 0-5460 │ │Slot 5461-10922│ │Slot 10923-16383│
│ Write │ │ Write │ │ Write │
└───────┬──────┘ └───────┬──────┘ └───────┬──────┘
↓ ↓ ↓
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Slave 1 │ │ Slave 2 │ │ Slave 3 │
│ (Read) │ │ (Read) │ │ (Read) │
└──────────────┘ └──────────────┘ └──────────────┘
特点:
- 分片:16384 个槽位
- 高可用:每个主节点配置从节点
- 自动故障转移:主节点故障时从节点升级
- 去中心化:无中心节点,节点间通过 Gossip 协议通信
优点:
- 自动分片
- 高可用性
- 水平扩展
- 无中心节点
缺点:
- 运维复杂
- 数据迁移成本高
- 事务支持有限
- 不支持多键操作(必须在同一槽位)
适用场景:
- 大规模应用(QPS > 50000)
- 需要水平扩展
- 数据量大(> 50 GB)
集群配置:
# cluster-enabled yes
# 集群配置文件
cluster-config-file nodes.conf
# 节点超时时间
cluster-node-timeout 5000
# 集群总线端口
port 7000
cluster-port 17000
# 持久化
appendonly yes
appendfilename "appendonly.aof"
创建集群:
# 创建 6 个节点(3 主 3 从)
redis-server /etc/redis/cluster/7000/redis.conf
redis-server /etc/redis/cluster/7001/redis.conf
redis-server /etc/redis/cluster/7002/redis.conf
redis-server /etc/redis/cluster/7003/redis.conf
redis-server /etc/redis/cluster/7004/redis.conf
redis-server /etc/redis/cluster/7005/redis.conf
# 创建集群
redis-cli --cluster create \
192.168.1.100:7000 192.168.1.100:7001 192.168.1.100:7002 \
192.168.1.100:7003 192.168.1.100:7004 192.168.1.100:7005 \
--cluster-replicas 1
验证集群:
# 查看集群状态
redis-cli -c -p 7000 cluster nodes
# 查看集群信息
redis-cli -c -p 7000 cluster info
1.5 架构对比
| 特性 | 单机 | 主从复制 | 哨兵 | 集群 |
|---|---|---|---|---|
| 高可用 | ❌ | ⚠️ | ✅ | ✅ |
| 自动故障转移 | ❌ | ❌ | ✅ | ✅ |
| 水平扩展 | ❌ | ❌ | ❌ | ✅ |
| 读写分离 | ❌ | ✅ | ✅ | ✅ |
| 数据分片 | ❌ | ❌ | ❌ | ✅ |
| 运维复杂度 | 低 | 中 | 中 | 高 |
| 成本 | 低 | 中 | 中 | 高 |
| QPS 能力 | < 1K | 1-10K | 1-10K | > 50K |
面试题:如何选择 Redis 部署架构?
答案:
-
单机模式
- 开发/测试环境
- 数据量小(< 1 GB)
- QPS < 1000
-
主从复制
- 读多写少
- 需要数据备份
- QPS 1000-10000
-
哨兵模式
- 需要高可用
- 不能容忍服务中断
- QPS 10000-50000
-
集群模式
- 大规模应用
- 需要水平扩展
- 数据量大(> 50 GB)
- QPS > 50000
二、主从复制详解
2.1 复制流程
完整流程:
1. 建立连接
Slave → Master: SYNC命令
Master → Slave: 确认连接
2. 全量同步
Master: fork 子进程
Master: 执行 BGSAVE 生成 RDB
Master: 发送 RDB 文件给 Slave
Slave: 载入 RDB 文件
Master: 发送复制缓冲区的增量命令
3. 增量同步
Master: 执行写命令
Master: 记录到复制缓冲区
Master: 发送命令给 Slave
Slave: 执行命令
4. 命令传播
Master: 每次执行写命令后发送给 Slave
Slave: 接收并执行命令
相关配置:
# 主节点配置
repl-diskless-sync no # 是否使用无盘复制
repl-diskless-sync-delay 5 # 无盘复制延迟(秒)
repl-ping-slave-period 10 # 从节点 ping 周期
repl-timeout 60 # 复制超时时间
repl-disable-tcp-nodelay no # 是否禁用 TCP_NODELAY
repl-backlog-size 1mb # 复制缓冲区大小
repl-backlog-ttl 3600 # 缓冲区存活时间
2.2 部分重同步(PSYNC)
版本信息:
- replication offset:复制偏移量
- master runid:主节点运行 ID
部分重同步条件:
- 从节点记录的主节点 runid 与当前主节点一致
- 复制偏移量在复制缓冲区范围内
配置:
# 复制积压缓冲区大小(根据网络状况调整)
repl-backlog-size 10mb
面试题:全量同步和部分同步的区别?
答案:
| 特性 | 全量同步(SYNC) | 部分同步(PSYNC) |
|---|---|---|
| 数据量 | 完整数据集 | 增量数据 |
| 耗时 | 长(取决于数据量) | 短 |
| 网络开销 | 大 | 小 |
| 触发条件 | 首次连接或复制偏移量丢失 | 复制偏移量在缓冲区内 |
| RDB 文件 | 需要 | 不需要 |
2.3 主从复制监控
监控命令:
# 查看主节点复制状态
127.0.0.1:6379> INFO replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.1.101,port=6380,state=online,offset=123456,lag=0
slave1:ip=192.168.1.102,port=6380,state=online,offset=123456,lag=1
# 查看从节点复制状态
127.0.0.1:6380> INFO replication
# Replication
role:slave
master_host:192.168.1.100
master_port:6379
master_link_status:up
master_link_down_time:0
master_sync_in_progress:0
slave_repl_offset:123456
slave_priority:100
slave_read_only:1
关键指标:
- master_link_status:主从连接状态
- master_link_down_time:断线时长
- slave_repl_offset:从节点复制偏移量
- lag:从节点延迟(秒)
三、哨兵模式详解
3.1 哨兵工作原理
三个监控机制:
- 主观下线(SDOWN)
# 单个哨兵认为主节点下线
条件:down-after-milliseconds 内无响应
- 客观下线(ODOWN)
# 多数哨兵认为主节点下线
条件:quorum 个哨兵认为主节点下线
sentinel monitor mymaster 192.168.1.100 6379 2 # quorum = 2
- 故障转移
1. 选举领头哨兵(Raft 协议)
2. 选择新主节点:
- 优先级(slave-priority)
- 复制偏移量(数据越新越优先)
- run ID(字典序越小越优先)
3. 升级从节点为主节点
4. 其他从节点复制新主节点
5. 通知客户端新主节点地址
3.2 哨兵配置详解
完整配置示例:
# sentinel.conf
port 26379
daemonize yes
logfile "/var/log/redis/sentinel.log"
dir "/var/lib/redis/sentinel"
# 监控主节点
sentinel monitor mymaster 192.168.1.100 6379 2
# 故障判断时间(毫秒)
sentinel down-after-milliseconds mymaster 30000
# 并行同步数(同时有多少个从节点同步新主节点)
sentinel parallel-syncs mymaster 1
# 故障转移超时时间(毫秒)
sentinel failover-timeout mymaster 180000
# 故障转移通知脚本
sentinel notification-script mymaster /var/redis/notify.sh
# 客户端重新配置脚本
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
# 认证密码
sentinel auth-pass mymaster YourPassword
# 配置纪元(用于识别配置版本)
sentinel config-epoch mymaster 1
# 领导选举
sentinel leader-epoch mymaster 1
# 当前纪元
sentinel current-epoch 1
3.3 哨兵命令
# 查看主节点状态
SENTINEL masters
# 查看主节点详细信息
SENTINEL master mymaster
# 查看从节点列表
SENTINEL slaves mymaster
# 查看哨兵信息
SENTINEL sentinels mymaster
# 获取主节点地址
SENTINEL get-master-addr-by-name mymaster
# 手动故障转移
SENTINEL failover mymaster
# 检查主观下线状态
SENTINEL ckquorum mymaster
# 刷新配置
SENTINEL FLUSHCONFIG
3.4 哨兵高可用部署
推荐架构:
┌──────────────┐
│ Client │
└──────┬───────┘
↓
┌──────────────────────────┐
│ Sentinel Quorum │
│ (至少 2 个哨兵同意) │
└──────────────────────────┘
↓ ↓ ↓
┌───────┐ ┌───────┐ ┌───────┐
│Sentinel│ │Sentinel│ │Sentinel│
│ Node 1│ │ Node 2│ │ Node 3│
└───────┘ └───────┘ └───────┘
↓ ↓ ↓
┌──────────────────────────────┐
│ Master/Slave │
└──────────────────────────────┘
部署建议:
- 至少 3 个哨兵节点
- 分布在不同机器或可用区
- 奇数个节点(2n+1)
- quorum 设置为 n+1
面试题:哨兵模式如何保证高可用?
答案:
-
多哨兵部署
- 至少 3 个节点
- 避免单点故障
-
quorum 机制
- 需要多数哨兵同意
- 避免误判
-
自动故障转移
- 主节点故障时自动选举新主节点
- 无需人工干预
-
客户端通知
- Pub/Sub 机制通知客户端
- 自动更新连接地址
-
配置持久化
- 哨兵配置持久化到磁盘
- 重启后恢复状态
四、Redis Cluster 集群详解
4.1 分片原理
槽位分配:
总槽位:16384
节点数:3(主节点)
每个节点:16384 / 3 ≈ 5461 个槽位
Master 1: Slot 0-5460
Master 2: Slot 5461-10922
Master 3: Slot 10923-16383
Key 分配算法:
# 计算 key 所属槽位
slot = CRC16(key) % 16384
# 示例
CRC16("user:1001") = 12345678
slot = 12345678 % 16384 = 5432
# 属于 Master 1
Hash Tag:
# 使用哈希标签确保相关 key 在同一节点
SET {user:1001}:profile "{...}"
SET {user:1001}:orders "{...}"
SET {user:1001}:cart "{...}"
# 这些 key 会分配到同一槽位
4.2 集群操作
查看集群状态:
# 连接到集群
redis-cli -c -p 7000
# 查看集群节点
127.0.0.1:7000> CLUSTER NODES
4b4b4b4b... 127.0.0.1:7000@17000 myself,master - 0 0 1 connected 0-5460
5c5c5c5c... 127.0.0.1:7001@17001 slave 4b4b4b4b... 0 1440000000000 2 connected
...
# 查看集群信息
127.0.0.1:7000> CLUSTER INFO
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
查看槽位信息:
# 查看槽位分布
127.0.0.1:7000> CLUSTER SLOTS
1) 1) (integer) 0
2) (integer) 5460
3) 1) "127.0.0.1"
2) (integer) 7000
3) "4b4b4b4b..."
2) 1) (integer) 5461
2) (integer) 10922
...
计算 key 的槽位:
127.0.0.1:7000> CLUSTER KEYSLOT user:1001
(integer) 5432
# 查看槽位所属节点
127.0.0.1:7000> CLUSTER NODES | grep 4b4b4b4b...
4.3 故障转移
故障转移流程:
1. 主节点故障
Master 1: Slot 0-5460
↓ 故障
2. 从节点检测到故障
Slave 1: PFAIL 状态
Slave 1: 通知其他节点
3. 主观下线(PFAIL)
部分节点认为 Master 1 下线
4. 客观下线(FAIL)
多数节点认为 Master 1 下线
5. 选举新主节点
Slave 1 升级为 Master
分配 Slot 0-5460
6. 重新分片
其他节点更新槽位映射
7. 故障恢复
旧 Master 1 恢复后作为 Slave
配置故障转移:
# 节点超时时间(故障检测)
cluster-node-timeout 15000
# 从节点优先级(用于选举)
replica-priority 100
# 迁移速度限制
cluster-migration-barrier 1
4.4 槽位迁移
迁移流程:
# 1. 源节点导入槽位
# 源节点上执行
CLUSTER SETSLOT 5432 IMPORTING <target-node-id>
# 2. 目标节点导入槽位
# 目标节点上执行
CLUSTER SETSLOT 5432 MIGRATING <source-node-id>
# 3. 迁移 key
MIGRATE <target-host> <target-port> key 0 5000
# 4. 完成迁移
CLUSTER SETSLOT 5432 NODE <target-node-id>
CLUSTER SETSLOT 5432 STABLE
批量迁移工具:
# 使用 redis-cli 迁移
redis-cli --cluster reshard 127.0.0.1:7000 \
--cluster-from <source-node-id> \
--cluster-to <target-node-id> \
--cluster-slots 1000
五、运维监控体系
5.1 监控指标
基础指标:
# 内存使用
INFO memory
used_memory:1073741824
used_memory_human:1.00G
used_memory_rss:1342177280
used_memory_peak:2147483648
maxmemory:0
maxmemory_policy:allkeys-lru
# CPU 使用
INFO cpu
used_cpu_sys:100.25
used_cpu_user:200.50
used_cpu_sys_children:50.12
used_cpu_user_children:100.25
# 连接数
INFO clients
connected_clients:100
blocked_clients:0
# 命令统计
INFO commandstats
cmdstat_get:calls=1000,usec=2500
cmdstat_set:calls=500,usec=1500
性能指标:
# QPS
INFO stats
instantaneous_ops_per_sec:1000
total_commands_processed:1000000
# 延迟
LATENCY LATEST
1) 1) "command"
2) "set"
3) "latency" (integer) 250
# 慢查询
SLOWLOG GET 10
1) 1) (integer) 14
2) (integer) 1704067200
3) (integer) 50000
4) "KEYS" "user:*"
复制指标:
INFO replication
role:master
connected_slaves:2
slave0:ip=192.168.1.101,port=6380,state=online,offset=123456,lag=0
集群指标:
CLUSTER INFO
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
5.2 Prometheus 监控
部署 redis_exporter:
# Docker 部署
docker run -d --name redis_exporter \
-p 9121:9121 \
oliver006/redis_exporter \
--redis.addr=redis://localhost:6379
# 编译部署
git clone https://github.com/oliver006/redis_exporter.git
cd redis_exporter
go build
./redis_exporter --redis.addr=redis://localhost:6379
Prometheus 配置:
# prometheus.yml
scrape_configs:
- job_name: 'redis'
static_configs:
- targets:
- 'localhost:9121'
scrape_interval: 15s
关键指标:
# 内存使用率
redis_memory_used_bytes / redis_memory_max_bytes * 100
# QPS
rate(redis_commands_processed_total[1m])
# 慢查询
rate(redis_slowlog_length[5m])
# 连接数
redis_connected_clients
# 命令失败率
rate(redis_commands_failed_total[5m]) / rate(redis_commands_processed_total[5m])
5.3 Grafana 监控面板
导入面板:
# Redis Dashboard ID: 11835
grafana-cli \
--grafana-url=http://localhost:3000 \
--user=admin \
--password=admin \
dashboards import 11835
自定义查询:
{
"title": "Redis QPS",
"targets": [
{
"expr": "rate(redis_commands_processed_total[1m])",
"legendFormat": "{{instance}}"
}
]
}
六、故障排查
6.1 常见问题
问题 1:内存不足
现象:
# OOM 错误
OOM command not allowed when used memory > 'maxmemory'.
排查:
# 查看内存使用
INFO memory
# 查看大 key
redis-cli --bigkeys
# 查看内存分布
redis-cli --memkeys
解决:
# 1. 设置最大内存
CONFIG SET maxmemory 2gb
# 2. 设置淘汰策略
CONFIG SET maxmemory-policy allkeys-lru
# 3. 删除大 key
redis-cli --bigkeys
# 找到后手动删除
DEL bigkey
# 4. 清理过期 key
redis-cli --scan --pattern "tmp:*" | xargs redis-cli DEL
问题 2:主从同步延迟
现象:
# 从节点复制延迟
INFO replication
lag:10 # 延迟 10 秒
排查:
# 检查网络延迟
ping 192.168.1.100
# 检查主节点负载
INFO stats
instantaneous_ops_per_sec:10000 # QPS 很高
# 检查带宽
iftop -i eth0
解决:
# 1. 增大复制缓冲区
repl-backlog-size 10mb
# 2. 禁用 TCP_NODELAY(减少网络包)
repl-disable-tcp-nodelay yes
# 3. 主节点使用更快的磁盘
# 使用 SSD 替代 HDD
问题 3:连接数耗尽
现象:
# 连接被拒绝
Error: Connection reset by peer
Error: Max number of clients reached
排查:
# 查看连接数
INFO clients
connected_clients:10000
maxclients:10000
解决:
# 1. 增加最大连接数
CONFIG SET maxclients 20000
# 2. 检查客户端连接泄漏
# 查看客户端列表
CLIENT LIST
# 3. 使用连接池
# Jedis 连接池配置
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(200);
config.setMaxIdle(50);
问题 4:CPU 飙升
现象:
# CPU 使用率高
top
PID USER PR NI VIRT RES %CPU
1234 redis 20 0 1.0g 500m 98.5
排查:
# 1. 查看慢查询
SLOWLOG GET 10
# 2. 查看正在执行的命令
CLIENT LIST
# 3. 监控命令执行
MONITOR
解决:
# 1. 优化慢查询
# 避免 KEYS、HGETALL、SMEMBERS
# 2. 使用 SCAN 代替 KEYS
SCAN 0 MATCH user:* COUNT 100
# 3. 限制 MONITOR 使用
# 仅在开发环境使用
# 4. 使用 Lua 脚本批量操作
# 减少网络往返
6.2 慢查询分析
慢查询配置:
# 慢查询阈值(微秒)
slowlog-log-slower-than 10000
# 慢查询日志长度
slowlog-max-len 128
慢查询分析:
# 查看慢查询
127.0.0.1:6379> SLOWLOG GET 10
1) 1) (integer) 14
2) (integer) 1704067200
3) (integer) 50000
4) "KEYS" "user:*"
# 分析慢查询类型
redis-cli SLOWLOG GET 100 | awk -F'"' '{print $2}' | sort | uniq -c | sort -rn
# 导出慢查询
redis-cli SLOWLOG GET 1000 > slowlog.txt
# 分析最慢的 10 个命令
cat slowlog.txt | grep -A 6 "integer)" | awk '/4)/ {cmd=$0; next} /3)/ {time=$2; print time, cmd}' | sort -rn | head -10
6.3 内存分析
内存使用分析:
# 查看内存详情
INFO memory
# 内存使用率
used_memory_rss / used_memory
# 内存碎片率
used_memory_rss / used_memory
# 查看内存分布
MEMORY STATS
# 分析 key 内存占用
MEMORY USAGE key
内存优化:
# 1. 开启内存碎片整理
activedefrag yes
active-defrag-ignore-bytes 100mb
active-defrag-threshold-lower 10
active-defrag-threshold-upper 100
# 2. 设置最大内存
CONFIG SET maxmemory 2gb
# 3. 设置淘汰策略
CONFIG SET maxmemory-policy allkeys-lru
# 4. 使用压缩编码
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
七、安全加固
7.1 访问控制
绑定 IP:
# 仅监听本地 IP
bind 127.0.0.1
# 监听多个 IP
bind 192.168.1.100 10.0.0.1
端口保护:
# 修改默认端口
port 6379
# 防火墙配置
iptables -A INPUT -p tcp --dport 6379 -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 6379 -j DROP
禁用危险命令:
# 重命名或禁用危险命令
rename-command CONFIG ""
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command SHUTDOWN "down"
7.2 身份认证
设置密码:
# 配置文件设置
requirepass your-strong-password
# 运行时设置
CONFIG SET requirepass your-strong-password
# 认证
AUTH your-strong-password
ACL 权限控制(Redis 6.0+):
# 创建用户
ACL SETUSER user1 on >password ~* +@all
# 创建只读用户
ACL SETUSER readonly on >password ~* +@read
# 创建限制用户
ACL SETUSER app_user on >password ~app:* +@read +@write -@dangerous
# 查看用户列表
ACL LIST
# 查看用户权限
ACL GETUSER user1
7.3 SSL/TLS 加密
生成证书:
# 生成 CA 证书
openssl genrsa -out ca.key 2048
openssl req -new -key ca.key -out ca.csr
openssl x509 -req -days 3650 -in ca.csr -signkey ca.key -out ca.crt
# 生成服务器证书
openssl genrsa -out redis.key 2048
openssl req -new -key redis.key -out redis.csr
openssl x509 -req -days 365 -in redis.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out redis.crt
配置 TLS:
# 启用 TLS
tls-port 6379
port 0
tls-cert-file /etc/redis/redis.crt
tls-key-file /etc/redis/redis.key
tls-ca-cert-file /etc/redis/ca.crt
tls-auth-clients no
tls-protocols TLSv1.2 TLSv1.3
客户端连接:
# redis-cli 使用 TLS
redis-cli --tls -h 192.168.1.100 -p 6379 \
--cert /etc/redis/redis.crt \
--key /etc/redis/redis.key \
--cacert /etc/redis/ca.crt
# Jedis 使用 TLS
JedisShardInfo shardInfo = new JedisShardInfo();
shardInfo.setSsl(true);
shardInfo.setSslSocketFactory(sslContext.getSocketFactory());
八、备份与恢复
8.1 RDB 备份
手动备份:
# 同步保存
SAVE
# 异步保存
BGSAVE
自动备份配置:
# 15 分钟内至少有 1 个 key 变化
save 900 1
# 5 分钟内至少有 10 个 key 变化
save 300 10
# 1 分钟内至少有 10000 个 key 变化
save 60 10000
# RDB 文件名
dbfilename dump.rdb
# RDB 文件目录
dir /var/lib/redis
备份脚本:
#!/bin/bash
# Redis 备份脚本
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR=/backup/redis
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=your-password
# 创建备份目录
mkdir -p $BACKUP_DIR
# 触发 BGSAVE
redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD BGSAVE
# 等待备份完成
while [ $(redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD LASTSAVE) -lt $(date +%s) ]; do
sleep 1
done
# 复制 RDB 文件
cp /var/lib/redis/dump.rdb $BACKUP_DIR/dump_$DATE.rdb
# 压缩备份
gzip $BACKUP_DIR/dump_$DATE.rdb
# 删除 7 天前的备份
find $BACKUP_DIR -name "dump_*.rdb.gz" -mtime +7 -delete
echo "Backup completed: dump_$DATE.rdb.gz"
8.2 AOF 备份
AOF 配置:
# 启用 AOF
appendonly yes
# AOF 文件名
appendfilename "appendonly.aof"
# 刷盘策略
appendfsync everysec
# AOF 重写配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# AOF 文件目录
dir /var/lib/redis
AOF 重写:
# 手动重写
BGREWRITEAOF
# 查看重写状态
INFO persistence
aof_rewrite_in_progress:0
aof_last_bgrewrite_status:ok
AOF 备份脚本:
#!/bin/bash
# AOF 备份脚本
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR=/backup/redis/aof
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=your-password
# 创建备份目录
mkdir -p $BACKUP_DIR
# 触发 AOF 重写
redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD BGREWRITEAOF
# 等待重写完成
while [ $(redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD INFO persistence | grep aof_rewrite_in_progress | cut -d: -f2) -eq 1 ]; do
sleep 1
done
# 复制 AOF 文件
cp /var/lib/redis/appendonly.aof $BACKUP_DIR/appendonly_$DATE.aof
# 压缩备份
gzip $BACKUP_DIR/appendonly_$DATE.aof
echo "AOF backup completed: appendonly_$DATE.aof.gz"
8.3 数据恢复
RDB 恢复:
# 1. 停止 Redis
redis-cli shutdown
# 2. 备份当前数据
cp /var/lib/redis/dump.rdb /var/lib/redis/dump.rdb.bak
# 3. 恢复 RDB 文件
cp /backup/redis/dump_20240101_120000.rdb.gz /var/lib/redis/dump.rdb.gz
gunzip /var/lib/redis/dump.rdb.gz
# 4. 启动 Redis
redis-server /etc/redis/redis.conf
AOF 恢复:
# 1. 停止 Redis
redis-cli shutdown
# 2. 备份当前数据
cp /var/lib/redis/appendonly.aof /var/lib/redis/appendonly.aof.bak
# 3. 恢复 AOF 文件
cp /backup/redis/aof/appendonly_20240101_120000.aof.gz /var/lib/redis/appendonly.aof.gz
gunzip /var/lib/redis/appendonly.aof.gz
# 4. 启动 Redis
redis-server /etc/redis/redis.conf
数据校验:
# 使用 redis-check-rdb 检查 RDB 文件
redis-check-rdb /var/lib/redis/dump.rdb
# 使用 redis-check-aof 检查 AOF 文件
redis-check-aof /var/lib/redis/appendonly.aof
# 修复 AOF 文件
redis-check-aof --fix /var/lib/redis/appendonly.aof
九、性能调优
9.1 内存优化
优化编码:
# Hash 使用 ziplist
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
# List 使用 quicklist
list-max-ziplist-size -2
# Set 使用 intset
set-max-intset-entries 512
# Sorted Set 使用 ziplist
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
内存分析:
# 查看内存统计
MEMORY STATS
# 分析 key 内存占用
MEMORY USAGE key
# 查找大 key
redis-cli --bigkeys
# 内存碎片整理
MEMORY PURGE
9.2 持久化优化
RDB 优化:
# 调整 save 规则,减少 RDB 生成频率
save 900 1
save 900 10
save 900 10000
# 使用无盘复制(适用于网络带宽大、磁盘慢)
repl-diskless-sync yes
AOF 优化:
# 调整刷盘策略
appendfsync everysec
# 关闭 AOF 重写期间的增量 fsync
no-appendfsync-on-rewrite no
# AOF 重写策略
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# AOF 使用 RDB 前缀(混合持久化)
aof-use-rdb-preamble yes
9.3 网络优化
TCP 优化:
# 启用 TCP_NODELAY(减少延迟)
repl-disable-tcp-nodelay no
# TCP keepalive
tcp-keepalive 300
客户端优化:
// Jedis 连接池配置
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(100);
config.setMaxIdle(50);
config.setMinIdle(10);
config.setMaxWaitMillis(10000);
config.setTestOnBorrow(true);
config.setTestOnReturn(false);
// 连接超时
config.setConnectionTimeout(2000);
config.setSoTimeout(2000);
9.4 操作系统优化
内核参数:
# /etc/sysctl.conf
# 最大文件描述符
fs.file-max = 1000000
# TCP 优化
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_max_tw_buckets = 5000
# 应用生效
sysctl -p
资源限制:
# /etc/security/limits.conf
redis soft nofile 65535
redis hard nofile 65535
redis soft nproc 65535
redis hard nproc 65535
十、常见面试题
10.1 运维题
Q1:Redis 如何进行容量规划?
答案:
-
数据量估算
- 预估数据条数
- 单条数据大小
- 总内存需求 = 数据条数 × 单条大小 × 剩余系数(1.5-2)
-
QPS 估算
- 预估请求量
- 读写比例
- 峰值系数(1.5-3)
-
实例选择
- 单机:QPS < 1000
- 主从:QPS 1000-10000
- 哨兵:QPS 10000-50000
- 集群:QPS > 50000
-
硬件配置
- CPU:根据 QPS 选择(通常 4-16 核)
- 内存:实际数据量的 2 倍
- 磁盘:SSD 推荐
- 网络:千兆网卡
Q2:Redis 如何进行故障切换?
答案:
主从模式:
# 手动切换
1. 将从节点提升为主节点
SLAVEOF NO ONE
2. 修改应用配置,连接新主节点
3. 其他从节点复制新主节点
SLAVEOF new-master-ip 6379
哨兵模式:
- 自动故障转移
- 无需人工介入
- 应用端使用哨兵获取主节点地址
集群模式:
- 自动故障转移
- 无需人工介入
- 客户端自动重定向
Q3:Redis 如何进行升级?
答案:
滚动升级:
# 1. 升级从节点
redis-cli -p 6380 shutdown
# 升级 Redis 版本
redis-server /etc/redis/new-redis.conf --port 6380
# 2. 升级主节点
redis-cli -p 6379 SHUTDOWN
redis-server /etc/redis/new-redis.conf --port 6379
# 3. 从节点复制新主节点
零停机升级(哨兵):
# 1. 升级哨兵节点
redis-sentinel /etc/redis/new-sentinel.conf --port 26379
# 2. 升级从节点
redis-cli -p 6380 shutdown
redis-server /etc/redis/new-redis.conf --port 6380
# 3. 升级主节点(哨兵自动故障转移)
# 手动触发主节点故障转移
redis-cli -p 26379 SENTINEL failover mymaster
10.2 架构题
Q4:如何设计 Redis 高可用架构?
答案:
推荐架构:
┌──────────────┐
│ Client │
└───────┬──────┘
↓
┌────────────────────────────┐
│ 哨兵集群 (3 节点) │
│ (Sentinel 1/2/3) │
└────────────────────────────┘
↓
┌────────────────────────────┐
│ Redis Cluster (3 主 3 从) │
│ Master 1: 7000, 7003 │
│ Master 2: 7001, 7004 │
│ Master 3: 7002, 7005 │
└────────────────────────────┘
高可用保障:
- 多哨兵部署:至少 3 个,奇数个
- 集群分片:3 主 3 从,每个主节点配置 1 个从节点
- 跨机房部署:主从节点分布在不同机房
- 监控告警:实时监控集群状态
- 备份策略:定时备份,异地存储
Q5:如何设计 Redis 多活架构?
答案:
架构设计:
机房 A 机房 B
┌────────────┐ ┌────────────┐
│ Redis M1 │◄────────►│ Redis M2 │
│ (Master) │ 双向复制 │ (Master) │
└────────────┘ └────────────┘
↓ ↓
┌────────────┐ ┌────────────┐
│ Redis S1 │ │ Redis S2 │
│ (Slave) │ │ (Slave) │
└────────────┘ └────────────┘
↓ ↓
┌────────────┐ ┌────────────┐
│ 应用 A │ │ 应用 B │
└────────────┘ └────────────┘
技术方案:
-
数据同步
- 主从双向复制
- 冲突解决机制(时间戳、向量时钟)
- 最终一致性
-
流量调度
- 就近访问
- 故障切换
- 灰度发布
-
数据分片
- 按地域分片
- 按用户 ID 分片
- 避免跨机房访问
十一、最佳实践
11.1 配置规范
生产环境配置:
# 网络配置
bind 0.0.0.0
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
# 内存配置
maxmemory 2gb
maxmemory-policy allkeys-lru
maxmemory-samples 5
# 持久化配置
save 900 1
save 300 10
save 60 10000
appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes
# 复制配置
repl-diskless-sync yes
repl-diskless-sync-delay 5
repl-ping-slave-period 10
repl-timeout 60
repl-disable-tcp-nodelay no
repl-backlog-size 10mb
repl-backlog-ttl 3600
# 安全配置
requirepass your-strong-password
rename-command CONFIG ""
rename-command FLUSHDB ""
rename-command FLUSHALL ""
# 日志配置
loglevel notice
logfile /var/log/redis/redis.log
syslog-enabled yes
# 慢查询配置
slowlog-log-slower-than 10000
slowlog-max-len 128
# 客户端配置
maxclients 10000
# 集群配置(如启用)
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
11.2 运维规范
日常运维:
-
监控巡检
- 每日检查内存使用率
- 每日检查慢查询日志
- 每日检查主从同步状态
-
备份验证
- 每周备份一次
- 每月恢复测试一次
- 异地存储
-
容量规划
- 每月评估数据增长
- 提前扩容
- 制定扩容方案
-
安全审计
- 定期检查日志
- 定期更新密码
- 定期漏洞扫描
应急响应:
-
故障响应
- 监控告警
- 快速定位
- 及时恢复
-
数据恢复
- 从备份恢复
- 主从切换
- 故障转移
-
根因分析
- 故障复盘
- 优化改进
- 文档记录
参考文档:
- Redis 官方文档
- Redis 运维指南
- 《Redis 开发与运维》
- 《Redis 实战》