本文是 Redis 运维实战手册,涵盖从基础概念到集群部署、从性能调优到故障排查的全流程。适合 DBA、后端开发和 SRE 日常参考。


一、Redis 基础概览

1.1 Redis 是什么

Redis(Remote Dictionary Server)是一个开源的、基于内存的高性能键值存储系统。它支持多种数据结构,常被用作数据库、缓存和消息中间件。

核心特性:

  • 高性能:纯内存操作,单线程模型避免锁竞争,QPS 可达 10 万+

  • 丰富的数据结构:String、Hash、List、Set、Sorted Set、Stream、HyperLogLog、Bitmap、Geospatial

  • 持久化:支持 RDB 快照和 AOF 日志两种方式

  • 高可用:主从复制、Sentinel 哨兵、Redis Cluster 集群

  • 原子操作:单线程保证命令原子性,支持 Lua 脚本和事务

1.2 数据类型速览

  • String:最基础的类型,可存储字符串、整数、浮点数,最大 512MB

  • Hash:键值对集合,适合存储对象(如用户信息)

  • List:有序链表,支持头尾操作,适合消息队列

  • Set:无序去重集合,支持交并差运算

  • Sorted Set (ZSet):带分数的有序集合,适合排行榜

  • Stream:日志型数据结构,支持消费者组,替代 Kafka 轻量场景

  • HyperLogLog:基数统计,占用固定 12KB 内存

  • Bitmap:位操作,适合签到、在线状态等场景

  • Geospatial:地理位置,支持距离计算和范围查询

1.3 Redis 7.x 新特性

  • Redis Functions:替代 EVAL 的服务端脚本方案,支持持久化

  • Multi-part AOF:AOF 文件拆分为多个部分,避免 rewrite 时的磁盘峰值

  • Shared Pub/Sub:集群模式下的 Pub/Sub 改进

  • ACL v2:更细粒度的访问控制


二、安装部署

2.1 源码编译安装(推荐)

# 安装依赖
sudo apt-get update && sudo apt-get install -y build-essential tcl pkg-config

# 下载并编译
cd /usr/local/src
wget https://download.redis.io/releases/redis-7.2.5.tar.gz
tar xzf redis-7.2.5.tar.gz
cd redis-7.2.5
make -j$(nproc)
make test
sudo make install PREFIX=/usr/local/redis

# 创建目录
sudo mkdir -p /etc/redis /var/lib/redis /var/log/redis
sudo useradd -r -s /bin/false redis
sudo chown redis:redis /var/lib/redis /var/log/redis

2.2 配置文件

# 复制配置文件
sudo cp redis.conf /etc/redis/redis.conf
sudo cp sentinel.conf /etc/redis/sentinel.conf

核心配置项(/etc/redis/redis.conf):

# 网络
bind 0.0.0.0
port 6379
protected-mode yes
tcp-backlog 511
timeout 300
tcp-keepalive 300

# 通用
daemonize yes
pidfile /var/run/redis/redis-server.pid
loglevel notice
logfile /var/log/redis/redis-server.log
databases 16

# 持久化
dir /var/lib/redis
dbfilename dump.rdb
save 900 1
save 300 10
save 60 10000
rdbcompression yes
rdbchecksum yes

# AOF
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-use-rdb-preamble yes

# 内存
maxmemory 8gb
maxmemory-policy allkeys-lru

# 安全
requirepass YourStrongPassword123!
rename-command FLUSHALL ""
rename-command FLUSHDB ""
rename-command CONFIG ""
rename-command DEBUG ""

# 慢日志
slowlog-log-slower-than 10000
slowlog-max-len 128

# 客户端
maxclients 10000

2.3 Systemd 服务管理

# /etc/systemd/system/redis.service
[Unit]
Description=Redis In-Memory Data Store
After=network.target

[Service]
User=redis
Group=redis
ExecStart=/usr/local/redis/bin/redis-server /etc/redis/redis.conf
ExecStop=/usr/local/redis/bin/redis-cli -a 'YourStrongPassword123!' shutdown
Restart=always
RestartSec=3
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable redis
sudo systemctl start redis
sudo systemctl status redis

2.4 Docker 部署

# 单节点
docker run -d \
  --name redis \
  -p 6379:6379 \
  -v /data/redis:/data \
  -v /etc/redis/redis.conf:/etc/redis/redis.conf \
  redis:7.2-alpine \
  redis-server /etc/redis/redis.conf

# Docker Compose
cat > docker-compose.yml << 'EOF'
version: '3.8'
services:
  redis:
    image: redis:7.2-alpine
    container_name: redis
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
      - ./redis.conf:/etc/redis/redis.conf
    command: redis-server /etc/redis/redis.conf
    restart: always
    sysctls:
      net.core.somaxconn: 1024
volumes:
  redis-data:
EOF

2.5 内核参数优化

# /etc/sysctl.conf
vm.overcommit_memory = 1
net.core.somaxconn = 1024
vm.swappiness = 1

# 禁用 THP(Transparent Huge Pages)
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

# 文件描述符限制
# /etc/security/limits.conf
redis soft nofile 65535
redis hard nofile 65535

三、持久化机制

3.1 RDB 快照

RDB 通过生成内存数据的二进制快照文件来持久化数据。

工作原理:

  • Redis fork 出子进程

  • 子进程将内存数据写入临时 RDB 文件

  • 写入完成后替换旧的 RDB 文件

配置示例:

# 触发条件:满足任意一条即触发
save 900 1      # 900 秒内至少 1 次写入
save 300 10     # 300 秒内至少 10 次写入
save 60 10000   # 60 秒内至少 10000 次写入

# 压缩与校验
rdbcompression yes
rdbchecksum yes

# 文件名
dbfilename dump.rdb
dir /var/lib/redis

手动触发:

# 阻塞式保存(生产慎用)
redis-cli SAVE

# 后台保存(推荐)
redis-cli BGSAVE

# 查看上次保存时间
redis-cli LASTSAVE

优缺点:

  • ✅ 文件紧凑,恢复速度快

  • ✅ 对性能影响小(fork 子进程)

  • ❌ 可能丢失最后一次快照后的数据

  • ❌ 数据量大时 fork 耗时较长

3.2 AOF 日志

AOF(Append Only File)以日志追加的方式记录每个写操作。

配置示例:

appendonly yes
appendfilename "appendonly.aof"

# 同步策略
appendfsync always    # 每次写入都同步(最安全,最慢)
appendfsync everysec  # 每秒同步一次(推荐,最多丢 1 秒数据)
appendfsync no        # 由操作系统决定(最快,但不安全)

# AOF 重写
auto-aof-rewrite-percentage 100  # 文件增长 100% 时触发重写
auto-aof-rewrite-min-size 64mb   # 最小重写文件大小

# Redis 7.x: 混合持久化
aof-use-rdb-preamble yes

手动触发重写:

redis-cli BGREWRITEAOF

AOF 文件修复:

# 检查 AOF 文件
redis-check-aof --fix appendonly.aof

3.3 混合持久化(推荐)

Redis 4.0+ 支持混合持久化,结合 RDB 和 AOF 的优点:

aof-use-rdb-preamble yes

工作原理:

  • AOF 重写时,前半部分写入 RDB 格式(快速加载)

  • 后半部分追加 AOF 增量日志(数据完整性)

  • 恢复时先加载 RDB 部分,再回放 AOF 部分

3.4 持久化策略选择

场景对照:

  • 纯缓存,丢了重填:关闭持久化,或只用 RDB

  • 数据安全性要求高:AOF + appendfsync everysec

  • 快速恢复 + 数据安全:混合持久化(推荐)

  • 大数据集:RDB 为主,AOF 为辅


四、内存管理

4.1 内存分配策略

# 查看内存使用详情
redis-cli INFO memory

# 关键指标
# used_memory: Redis 分配器分配的内存总量
# used_memory_rss: 操作系统视角的内存占用
# used_memory_peak: 内存使用峰值
# mem_fragmentation_ratio: 内存碎片率(= rss / used)

碎片率判断:

  • > 1.5:碎片严重,考虑开启 activedefrag

  • < 1.0:使用了 swap,极其危险

# 开启主动碎片整理(Redis 4.0+)
activedefrag yes
active-defrag-enabled yes
active-defrag-ignore-bytes 100mb
active-defrag-threshold-lower 10
active-defrag-threshold-upper 100

4.2 内存淘汰策略

当内存达到 maxmemory 限制时,Redis 的淘汰行为:

  • noeviction:不淘汰,写入报错(默认)

  • allkeys-lru:所有 key 中淘汰最近最少使用的(推荐缓存场景)

  • allkeys-lfu:所有 key 中淘汰最不常用的(Redis 4.0+)

  • allkeys-random:所有 key 中随机淘汰

  • volatile-lru:有过期时间的 key 中淘汰 LRU

  • volatile-lfu:有过期时间的 key 中淘汰 LFU

  • volatile-random:有过期时间的 key 中随机淘汰

  • volatile-ttl:淘汰 TTL 最短的 key

# 查看当前策略
redis-cli CONFIG GET maxmemory-policy

# 设置策略
redis-cli CONFIG SET maxmemory-policy allkeys-lru

# 设置最大内存
redis-cli CONFIG SET maxmemory 8gb

4.3 大 Key 排查

大 Key 是 Redis 性能杀手,会导致阻塞、网络拥塞和内存不均。

扫描大 Key:

# 使用 redis-cli 内置扫描(Redis 4.0+)
redis-cli --bigkeys

# 更精确的扫描(同时统计内存)
redis-cli --memkeys

# 使用 memory usage 命令检查单个 key
redis-cli MEMORY USAGE mykey

# 使用 debug object 查看序列化长度
redis-cli DEBUG OBJECT mykey

使用脚本扫描:

#!/usr/bin/env python3
"""redis_bigkey_scan.py - 扫描 Redis 大 Key"""
import redis

r = redis.Redis(host='localhost', port=6379, password='xxx', decode_responses=True)

THRESHOLD = 1024  # 1KB

cursor = 0
while True:
    cursor, keys = r.scan(cursor, count=100)
    for key in keys:
        key_type = r.type(key)
        size = 0
        if key_type == 'string':
            size = r.strlen(key)
        elif key_type == 'hash':
            size = r.hlen(key)
        elif key_type == 'list':
            size = r.llen(key)
        elif key_type == 'set':
            size = r.scard(key)
        elif key_type == 'zset':
            size = r.zcard(key)
        
        if size > THRESHOLD:
            mem = r.memory_usage(key) or 0
            print(f"[{key_type}] {key} -> count={size}, mem={mem/1024:.1f}KB")
    
    if cursor == 0:
        break

大 Key 治理:

# 删除大 Key(不要直接 DEL!会阻塞)
# Redis 4.0+ 使用 UNLINK(异步删除)
redis-cli UNLINK bigkey

# 对于 Hash 类型,分批删除
redis-cli HSCAN myhash 0 COUNT 100
# 然后逐批 HDEL

# 对于 List 类型,分批裁剪
redis-cli LTRIM mylist 0 -1001  # 每次保留后 1000 个

4.4 Key 过期策略

Redis 采用惰性删除 + 定期删除的组合策略:

# 设置过期时间
redis-cli EXPIRE mykey 3600        # 秒
redis-cli PEXPIRE mykey 3600000    # 毫秒
redis-cli EXPIREAT mykey 1735689600  # Unix 时间戳

# 查看剩余 TTL
redis-cli TTL mykey

# 取消过期
redis-cli PERSIST mykey

五、主从复制

5.1 架构原理

Master (写) ──复制──> Slave 1 (读)
     │
     └──复制──> Slave 2 (读)

复制流程:

  1. Slave 发送 PSYNC 命令

  2. Master 执行 BGSAVE 生成 RDB,同时记录增量命令

  3. Master 将 RDB 发送给 Slave

  4. Slave 加载 RDB,之后 Master 持续发送增量数据

5.2 配置主从

从节点配置:

# /etc/redis/redis-slave.conf
replicaof 192.168.1.10 6379
masterauth YourStrongPassword123!
replica-read-only yes

# 无盘复制(网络带宽充足时推荐)
repl-diskless-sync yes
repl-diskless-sync-delay 5

# 复制积压缓冲区大小
repl-backlog-size 256mb

动态设置:

# 在从节点执行
redis-cli REPLICAOF 192.168.1.10 6379
redis-cli CONFIG SET masterauth 'YourStrongPassword123!'

# 取消复制,变为独立主节点
redis-cli REPLICAOF NO ONE

5.3 复制状态监控

# 查看复制信息
redis-cli INFO replication

# 关键指标
# role: master/slave
# connected_slaves: 已连接的从节点数
# master_link_status: up/down(从节点视角)
# master_last_io_seconds_ago: 距上次通信秒数
# repl_backlog_active: 复制积压缓冲区是否活跃

5.4 复制常见问题

问题 1:全量复制频繁

# 增大复制积压缓冲区
redis-cli CONFIG SET repl-backlog-size 512mb

# 避免 Master 重启导致 runid 变化
# 使用 redis-shake 等工具做数据迁移

问题 2:复制延迟

# 检查主从偏移量差
redis-cli INFO replication | grep -E "master_repl_offset|slave.*offset"

# 开启无盘复制减少磁盘 I/O
redis-cli CONFIG SET repl-diskless-sync yes

六、Redis Sentinel(哨兵)

6.1 架构概述

Sentinel 是 Redis 的高可用方案,负责监控、通知和自动故障转移。

最少部署 3 个 Sentinel 节点,采用多数投票机制。

6.2 配置文件

# /etc/redis/sentinel.conf
port 26379
daemonize yes
pidfile /var/run/redis/sentinel.pid
logfile /var/log/redis/sentinel.log
dir /var/lib/redis

# 监控主节点
sentinel monitor mymaster 192.168.1.10 6379 2
sentinel auth-pass mymaster YourStrongPassword123!

# 故障判定
sentinel down-after-milliseconds mymaster 5000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 60000

# 通知脚本
# sentinel notification-script mymaster /opt/redis/notify.sh

# 客户端重配置脚本
# sentinel client-reconfig-script mymaster /opt/redis/reconfig.sh

关键参数说明:

  • sentinel monitor mymaster ... 2:至少 2 个 Sentinel 同意才能判定主观下线

  • down-after-milliseconds:5 秒无响应判定主观下线

  • failover-timeout:故障转移超时时间

6.3 Sentinel 管理

# 启动 Sentinel
redis-sentinel /etc/redis/sentinel.conf
# 或
redis-server /etc/redis/sentinel.conf --sentinel

# 连接 Sentinel
redis-cli -p 26379

# 查看主节点信息
redis-cli -p 26379 SENTINEL master mymaster

# 查看所有被监控的主节点
redis-cli -p 26379 SENTINEL masters

# 查看从节点
redis-cli -p 26379 SENTINEL replicas mymaster

# 获取当前主节点地址
redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster

# 手动触发故障转移
redis-cli -p 26379 SENTINEL failover mymaster

# 检查 Sentinel 状态
redis-cli -p 26379 SENTINEL ckquorum mymaster

6.4 客户端连接方式

# Python 示例(使用 redis-py)
from redis.sentinel import Sentinel

sentinel = Sentinel([
    ('192.168.1.10', 26379),
    ('192.168.1.11', 26379),
    ('192.168.1.12', 26379),
], socket_timeout=0.5)

# 获取主节点连接(写)
master = sentinel.master_for('mymaster', password='YourStrongPassword123!')
master.set('key', 'value')

# 获取从节点连接(读)
slave = sentinel.slave_for('mymaster', password='YourStrongPassword123!')
slave.get('key')

七、Redis Cluster(集群)

7.1 架构概述

Redis Cluster 是 Redis 的分布式方案,支持数据分片和高可用。

核心概念:

  • 16384 个哈希槽(slot):数据通过 CRC16(key) % 16384 分配到不同节点

  • 最少 3 主 3 从:每个主节点负责一部分槽位

  • Gossip 协议:节点间通信使用 Gossip 协议

  • MOVED/ASK 重定向:客户端自动路由到正确的节点

7.2 集群部署

# 创建 6 节点集群(3主3从)
mkdir -p /data/redis-cluster/{7001,7002,7003,7004,7005,7006}

# 生成配置文件模板
for port in 7001 7002 7003 7004 7005 7006; do
cat > /data/redis-cluster/$port/redis.conf << EOF
port $port
bind 0.0.0.0
daemonize yes
pidfile /var/run/redis/redis-$port.pid
logfile /var/log/redis/redis-$port.log
dir /data/redis-cluster/$port
dbfilename dump.rdb
appendonly yes
appendfilename "appendonly.aof"

# 集群配置
cluster-enabled yes
cluster-config-file nodes-$port.conf
cluster-node-timeout 15000
cluster-announce-ip 192.168.1.10
cluster-announce-port $port
cluster-announce-bus-port 1${port#7000}

# 安全
requirepass YourStrongPassword123!
masterauth YourStrongPassword123!
EOF
done

# 启动所有节点
for port in 7001 7002 7003 7004 7005 7006; do
  redis-server /data/redis-cluster/$port/redis.conf
done

# 创建集群
redis-cli --cluster create \
  192.168.1.10:7001 192.168.1.10:7002 192.168.1.10:7003 \
  192.168.1.10:7004 192.168.1.10:7005 192.168.1.10:7006 \
  --cluster-replicas 1 \
  -a YourStrongPassword123!

7.3 集群管理

# 查看集群信息
redis-cli -c -p 7001 CLUSTER INFO
redis-cli -c -p 7001 CLUSTER NODES

# 查看槽位分配
redis-cli --cluster check 192.168.1.10:7001 -a YourStrongPassword123!

# 添加主节点
redis-cli --cluster add-node 192.168.1.10:7007 192.168.1.10:7001 \
  -a YourStrongPassword123!

# 添加从节点
redis-cli --cluster add-node 192.168.1.10:7008 192.168.1.10:7001 \
  --cluster-slave --cluster-master-id <master-node-id> \
  -a YourStrongPassword123!

# 迁移槽位
redis-cli --cluster reshard 192.168.1.10:7001 \
  --cluster-from <source-node-id> \
  --cluster-to <target-node-id> \
  --cluster-slots 1000 \
  --cluster-yes \
  -a YourStrongPassword123!

# 自动均衡槽位
redis-cli --cluster rebalance 192.168.1.10:7001 \
  -a YourStrongPassword123!

# 删除节点(先迁走槽位)
redis-cli --cluster del-node 192.168.1.10:7001 <node-id> \
  -a YourStrongPassword123!

7.4 集群故障转移

# 手动故障转移(在从节点执行)
redis-cli -p 7004 CLUSTER FAILOVER

# 强制故障转移(不等待数据同步)
redis-cli -p 7004 CLUSTER FAILOVER FORCE

# 模拟故障
redis-cli -p 7001 DEBUG SLEEP 30

7.5 集群注意事项

  • 不支持跨槽的多 key 操作:使用 Hash Tag {tag} 将相关 key 分配到同一槽位

  • 批量操作要小心:MGET/MSET 的 key 必须在同一槽位

  • Lua 脚本的 key 必须在同一槽位

# Hash Tag 示例
SET {user:1000}.name "Alice"
SET {user:1000}.age "30"
# 这两个 key 会在同一个槽位,可以一起操作
MGET {user:1000}.name {user:1000}.age

八、性能优化

8.1 Pipeline 批量操作

Pipeline 将多个命令打包发送,减少网络往返时间。

# Python 示例
import redis

r = redis.Redis(host='localhost', port=6379, decode_responses=True)

# 不使用 Pipeline(10000 次网络往返)
for i in range(10000):
    r.set(f'key:{i}', f'value:{i}')

# 使用 Pipeline(1 次网络往返)
pipe = r.pipeline(transaction=False)
for i in range(10000):
    pipe.set(f'key:{i}', f'value:{i}')
pipe.execute()
# redis-cli 中使用 Pipeline
cat commands.txt | redis-cli --pipe
# commands.txt 格式:
# SET key1 value1
# SET key2 value2

8.2 Lua 脚本

Lua 脚本在 Redis 服务端原子执行,适合复杂逻辑。

# 原子递增并检查阈值
redis-cli EVAL "
  local current = redis.call('INCR', KEYS[1])
  if current == 1 then
    redis.call('EXPIRE', KEYS[1], ARGV[1])
  end
  if current > tonumber(ARGV[2]) then
    return 0
  end
  return 1
" 1 rate:api 60 100

# 限流器示例(滑动窗口)
redis-cli EVAL "
  local key = KEYS[1]
  local now = tonumber(ARGV[1])
  local window = tonumber(ARGV[2])
  local limit = tonumber(ARGV[3])
  
  redis.call('ZREMRANGEBYSCORE', key, 0, now - window)
  local count = redis.call('ZCARD', key)
  
  if count < limit then
    redis.call('ZADD', key, now, now .. ':' .. math.random())
    redis.call('EXPIRE', key, window / 1000)
    return 1
  end
  return 0
" 1 rate:sliding:api 1718000000000 60000 100

脚本缓存:

# 先加载脚本获取 SHA1
redis-cli SCRIPT LOAD "return redis.call('GET', KEYS[1])"
# 返回: "e0e1f9fabfc9d4800c877a703b823ac0578ff831"

# 通过 SHA1 执行
redis-cli EVALSHA e0e1f9fabfc9d4800c877a703b823ac0578ff831 1 mykey

8.3 热 Key 问题

热 Key 会导致单节点过载,常见于秒杀、热点新闻等场景。

发现热 Key:

# Redis 4.0+ 使用 LFU 策略时可查看
redis-cli --hotkeys

# 使用 MONITOR 实时分析(生产慎用,影响性能)
redis-cli MONITOR | head -10000 | awk '{print $4}' | sort | uniq -c | sort -rn | head -20

# 使用 keyspace 通知统计
redis-cli CONFIG SET notify-keyspace-events Kg$  # 仅开启 key 事件

热 Key 解决方案:

# 方案 1:本地缓存(应用层)
# 在应用中使用 LRU Cache 缓存热 Key

# 方案 2:读写分离
# 从多个从节点读取

# 方案 3:Key 分片
# 将热 Key 拆分为多个子 Key
SET hotkey:1 "value"
SET hotkey:2 "value"
SET hotkey:3 "value"
# 读取时随机选择
GET hotkey:{random(1,3)}

8.4 慢查询分析

# 查看慢查询日志
redis-cli SLOWLOG GET 10

# 设置慢查询阈值(微秒)
redis-cli CONFIG SET slowlog-log-slower-than 10000  # 10ms

# 查看慢查询日志长度
redis-cli SLOWLOG LEN

# 清空慢查询日志
redis-cli SLOWLOG RESET

8.5 连接池优化

# Python 连接池配置
import redis

pool = redis.ConnectionPool(
    host='localhost',
    port=6379,
    password='YourStrongPassword123!',
    max_connections=50,
    decode_responses=True,
    socket_timeout=5,
    socket_connect_timeout=5,
    retry_on_timeout=True,
    health_check_interval=30
)

r = redis.Redis(connection_pool=pool)

九、安全配置

9.1 认证与授权

# 设置密码
redis-cli CONFIG SET requirepass YourStrongPassword123!

# Redis 6.0+ ACL
# 创建用户
redis-cli ACL SETUSER alice on >password123 ~* +@all -@dangerous

# 创建只读用户
redis-cli ACL SETUSER reader on >readpass ~* +@read

# 查看用户列表
redis-cli ACL LIST

# 保存 ACL 配置
redis-cli ACL SAVE

ACL 配置文件示例:

# /etc/redis/users.acl
user default off
user alice on >StrongPass1 ~* +@all -@dangerous -FLUSHALL -FLUSHDB -DEBUG
user reader on >ReadPass1 ~* +@read
user app on >AppPass1 ~app:* +@read +@write -@admin

9.2 网络安全

# 绑定内网 IP
bind 127.0.0.1 192.168.1.10

# 启用保护模式
protected-mode yes

# 修改默认端口
port 16379

# 禁用危险命令
rename-command FLUSHALL ""
rename-command FLUSHDB ""
rename-command CONFIG "CONFIG_b93e7a2d"
rename-command DEBUG ""
rename-command KEYS ""

9.3 TLS 加密

# Redis 6.0+ 支持 TLS
tls-port 6380
tls-cert-file /etc/redis/tls/redis.crt
tls-key-file /etc/redis/tls/redis.key
tls-ca-cert-file /etc/redis/tls/ca.crt
tls-auth-clients optional

9.4 安全检查清单

# 1. 检查是否设置了密码
redis-cli CONFIG GET requireauth

# 2. 检查绑定地址
redis-cli CONFIG GET bind

# 3. 检查保护模式
redis-cli CONFIG GET protected-mode

# 4. 检查危险命令是否禁用
redis-cli FLUSHALL  # 应该报错

# 5. 检查是否暴露在公网
nmap -p 6379 <your-ip>

十、监控与告警

10.1 核心监控指标

# 获取所有信息
redis-cli INFO all

# 分类获取
redis-cli INFO server      # 服务器信息
redis-cli INFO clients     # 客户端连接
redis-cli INFO memory      # 内存使用
redis-cli INFO stats       # 统计信息
redis-cli INFO replication # 复制状态
redis-cli INFO cpu         # CPU 使用
redis-cli INFO keyspace    # 数据库 key 统计

关键指标清单:

  • 内存used_memoryused_memory_rssmem_fragmentation_ratio

  • 连接connected_clientsblocked_clientsrejected_connections

  • 性能instantaneous_ops_per_seclatency_percentiles

  • 命中率keyspace_hitskeyspace_misses(命中率 = hits / (hits + misses))

  • 持久化rdb_last_bgsave_statusaof_last_bgrewrite_status

  • 复制master_link_statusmaster_last_io_seconds_ago

  • 碎片mem_fragmentation_ratioactive_defrag_running

10.2 Prometheus + Grafana 监控

# 部署 redis_exporter
docker run -d \
  --name redis_exporter \
  -p 9121:9121 \
  oliver006/redis_exporter \
  --redis.addr redis://192.168.1.10:6379 \
  --redis.password 'YourStrongPassword123!'

Prometheus 配置:

# prometheus.yml
scrape_configs:
  - job_name: 'redis'
    static_configs:
      - targets: ['192.168.1.10:9121']
    metrics_path: /metrics

Grafana Dashboard ID: 763(Redis Dashboard for Prometheus)

10.3 告警规则

# Prometheus 命名规则
groups:
  - name: redis_alerts
    rules:
      # 实例宕机
      - alert: RedisDown
        expr: redis_up == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Redis 实例 {{ $labels.instance }} 宕机"

      # 内存使用过高
      - alert: RedisHighMemory
        expr: redis_memory_used_bytes / redis_memory_max_bytes > 0.9
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Redis 内存使用超过 90%"

      # 连接数过高
      - alert: RedisHighConnections
        expr: redis_connected_clients > 1000
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Redis 连接数过高: {{ $value }}"

      # 命中率过低
      - alert: RedisLowHitRate
        expr: redis_keyspace_hits_total / (redis_keyspace_hits_total + redis_keyspace_misses_total) < 0.8
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Redis 缓存命中率低于 80%"

      # 复制断开
      - alert: RedisReplicationBroken
        expr: redis_connected_slaves < 1
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Redis 主从复制断开"

      # 慢查询过多
      - alert: RedisTooManySlowQueries
        expr: increase(redis_slowlog_length[5m]) > 10
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Redis 5 分钟内慢查询超过 10 条"

10.4 Latency 监控

# Redis 内置延迟监控
redis-cli CONFIG SET latency-monitor-threshold 5  # 5ms

# 查看延迟事件
redis-cli LATENCY LATEST
redis-cli LATENCY HISTORY command
redis-cli LATENCY RESET

# 延迟图谱
redis-cli --latency
redis-cli --latency-history
redis-cli --latency-dist

十一、常见问题排查

11.1 Redis 响应变慢

排查步骤:

# 1. 查看慢查询
redis-cli SLOWLOG GET 20

# 2. 检查内存碎片
redis-cli INFO memory | grep mem_fragmentation_ratio

# 3. 检查是否在做持久化
redis-cli INFO persistence | grep -E "rdb_bgsave_in_progress|aof_rewrite_in_progress"

# 4. 检查客户端连接数
redis-cli INFO clients | grep connected_clients

# 5. 检查网络延迟
redis-cli --latency-history -i 1

# 6. 检查是否有大 Key 阻塞
redis-cli --bigkeys

# 7. 检查是否使用了 swap
redis-cli INFO memory | grep mem_allocator
# 如果 used_memory > used_memory_rss,可能在用 swap

11.2 内存暴涨

# 1. 检查内存使用
redis-cli INFO memory

# 2. 查看内存增长趋势
redis-cli MEMORY STATS

# 3. 扫描大 Key
redis-cli --bigkeys
redis-cli --memkeys

# 4. 检查是否有大量过期 key 未清理
redis-cli INFO keyspace
# 如果 keys 远大于 expires,说明过期清理不及时

# 5. 检查是否有 pub/sub 泄漏
redis-cli PUBSUB CHANNELS | wc -l

11.3 主从同步延迟

# 1. 检查复制状态
redis-cli INFO replication

# 2. 查看主从偏移量差
# master_repl_offset - slave_repl_offset = 延迟字节数

# 3. 检查网络带宽
iftop -i eth0

# 4. 增大复制缓冲区
redis-cli CONFIG SET repl-backlog-size 512mb

# 5. 开启无盘复制
redis-cli CONFIG SET repl-diskless-sync yes

11.4 集群节点故障

# 1. 查看集群状态
redis-cli -c -p 7001 CLUSTER INFO | grep cluster_state
# cluster_state:ok 表示正常

# 2. 查看节点状态
redis-cli -c -p 7001 CLUSTER NODES | grep -v "handshake"
# 查找 fail 状态的节点

# 3. 检查故障节点
redis-cli -c -p 7001 CLUSTER NODES | grep "fail"

# 4. 尝试恢复节点
redis-cli -c -p 7001 CLUSTER RESET SOFT

# 5. 如果是网络分区,等网络恢复后节点会自动重新加入

11.5 持久化导致的延迟

# 1. 检查 fork 耗时
redis-cli INFO stats | grep latest_fork_usec
# 如果 > 100ms,说明 fork 耗时过长

# 2. 减小数据集大小
# 分片或清理不必要的数据

# 3. 使用 SSD 替代 HDD
# RDB 和 AOF 的写入对磁盘 I/O 要求较高

# 4. 调整 AOF 同步策略
redis-cli CONFIG SET appendfsync everysec  # 替代 always

十二、运维命令速查表

12.1 服务器管理

# 服务启停
systemctl start redis
systemctl stop redis
systemctl restart redis
systemctl status redis

# 热更新配置
redis-cli CONFIG SET <param> <value>
redis-cli CONFIG REWRITE  # 写入配置文件

# 关闭 Redis(安全关闭)
redis-cli SHUTDOWN NOSAVE  # 不保存直接关闭
redis-cli SHUTDOWN SAVE    # 保存后关闭

# 查看服务器信息
redis-cli INFO [section]
redis-cli DBSIZE
redis-cli TIME
redis-cli LASTSAVE

12.2 Key 操作

# 基本操作
redis-cli SET key value [EX seconds] [PX milliseconds] [NX|XX]
redis-cli GET key
redis-cli DEL key [key ...]
redis-cli UNLINK key [key ...]     # 异步删除
redis-cli EXISTS key [key ...]
redis-cli TYPE key
redis-cli TTL key
redis-cli PTTL key
redis-cli EXPIRE key seconds
redis-cli PERSIST key

# 批量操作
redis-cli MSET key1 val1 key2 val2
redis-cli MGET key1 key2

# 扫描(生产替代 KEYS)
redis-cli SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]

# 查看编码
redis-cli OBJECT ENCODING key
redis-cli OBJECT REFCOUNT key
redis-cli OBJECT IDLETIME key

12.3 数据类型操作

# String
redis-cli INCR key / INCRBY key increment
redis-cli DECR key / DECRBY key decrement
redis-cli APPEND key value
redis-cli STRLEN key
redis-cli SETNX key value
redis-cli SETEX key seconds value

# Hash
redis-cli HSET key field value
redis-cli HGET key field
redis-cli HMSET key field1 val1 field2 val2
redis-cli HMGET key field1 field2
redis-cli HGETALL key
redis-cli HDEL key field [field ...]
redis-cli HINCRBY key field increment
redis-cli HLEN key
redis-cli HSCAN key cursor [MATCH pattern] [COUNT count]

# List
redis-cli LPUSH key value [value ...]
redis-cli RPUSH key value [value ...]
redis-cli LPOP key
redis-cli RPOP key
redis-cli LRANGE key start stop
redis-cli LLEN key
redis-cli LINDEX key index
redis-cli LSET key index value
redis-cli BLPOP key [key ...] timeout  # 阻塞弹出

# Set
redis-cli SADD key member [member ...]
redis-cli SMEMBERS key
redis-cli SISMEMBER key member
redis-cli SCARD key
redis-cli SREM key member [member ...]
redis-cli SUNION key [key ...]
redis-cli SINTER key [key ...]
redis-cli SDIFF key [key ...]
redis-cli SRANDMEMBER key [count]

# Sorted Set
redis-cli ZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member ...]
redis-cli ZRANGE key start stop [WITHSCORES]
redis-cli ZREVRANGE key start stop [WITHSCORES]
redis-cli ZSCORE key member
redis-cli ZRANK key member
redis-cli ZREVRANK key member
redis-cli ZCARD key
redis-cli ZCOUNT key min max
redis-cli ZINCRBY key increment member
redis-cli ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]

12.4 事务与发布订阅

# 事务
redis-cli MULTI
redis-cli EXEC
redis-cli DISCARD
redis-cli WATCH key [key ...]
redis-cli UNWATCH

# 发布订阅
redis-cli PUBLISH channel message
redis-cli SUBSCRIBE channel [channel ...]
redis-cli PSUBSCRIBE pattern [pattern ...]
redis-cli UNSUBSCRIBE [channel [channel ...]]

# 查看订阅信息
redis-cli PUBSUB CHANNELS [pattern]
redis-cli PUBSUB NUMSUB [channel [channel ...]]

12.5 调试与诊断

# 延迟诊断
redis-cli --latency              # 实时延迟
redis-cli --latency-history      # 延迟历史
redis-cli --latency-dist         # 延迟分布
redis-cli --intrinsic-latency 100  # 系统固有延迟(100秒)

# 内部延迟
redis-cli LATENCY LATEST
redis-cli LATENCY HISTORY event
redis-cli LATENCY RESET

# 监控命令(生产慎用)
redis-cli MONITOR                # 实时打印所有命令
redis-cli SLOWLOG GET 20        # 慢查询
redis-cli SLOWLOG LEN
redis-cli SLOWLOG RESET

# 内存分析
redis-cli MEMORY DOCTOR
redis-cli MEMORY STATS
redis-cli MEMORY USAGE key [SAMPLES count]
redis-cli MEMORY PURGE
redis-cli MEMORY MALLOC-STATS

# 客户端管理
redis-cli CLIENT LIST
redis-cli CLIENT GETNAME
redis-cli CLIENT SETNAME myconn
redis-cli CLIENT KILL ID <id>
redis-cli CLIENT PAUSE timeout [ALL|WRITE]

12.6 备份与恢复

# RDB 备份
redis-cli BGSAVE
cp /var/lib/redis/dump.rdb /backup/dump-$(date +%Y%m%d).rdb

# AOF 备份
cp /var/lib/redis/appendonly.aof /backup/appendonly-$(date +%Y%m%d).aof

# 恢复(停止 Redis → 替换文件 → 启动)
systemctl stop redis
cp /backup/dump-20260610.rdb /var/lib/redis/dump.rdb
# 或
cp /backup/appendonly-20260610.aof /var/lib/redis/appendonly.aof
systemctl start redis

# RDB 文件检查
redis-check-rdb /var/lib/redis/dump.rdb

# AOF 文件检查与修复
redis-check-aof --fix /var/lib/redis/appendonly.aof

12.7 数据迁移

# 使用 redis-shake 迁移
# 下载: https://github.com/tair-opensource/RedisShake

# 全量 + 增量同步配置
cat > shake.toml << 'EOF'
[source]
type = "standalone"
address = "192.168.1.10:6379"
password = "OldPassword"

[target]
type = "standalone"
address = "192.168.1.20:6379"
password = "NewPassword"

[advanced]
dir = "./data"
ncpu = 4
EOF

./redis-shake shake.toml

附录:Redis 版本选择建议

  • Redis 7.2.x:最新稳定版,推荐新项目使用

  • Redis 7.0.x:成熟稳定,推荐生产环境

  • Redis 6.2.x:仍广泛使用,ACL 和 TLS 支持完善

  • Redis 6.0.x:支持 ACL、TLS、多线程 I/O

  • Redis 5.x:旧版本,建议升级

升级注意事项:

  1. 先在测试环境验证兼容性

  2. 备份数据后再升级

  3. 主从架构中先升级从节点,最后升级主节点

  4. 集群架构中逐节点滚动升级