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 的核心原理:
- 概述与架构:理解 Redis 的整体设计哲学
- 基础数据结构:SDS、链表、字典的实现原理
- 核心数据结构:跳跃表、整数集合、压缩列表
- 对象系统:类型编码、内存优化机制
- 持久化:RDB、AOF、混合持久化
- 事件驱动:文件事件、时间事件、事件循环
- 复制与哨兵:主从复制、哨兵机制
- 集群原理:数据分片、故障转移
- 生产实践:性能优化、监控运维
掌握这些原理,将帮助你在生产环境中更好地使用和运维 Redis。
参考资料
- Redis Documentation
- Redis Best Practices
- 《Redis设计与实现》- 黄健宏
- 《Redis开发与运维》- 付磊、张益军
相关文章
Milvus底层原理(十四):内存与缓存管理
2026-03-10·5 分钟阅读
深入理解 Milvus 的内存与缓存管理机制,掌握内存池设计、Chunk Cache、查询缓存策略和内存优化技巧,提升系统性能和资源利用率。
Milvus底层原理(十五):生产环境实践
2026-03-10·5 分钟阅读
综合运用 Milvus 底层原理知识,掌握生产环境部署、性能调优、监控告警、容量规划和故障排查的实战技能,构建稳定高效的向量检索系统。
从零到一实现 nano-agent(十二):生产级实践
2025-02-03·5 分钟阅读
总结生产级 AI 编程助手的实践经验,包括错误恢复、可观测性、性能优化和部署策略,为项目画上圆满句号。