跳到主要内容

运维与架构

一、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 能力< 1K1-10K1-10K> 50K

面试题:如何选择 Redis 部署架构?

答案:

  1. 单机模式

    • 开发/测试环境
    • 数据量小(< 1 GB)
    • QPS < 1000
  2. 主从复制

    • 读多写少
    • 需要数据备份
    • QPS 1000-10000
  3. 哨兵模式

    • 需要高可用
    • 不能容忍服务中断
    • QPS 10000-50000
  4. 集群模式

    • 大规模应用
    • 需要水平扩展
    • 数据量大(> 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

部分重同步条件:

  1. 从节点记录的主节点 runid 与当前主节点一致
  2. 复制偏移量在复制缓冲区范围内

配置:

# 复制积压缓冲区大小(根据网络状况调整)
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 哨兵工作原理

三个监控机制:

  1. 主观下线(SDOWN)
# 单个哨兵认为主节点下线
条件:down-after-milliseconds 内无响应
  1. 客观下线(ODOWN)
# 多数哨兵认为主节点下线
条件:quorum 个哨兵认为主节点下线
sentinel monitor mymaster 192.168.1.100 6379 2 # quorum = 2
  1. 故障转移
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

面试题:哨兵模式如何保证高可用?

答案:

  1. 多哨兵部署

    • 至少 3 个节点
    • 避免单点故障
  2. quorum 机制

    • 需要多数哨兵同意
    • 避免误判
  3. 自动故障转移

    • 主节点故障时自动选举新主节点
    • 无需人工干预
  4. 客户端通知

    • Pub/Sub 机制通知客户端
    • 自动更新连接地址
  5. 配置持久化

    • 哨兵配置持久化到磁盘
    • 重启后恢复状态

四、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. 数据量估算

    • 预估数据条数
    • 单条数据大小
    • 总内存需求 = 数据条数 × 单条大小 × 剩余系数(1.5-2)
  2. QPS 估算

    • 预估请求量
    • 读写比例
    • 峰值系数(1.5-3)
  3. 实例选择

    • 单机:QPS < 1000
    • 主从:QPS 1000-10000
    • 哨兵:QPS 10000-50000
    • 集群:QPS > 50000
  4. 硬件配置

    • 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 │
└────────────────────────────┘

高可用保障:

  1. 多哨兵部署:至少 3 个,奇数个
  2. 集群分片:3 主 3 从,每个主节点配置 1 个从节点
  3. 跨机房部署:主从节点分布在不同机房
  4. 监控告警:实时监控集群状态
  5. 备份策略:定时备份,异地存储

Q5:如何设计 Redis 多活架构?

答案:

架构设计:

  机房 A                    机房 B
┌────────────┐ ┌────────────┐
│ Redis M1 │◄────────►│ Redis M2 │
│ (Master) │ 双向复制 │ (Master) │
└────────────┘ └────────────┘
↓ ↓
┌────────────┐ ┌────────────┐
│ Redis S1 │ │ Redis S2 │
│ (Slave) │ │ (Slave) │
└────────────┘ └────────────┘
↓ ↓
┌────────────┐ ┌────────────┐
│ 应用 A │ │ 应用 B │
└────────────┘ └────────────┘

技术方案:

  1. 数据同步

    • 主从双向复制
    • 冲突解决机制(时间戳、向量时钟)
    • 最终一致性
  2. 流量调度

    • 就近访问
    • 故障切换
    • 灰度发布
  3. 数据分片

    • 按地域分片
    • 按用户 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 运维规范

日常运维:

  1. 监控巡检

    • 每日检查内存使用率
    • 每日检查慢查询日志
    • 每日检查主从同步状态
  2. 备份验证

    • 每周备份一次
    • 每月恢复测试一次
    • 异地存储
  3. 容量规划

    • 每月评估数据增长
    • 提前扩容
    • 制定扩容方案
  4. 安全审计

    • 定期检查日志
    • 定期更新密码
    • 定期漏洞扫描

应急响应:

  1. 故障响应

    • 监控告警
    • 快速定位
    • 及时恢复
  2. 数据恢复

    • 从备份恢复
    • 主从切换
    • 故障转移
  3. 根因分析

    • 故障复盘
    • 优化改进
    • 文档记录

参考文档: