← 返回文章列表

Redis底层原理(九):生产实践与最佳实践

2020-04-03·8 分钟阅读

前言

经过前八章的学习,我们已经深入理解了 Redis 的核心原理。本章将聚焦生产实践,总结 Redis 在性能优化、内存管理、监控告警、问题排查等方面的最佳实践,帮助读者构建稳定高效的 Redis 服务。

一、性能优化

1.1 网络优化

┌──────────────────────────────────────────────────────────────┐
│                    网络优化策略                               │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  1. Pipeline 批量操作                                       │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  普通模式:每个命令一次网络往返                          ││
│  │  ┌─────────────────────────────────────────────────┐   ││
│  │  │ Client ──SET──► Server                          │   ││
│  │  │ Client ◄──OK─── Server                          │   ││
│  │  │ Client ──GET──► Server                          │   ││
│  │  │ Client ◄──val── Server                          │   ││
│  │  │ ... 10 个命令 = 20 次网络往返                    │   ││
│  │  └─────────────────────────────────────────────────┘   ││
│  │                                                         ││
│  │  Pipeline 模式:批量发送,一次往返                      ││
│  │  ┌─────────────────────────────────────────────────┐   ││
│  │  │ Client ──SET/GET/SET/GET...──► Server           │   ││
│  │  │ Client ◄──OK/val/OK/val...─── Server            │   ││
│  │  │ ... 10 个命令 = 2 次网络往返                     │   ││
│  │  └─────────────────────────────────────────────────┘   ││
│  │                                                         ││
│  │  // Java 示例                                           ││
│  │  Pipeline p = jedis.pipelined();                       ││
│  │  for (int i = 0; i < 1000; i++) {                      ││
│  │      p.set("key" + i, "value" + i);                    ││
│  │  }                                                     ││
│  │  List<Object> results = p.syncAndReturnAll();          ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  2. 连接池配置                                               │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  # Jedis 连接池配置示例                                 ││
│  │  JedisPoolConfig config = new JedisPoolConfig();       ││
│  │  config.setMaxTotal(200);        // 最大连接数          ││
│  │  config.setMaxIdle(50);          // 最大空闲连接        ││
│  │  config.setMinIdle(10);          // 最小空闲连接        ││
│  │  config.setMaxWaitMillis(3000);  // 获取连接超时        ││
│  │  config.setTestWhileIdle(true);  // 空闲时检测          ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  3. 批量命令                                                 │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  # 使用 MSET/MGET 替代多次 SET/GET                      ││
│  │  MSET key1 val1 key2 val2 key3 val3                    ││
│  │  MGET key1 key2 key3                                    ││
│  │                                                         ││
│  │  # 使用 Lua 脚本封装复杂操作                            ││
│  │  EVAL "local v = redis.call('GET', KEYS[1]);           ││
│  │        redis.call('SET', KEYS[2], v);                  ││
│  │        return v;" 2 key1 key2                          ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
└──────────────────────────────────────────────────────────────┘

1.2 命令优化

┌──────────────────────────────────────────────────────────────┐
│                    命令使用优化                               │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  1. 避免慢命令                                               │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  高风险命令:                                            ││
│  │  ┌───────────────┬───────────────────────────────────┐ ││
│  │  │ KEYS *        │ 全量扫描,生产环境禁用            │ ││
│  │  │ HGETALL       │ Hash 过大时阻塞                   │ ││
│  │  │ SMEMBERS      │ Set 过大时阻塞                    │ ││
│  │  │ LRANGE 0 -1   │ List 过大时阻塞                   │ ││
│  │  │ SORT          │ 复杂排序操作                      │ ││
│  │  └───────────────┴───────────────────────────────────┘ ││
│  │                                                         ││
│  │  替代方案:                                              ││
│  │  ┌───────────────┬───────────────────────────────────┐ ││
│  │  │ KEYS *        │ SCAN 命令分批扫描                 │ ││
│  │  │ HGETALL       │ HSCAN 分批获取                    │ ││
│  │  │ SMEMBERS      │ SSCAN 分批获取                    │ ││
│  │  │ LRANGE        │ LRANGE 分批获取                   │ ││
│  │  │ SORT          │ 使用 Sorted Set                   │ ││
│  │  └───────────────┴───────────────────────────────────┘ ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  2. SCAN 命令使用                                            │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  # 游标遍历,不阻塞                                      ││
│  │  SCAN 0 MATCH user:* COUNT 100                         ││
│  │  # 返回:下一个游标 + 当前批次键                         ││
│  │                                                         ││
│  │  # Java 示例                                            ││
│  │  String cursor = "0";                                   ││
│  │  do {                                                   ││
│  │      ScanResult<String> result = jedis.scan(           ││
│  │          cursor, new ScanParams().match("user:*")      ││
│  │                        .count(100));                   ││
│  │      cursor = result.getCursor();                      ││
│  │      for (String key : result.getResult()) {           ││
│  │          // 处理 key                                    ││
│  │      }                                                  ││
│  │  } while (!cursor.equals("0"));                        ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  3. 合理设置过期时间                                         │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  # 避免同一时间大量过期                                  ││
│  │  # 错误:所有 key 都在同一时间过期                       ││
│  │  SET key1 val1 EX 3600                                  ││
│  │  SET key2 val2 EX 3600                                  ││
│  │  SET key3 val3 EX 3600                                  ││
│  │                                                         ││
│  │  # 正确:添加随机偏移                                    ││
│  │  SET key1 val1 EX 3600                                  ││
│  │  SET key2 val2 EX 3650                                  ││
│  │  SET key3 val3 EX 3700                                  ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
└──────────────────────────────────────────────────────────────┘

1.3 数据结构优化

┌──────────────────────────────────────────────────────────────┐
│                    数据结构选择优化                           │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  1. 选择合适的数据类型                                       │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  场景                    │ 推荐类型     │ 原因          ││
│  │  ────────────────────────┼──────────────┼─────────────  ││
│  │  简单键值对              │ String       │ 最简单高效    ││
│  │  计数器/自增ID           │ String (INT) │ 原子操作      ││
│  │  对象属性                │ Hash         │ 字段级别操作  ││
│  │  列表/队列               │ List         │ 有序可重复    ││
│  │  去重集合                │ Set          │ 无序不重复    ││
│  │  排行榜                  │ ZSet         │ 有序不重复    ││
│  │  地理位置                │ Geo          │ 位置计算      ││
│  │  消息队列                │ Stream       │ 持久化消费组  ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  2. 小对象优化                                               │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  # Hash 小对象优化                                       ││
│  │  # 多个字段存储在一个 Hash 中,节省内存                  ││
│  │                                                         ││
│  │  # 不推荐:每个属性单独存储                              ││
│  │  SET user:1001:name "张三"                              ││
│  │  SET user:1001:age "25"                                 ││
│  │  SET user:1001:city "北京"                              ││
│  │                                                         ││
│  │  # 推荐:使用 Hash 存储                                  ││
│  │  HSET user:1001 name "张三" age 25 city "北京"          ││
│  │                                                         ││
│  │  # 内存对比(假设 10000 个用户)                         ││
│  │  独立键:10000 * 3 * 16字节 ≈ 480KB                     ││
│  │  Hash:  10000 * 1 * 80字节 ≈ 800KB(更少键)           ││
│  │  实际:Hash 编码优化后更省内存                           ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  3. 大键拆分                                                 │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  大键问题:                                              ││
│  │  • 内存不均匀                                           ││
│  │  • 操作阻塞                                             ││
│  │  • 迁移困难                                             ││
│  │                                                         ││
│  │  拆分策略:                                              ││
│  │  ┌───────────────────────────────────────────────────┐ ││
│  │  │ Hash 超过 5000 字段:按业务分组拆分               │ ││
│  │  │ user:1001:basic    → name, age                   │ ││
│  │  │ user:1001:contact  → phone, email                │ ││
│  │  │ user:1001:address  → city, street                │ ││
│  │  │                                                   │ ││
│  │  │ List 超过 10000 元素:按时间或ID拆分              │ ││
│  │  │ logs:20240101                                     │ ││
│  │  │ logs:20240102                                     │ ││
│  │  │ logs:20240103                                     │ ││
│  │  └───────────────────────────────────────────────────┘ ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
└──────────────────────────────────────────────────────────────┘

二、内存优化

2.1 内存分析

┌──────────────────────────────────────────────────────────────┐
│                    内存分析工具                               │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  1. INFO 命令                                                │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  # 查看内存信息                                          ││
│  │  INFO memory                                            ││
│  │                                                         ││
│  │  关键指标:                                              ││
│  │  ┌───────────────────────────────────────────────────┐ ││
│  │  │ used_memory:          已使用内存                  │ ││
│  │  │ used_memory_rss:      系统分配内存                │ ││
│  │  │ used_memory_peak:     历史最大内存                │ ││
│  │  │ mem_fragmentation_ratio: 内存碎片率               │ ││
│  │  │ mem_allocator:        内存分配器                  │ ││
│  │  └───────────────────────────────────────────────────┘ ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  2. MEMORY 命令                                              │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  # 查看单个键的内存占用                                  ││
│  │  MEMORY USAGE key                                       ││
│  │                                                         ││
│  │  # 内存诊断                                              ││
│  │  MEMORY DOCTOR                                          ││
│  │                                                         ││
│  │  # 内存分配统计                                          ││
│  │  MEMORY STATS                                           ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  3. 分析工具                                                 │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  # Redis RDB Tools                                      ││
│  │  rdb --command memory dump.rdb > memory_report.csv      ││
│  │                                                         ││
│  │  # Redis Memory Analyzer                                ││
│  │  redis-memory-analyzer -h localhost -p 6379             ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
└──────────────────────────────────────────────────────────────┘

2.2 内存优化策略

┌──────────────────────────────────────────────────────────────┐
│                    内存优化配置                               │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  1. 编码优化                                                 │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  # redis.conf                                           ││
│  │                                                         ││
│  │  # Hash 优化阈值                                         ││
│  │  hash-max-ziplist-entries 512                          ││
│  │  hash-max-ziplist-value 64                             ││
│  │                                                         ││
│  │  # List 优化                                             ││
│  │  list-max-ziplist-size -2    # 每个节点 8KB            ││
│  │  list-compress-depth 1       # 压缩中间节点            ││
│  │                                                         ││
│  │  # Set 优化                                              ││
│  │  set-max-intset-entries 512                            ││
│  │                                                         ││
│  │  # ZSet 优化                                             ││
│  │  zset-max-ziplist-entries 128                          ││
│  │  zset-max-ziplist-value 64                             ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  2. 内存淘汰策略                                             │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  # 设置最大内存                                          ││
│  │  maxmemory 4gb                                          ││
│  │                                                         ││
│  │  # 选择淘汰策略                                          ││
│  │  # volatile-lru: 从设置了过期时间的键中淘汰 LRU         ││
│  │  # allkeys-lru: 从所有键中淘汰 LRU                      ││
│  │  # volatile-lfu: 从设置了过期时间的键中淘汰 LFU         ││
│  │  # allkeys-lfu: 从所有键中淘汰 LFU                      ││
│  │  # volatile-random: 从设置了过期时间的键中随机淘汰      ││
│  │  # allkeys-random: 从所有键中随机淘汰                   ││
│  │  # volatile-ttl: 淘汰 TTL 最小的键                      ││
│  │  # noeviction: 不淘汰,内存满时报错                     ││
│  │                                                         ││
│  │  maxmemory-policy allkeys-lru                          ││
│  │                                                         ││
│  │  # LRU/LFU 采样数量                                      ││
│  │  maxmemory-samples 5                                    ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  3. 内存碎片整理                                             │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  # 开启主动碎片整理                                      ││
│  │  activedefrag yes                                       ││
│  │                                                         ││
│  │  # 碎片整理阈值                                          ││
│  │  active-defrag-ignore-bytes 100mb  # 忽略小于100MB      ││
│  │  active-defrag-threshold-lower 10  # 碎片率>10%开始     ││
│  │  active-defrag-threshold-upper 100 # 碎片率>100%强制    ││
│  │                                                         ││
│  │  # 整理速度控制                                          ││
│  │  active-defrag-cycle-min 1    # 最小CPU占用1%           ││
│  │  active-defrag-cycle-max 25   # 最大CPU占用25%          ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
└──────────────────────────────────────────────────────────────┘

三、监控告警

3.1 关键监控指标

┌──────────────────────────────────────────────────────────────┐
│                    关键监控指标                               │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  1. 基础指标                                                 │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  类别          │ 指标                    │ 告警阈值     ││
│  │  ──────────────┼─────────────────────────┼───────────── ││
│  │  内存          │ used_memory             │ > 80%        ││
│  │                │ mem_fragmentation_ratio │ > 1.5        ││
│  │  ──────────────┼─────────────────────────┼───────────── ││
│  │  连接          │ connected_clients       │ > 5000       ││
│  │                │ blocked_clients         │ > 0          ││
│  │  ──────────────┼─────────────────────────┼───────────── ││
│  │  命令          │ instantaneous_ops_per_sec│ > 50000     ││
│  │                │ slowlog_len             │ > 0          ││
│  │  ──────────────┼─────────────────────────┼───────────── ││
│  │  持久化        │ rdb_last_bgsave_status  │ err          ││
│  │                │ aof_last_bgrewrite_status│ err         ││
│  │                │ aof_delayed_fsync       │ > 0          ││
│  │  ──────────────┼─────────────────────────┼───────────── ││
│  │  复制          │ master_link_status      │ down         ││
│  │                │ slave_read_only         │ no           ││
│  │  ──────────────┼─────────────────────────┼───────────── ││
│  │  集群          │ cluster_state           │ fail         ││
│  │                │ cluster_slots_assigned  │ < 16384      ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  2. 监控命令                                                 │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  # 实时监控                                              ││
│  │  redis-cli --stat                                       ││
│  │                                                         ││
│  │  # 慢查询日志                                            ││
│  │  SLOWLOG GET 10                                         ││
│  │                                                         ││
│  │  # 客户端列表                                            ││
│  │  CLIENT LIST                                            ││
│  │                                                         ││
│  │  # 集群状态                                              ││
│  │  CLUSTER INFO                                           ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
└──────────────────────────────────────────────────────────────┘

3.2 监控方案

┌──────────────────────────────────────────────────────────────┐
│                    监控方案推荐                               │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  1. Prometheus + Grafana                                     │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  架构:                                                  ││
│  │  ┌───────────┐    ┌───────────┐    ┌───────────┐       ││
│  │  │ Redis     │───►│ Exporter  │───►│ Prometheus│       ││
│  │  │ Instance  │    │           │    │           │       ││
│  │  └───────────┘    └───────────┘    └─────┬─────┘       ││
│  │                                          │              ││
│  │                                          ▼              ││
│  │                                   ┌───────────┐         ││
│  │                                   │ Grafana   │         ││
│  │                                   │ Dashboard │         ││
│  │                                   └───────────┘         ││
│  │                                                         ││
│  │  redis_exporter 启动:                                   ││
│  │  redis_exporter --redis.addr=redis://localhost:6379     ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  2. Redis Insight                                            │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  官方可视化工具:                                        ││
│  │  • 实时监控                                              ││
│  │  • 内存分析                                              ││
│  │  • 慢查询分析                                            ││
│  │  • 命令执行                                              ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  3. 自定义监控脚本                                           │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  #!/bin/bash                                            ││
│  │  # 检查 Redis 状态                                       ││
│  │                                                         ││
│  │  REDIS_CLI="redis-cli -h localhost -p 6379"             ││
│  │                                                         ││
│  │  # 内存使用率                                            ││
│  │  used_memory=$($REDIS_CLI INFO memory |                 ││
│  │                 grep used_memory: | cut -d: -f2)        ││
│  │  max_memory=$($REDIS_CLI CONFIG GET maxmemory |         ││
│  │                tail -1)                                 ││
│  │                                                         ││
│  │  if [ "$max_memory" -gt 0 ]; then                       ││
│  │    usage=$((used_memory * 100 / max_memory))            ││
│  │    if [ $usage -gt 80 ]; then                           ││
│  │      echo "WARNING: Memory usage is ${usage}%"          ││
│  │    fi                                                   ││
│  │  fi                                                     ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
└──────────────────────────────────────────────────────────────┘

四、常见问题排查

4.1 性能问题排查

┌──────────────────────────────────────────────────────────────┐
│                    性能问题排查指南                           │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  问题 1: 响应延迟高                                          │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  排查步骤:                                              ││
│  │  1. 检查慢查询日志:SLOWLOG GET 10                      ││
│  │  2. 检查大键:redis-cli --bigkeys                       ││
│  │  3. 检查内存碎片:INFO memory                           ││
│  │  4. 检查持久化状态:INFO persistence                    ││
│  │  5. 检查客户端连接:CLIENT LIST                         ││
│  │                                                         ││
│  │  常见原因:                                              ││
│  │  • 执行了慢命令(KEYS, SORT 等)                        ││
│  │  • 大键操作                                              ││
│  │  • 内存不足触发淘汰                                      ││
│  │  • 持久化阻塞                                            ││
│  │  • 客户端输出缓冲区积压                                  ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  问题 2: CPU 使用率高                                        │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  排查步骤:                                              ││
│  │  1. 检查命令执行频率:INFO stats                        ││
│  │  2. 检查是否在 rehash:INFO stats                       ││
│  │  3. 检查是否在内存整理:INFO memory                     ││
│  │  4. 检查 Lua 脚本执行                                   ││
│  │                                                         ││
│  │  解决方案:                                              ││
│  │  • 优化慢命令                                            ││
│  │  • 控制 rehash 频率                                      ││
│  │  • 调整碎片整理参数                                      ││
│  │  • 优化 Lua 脚本                                        ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  问题 3: 内存使用异常                                        │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  排查步骤:                                              ││
│  │  1. 分析内存分布:MEMORY STATS                          ││
│  │  2. 查找内存泄漏键:redis-cli --memkeys                 ││
│  │  3. 检查客户端缓冲区:CLIENT LIST                       ││
│  │  4. 检查复制缓冲区:INFO replication                    ││
│  │                                                         ││
│  │  常见原因:                                              ││
│  │  • 客户端输出缓冲区过大                                  ││
│  │  • 复制积压缓冲区过大                                    ││
│  │  • 内存碎片率高                                          ││
│  │  • 键未设置过期时间                                      ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
└──────────────────────────────────────────────────────────────┘

4.2 故障处理

┌──────────────────────────────────────────────────────────────┐
│                    故障处理指南                               │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  故障 1: Redis 无法启动                                      │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  常见原因及解决:                                        ││
│  │  1. 端口被占用:netstat -tlnp | grep 6379               ││
│  │  2. 配置文件错误:检查 redis.conf 语法                  ││
│  │  3. RDB/AOF 文件损坏:                                  ││
│  │     - RDB: redis-check-rdb dump.rdb                     ││
│  │     - AOF: redis-check-aof --fix appendonly.aof         ││
│  │  4. 内存不足:检查系统可用内存                          ││
│  │  5. 权限问题:检查数据目录权限                          ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  故障 2: 主从复制断开                                        │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  排查步骤:                                              ││
│  │  1. 检查网络连通性                                      ││
│  │  2. 检查认证配置:masterauth 是否正确                   ││
│  │  3. 检查复制状态:INFO replication                      ││
│  │  4. 检查超时配置:repl-timeout                          ││
│  │  5. 检查积压缓冲区:repl-backlog-size                   ││
│  │                                                         ││
│  │  解决方案:                                              ││
│  │  • 调整超时时间                                          ││
│  │  • 增大积压缓冲区                                        ││
│  │  • 检查网络带宽                                          ││
│  │  • 使用无盘复制                                          ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  故障 3: 集群节点下线                                        │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  排查步骤:                                              │
│  │  1. 检查节点状态:CLUSTER NODES                         ││
│  │  2. 检查网络连通性                                      ││
│  │  3. 检查集群端口:16379 端口是否开放                    ││
│  │  4. 检查配置纪元:CLUSTER INFO                          ││
│  │                                                         ││
│  │  恢复步骤:                                              ││
│  │  1. 重启下线节点                                        ││
│  │  2. 检查是否自动恢复                                    ││
│  │  3. 手动触发故障转移:CLUSTER FAILOVER                  ││
│  │  4. 必要时重新加入集群                                  ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
└──────────────────────────────────────────────────────────────┘

五、安全配置

5.1 访问控制

# redis.conf 安全配置

# 绑定地址(限制访问来源)
bind 127.0.0.1 10.0.0.1

# 保护模式
protected-mode yes

# 端口(非默认端口更安全)
port 6379

# 认证密码
requirepass "your-strong-password-here"

# 重命名危险命令
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command KEYS ""
rename-command CONFIG ""

# 禁用危险命令
# rename-command DEBUG ""

5.2 网络安全

┌──────────────────────────────────────────────────────────────┐
│                    网络安全策略                               │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  1. 网络隔离                                                 │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  • 使用内网 IP                                          ││
│  │  • 配置防火墙规则                                        ││
│  │  • 使用 VPN 或专线                                       ││
│  │  • 避免暴露公网                                          ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  2. TLS 加密(Redis 6.0+)                                   │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  # redis.conf                                           ││
│  │  tls-port 6380                                          ││
│  │  tls-cert-file redis.crt                                ││
│  │  tls-key-file redis.key                                 ││
│  │  tls-ca-cert-file ca.crt                                ││
│  │  tls-auth-clients optional                              ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  3. ACL 控制(Redis 6.0+)                                   │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  # 创建用户                                              ││
│  │  ACL SETUSER app_user on >password ~* +@read +@write    ││
│  │                                                         ││
│  │  # 只读用户                                              ││
│  │  ACL SETUSER readonly on >password ~* +@read            ││
│  │                                                         │
│  │  # 查看用户列表                                          ││
│  │  ACL LIST                                               ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
└──────────────────────────────────────────────────────────────┘

六、备份与恢复

6.1 备份策略

┌──────────────────────────────────────────────────────────────┐
│                    备份策略                                   │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  1. RDB 备份                                                 │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  # 手动备份                                              ││
│  │  redis-cli BGSAVE                                       ││
│  │  cp dump.rdb dump.rdb.$(date +%Y%m%d)                   ││
│  │                                                         ││
│  │  # 自动备份脚本                                          ││
│  │  #!/bin/bash                                            ││
│  │  BACKUP_DIR="/backup/redis"                             ││
│  │  REDIS_CLI="redis-cli -h localhost -p 6379"             ││
│  │                                                         ││
│  │  # 触发 BGSAVE                                           ││
│  │  $REDIS_CLI BGSAVE                                      ││
│  │                                                         ││
│  │  # 等待完成                                              ││
│  │  while [ $($REDIS_CLI LASTSAVE) -eq $last_save ]; do    ││
│  │    sleep 1                                              ││
│  │  done                                                   ││
│  │                                                         ││
│  │  # 复制备份文件                                          ││
│  │  cp /var/lib/redis/dump.rdb \                           ││
│  │     $BACKUP_DIR/dump.rdb.$(date +%Y%m%d_%H%M%S)         ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  2. AOF 备份                                                 │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  # 复制 AOF 文件                                         ││
│  │  cp appendonly.aof appendonly.aof.$(date +%Y%m%d)       ││
│  │                                                         ││
│  │  # 定期重写压缩                                          ││
│  │  redis-cli BGREWRITEAOF                                 ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  3. 备份保留策略                                             │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  • 每日备份,保留 7 天                                   ││
│  │  • 每周备份,保留 4 周                                   ││
│  │  • 每月备份,保留 12 月                                  ││
│  │  • 异地备份(容灾)                                      ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
└──────────────────────────────────────────────────────────────┘

6.2 恢复流程

┌──────────────────────────────────────────────────────────────┐
│                    恢复流程                                   │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  1. RDB 恢复                                                 │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  # 1. 停止 Redis                                        ││
│  │  redis-cli SHUTDOWN NOSAVE                              ││
│  │                                                         ││
│  │  # 2. 替换 RDB 文件                                      ││
│  │  cp dump.rdb.backup dump.rdb                            ││
│  │                                                         ││
│  │  # 3. 启动 Redis                                        ││
│  │  redis-server redis.conf                                ││
│  │                                                         ││
│  │  # 4. 验证数据                                          ││
│  │  redis-cli DBSIZE                                       ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
│  2. AOF 恢复                                                 │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                                                         ││
│  │  # 1. 停止 Redis                                        ││
│  │  redis-cli SHUTDOWN NOSAVE                              ││
│  │                                                         ││
│  │  # 2. 检查 AOF 文件                                      ││
│  │  redis-check-aof appendonly.aof                         ││
│  │                                                         ││
│  │  # 3. 修复损坏(如有)                                   ││
│  │  redis-check-aof --fix appendonly.aof                   ││
│  │                                                         ││
│  │  # 4. 启动 Redis                                        ││
│  │  redis-server redis.conf                                ││
│  │                                                         ││
│  └─────────────────────────────────────────────────────────┘│
│                                                              │
└──────────────────────────────────────────────────────────────┘

七、总结

本章总结了 Redis 生产实践的关键要点:

领域关键点
性能优化Pipeline、批量命令、合理数据结构
内存优化编码配置、淘汰策略、碎片整理
监控告警关键指标、Prometheus+Grafana
故障排查慢查询、大键、内存分析
安全配置认证、ACL、网络隔离
备份恢复RDB/AOF 备份、定期演练

系列总结

通过九篇文章,我们系统学习了 Redis 的核心原理:

  1. 概述与架构:理解 Redis 的整体设计哲学
  2. 基础数据结构:SDS、链表、字典的实现原理
  3. 核心数据结构:跳跃表、整数集合、压缩列表
  4. 对象系统:类型编码、内存优化机制
  5. 持久化:RDB、AOF、混合持久化
  6. 事件驱动:文件事件、时间事件、事件循环
  7. 复制与哨兵:主从复制、哨兵机制
  8. 集群原理:数据分片、故障转移
  9. 生产实践:性能优化、监控运维

掌握这些原理,将帮助你在生产环境中更好地使用和运维 Redis。

参考资料

分享: