Redis生产环境部署避坑指南

描述

前言

Redis 是 PHP 项目中使用最广泛的 Nosql 缓存数据库,但很多团队在生产环境中部署 Redis 时存在诸多隐患:内存配置不当导致 OOM、持久化配置错误导致数据丢失、集群部署不合理导致性能下降、安全配置缺失导致被攻击。

本文从实际生产经验出发,详细讲解 Redis 在生产环境中的部署避坑指南,包括内存配置、持久化方案、集群架构、安全加固、监控告警等方面。

1 内存配置

1.1 最大内存配置

 

# 查看当前最大内存配置
redis-cli CONFIG GET maxmemory

# 设置最大内存(字节)
redis-cli CONFIG SET maxmemory 10737418240  # 10GB

# 临时设置(重启失效)
redis-server --maxmemory 10gb

# 永久设置(配置文件)
# redis.conf
maxmemory 10gb

 

内存单位说明:

 

1k => 1000 bytes
1kb => 1024 bytes
1m => 1000000 bytes
1mb => 1024*1024 bytes
1g => 1000000000 bytes
1gb => 1024*1024*1024 bytes

 

1.2 内存淘汰策略

当 Redis 内存达到 maxmemory 时,会根据配置的淘汰策略删除键值。

 

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

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

 

可选策略:

策略 说明 适用场景
noeviction 不淘汰,返回错误 数据不允许丢失
allkeys-lru 所有键使用 LRU 淘汰 通用缓存场景
allkeys-lfu 所有键使用 LFU 淘汰 热点数据场景
allkeys-random 所有键随机淘汰 随机淘汰场景
volatile-lru 已设置 TTL 的键使用 LRU 混合使用
volatile-lfu 已设置 TTL 的键使用 LFU 混合使用
volatile-random 已设置 TTL 的键随机淘汰 混合使用
volatile-ttl 已设置 TTL 的键按 TTL 淘汰 保留热点数据

LRU vs LFU:

**LRU (Least Recently Used)**:最近最少使用,淘汰最久未访问的键

**LFU (Least Frequently Used)**:最不经常使用,淘汰访问频率最低的键

 

# volatile-lru 适合的场景:
# 既有缓存数据又有持久数据的混合应用
# 设置了 TTL 的数据希望优先淘汰

# allkeys-lru 适合的场景:
# 所有数据都是缓存,希望优先保留热点数据

 

1.3 内存碎片

Redis 使用 glibc 的内存分配器,会产生内存碎片。

 

# 查看内存碎片率
redis-cli INFO memory | grep mem_fragmentation_ratio

# 手动整理碎片(Redis 4.0+)
redis-cli MEMORY PURGE

# 重启 Redis 也会清理碎片

 

内存碎片率说明:

1.0 ~ 1.5:正常范围

1.5:碎片较多,可能需要整理

< 1.0:使用了 swap 或物理内存不足

减少碎片的建议:

使用 Jemalloc 内存分配器(Redis 默认)

合理设置 maxmemory,避免频繁淘汰

使用 Redis 4.0+ 的主动碎片整理

 

# 启用主动碎片整理(Redis 4.0+)
redis-cli CONFIG SET activedefrag yes

# 查看碎片整理统计
redis-cli INFO memory | grep mem_fragmentation_ratio

 

1.4 内存监控

 

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

# 输出示例
# used_memory: 1073741824           # Redis 实际使用的内存
# used_memory_human: 1.00G
# used_memory_rss: 1258291200       # 操作系统实际分配的物理内存
# used_memory_rss_human: 1.17G
# used_memory_peak: 2147483648      # 内存使用峰值
# used_memory_peak_human: 2.00G
# mem_fragmentation_ratio: 1.17      # 内存碎片率
# mem_allocator: jemalloc-5.2.1     # 内存分配器

# 监控脚本
#!/bin/bash
USED=$(redis-cli INFO memory | grep used_memory | awk -F: '{print $2}')
PEAK=$(redis-cli INFO memory | grep used_memory_peak | awk -F: '{print $2}')
MAX=$(redis-cli CONFIG GET maxmemory | tail -1)

echo "Used: $((USED/1024/1024)) MB"
echo "Peak: $((PEAK/1024/1024)) MB"
echo "Max: $((MAX/1024/1024)) MB"
echo "Usage: $(echo "scale=2; $USED*100/$MAX" | bc)%"

 

2 持久化配置

2.1 RDB 持久化

RDB 是 Redis 的定时快照备份,生成紧凑的二进制文件。

 

# 手动触发 RDB
redis-cli BGSAVE
# 或
redis-cli SAVE  # 同步保存,会阻塞 Redis

# 查看最近一次 RDB 保存时间
redis-cli DEBUG SLEEP 1 && redis-cli LASTSAVE

# 查看子进程状态
redis-cli INFO persistence
# rdb_changes_since_last_save: 0
# rdb_last_save_time: 1609459200
# rdb_last_bgsave_status: ok
# rdb_last_bgsave_time_sec: 1

 

RDB 配置:

 

# redis.conf

# 多久触发一次 RDB
# 900秒内至少1个key变化
save 900 1
# 300秒内至少10个key变化
save 300 10
# 60秒内至少10000个key变化
save 60 10000

# 关闭 RDB(如果只用作缓存)
save ""

# RDB 文件名
dbfilename dump.rdb

# RDB 文件存放目录
dir /var/lib/redis

# bgsave 失败时禁止写入
stop-writes-on-bgsave-error yes

# 是否压缩 RDB 文件
rdbcompression yes

# 是否校验 RDB 文件
rdbchecksum yes

 

RDB 优点:

文件紧凑,适合备份和灾难恢复

恢复大数据集时比 AOF 快

RDB 缺点:

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

fork() 操作在数据量大时可能导致 Redis 短暂卡顿

2.2 AOF 持久化

AOF 是 Redis 的增量日志,记录每个写操作。

 

# 查看 AOF 状态
redis-cli INFO persistence
# aof_enabled: 1
# aof_current_size: 1048576
# aof_base_size: 1048576
# aof_pending_rewrite: 0
# aof_buffer_length: 0
# aof_rewrite_buffer_length: 0
# aof_pending_bio_fsync: 0
# aof_last_bgrewrite_status: ok
# aof_last_write_status: ok

 

AOF 配置:

 

# redis.conf

# 开启 AOF
appendonly yes

# AOF 文件名
appendfilename "appendonly.aof"

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

# AOF 重写配置
auto-aof-rewrite-percentage 100  # 文件比上次重写大100%时触发
auto-aof-rewrite-min-size 64mb   # 文件至少达到64MB才触发

# AOF 重写失败时停止写入
aof-load-truncated yes

# 启用 RDB-AOF 混合持久化(Redis 7.0+)
aof-use-rdb-preamble yes

 

AOF 优点:

数据安全性更高,最多丢失一个写入周期

AOF 文件是追加写入,不会产生随机写

AOF 缺点:

文件比 RDB 大

恢复数据时比 RDB 慢

2.3 混合持久化(Redis 4.0+)

 

# 启用混合持久化
aof-use-rdb-preamble yes

 

混合持久化会在 AOF 重写时使用 RDB 格式存储数据,然后在后面追加增量 AOF 指令。这样既保证了快速恢复,又保证了数据不丢失。

恢复优先级:

如果存在 AOF 文件,优先使用 AOF 恢复

如果 AOF 被关闭或不完整,使用 RDB 恢复

2.4 生产环境持久化建议

 

# 生产环境推荐配置

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

# RDB 配置
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes

# AOF 配置
appendonly yes
appendfsync everysec
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes

 

3 RDB 与 AOF 备份策略

3.1 备份脚本

 

#!/bin/bash
# filename: redis_backup.sh
# Redis 备份脚本

BACKUP_DIR="/data/redis_backup"
REDIS_HOST="127.0.0.1"
REDIS_PORT="6379"
REDIS_PASSWORD="your_redis_password"
DATE=$(date +%Y%m%d_%H%M%S)

# 创建备份目录
mkdir -p $BACKUP_DIR

# 获取 Redis 配置
REDIS_DATA_DIR=$(redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD CONFIG GET dir | tail -1)
REDIS_DBFILE=$(redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD CONFIG GET dbfilename | tail -1)
REDIS_AOFFILE=$(redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD CONFIG GET appendfilename | tail -1)

# 执行 BGSAVE
echo "Triggering BGSAVE..."
redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD BGSAVE

# 等待 RDB 保存完成
while [ $(redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD LASTSAVE) -eq $(redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD LASTSAVE) ]; do
    sleep 1
done

# 复制 RDB 文件
if [ -f "$REDIS_DATA_DIR/$REDIS_DBFILE" ]; then
    cp $REDIS_DATA_DIR/$REDIS_DBFILE $BACKUP_DIR/dump_$DATE.rdb
    echo "RDB backup: $REDIS_DBFILE"
fi

# 复制 AOF 文件
if [ -f "$REDIS_DATA_DIR/$REDIS_AOFFILE" ]; then
    cp $REDIS_DATA_DIR/$REDIS_AOFFILE $BACKUP_DIR/appendonly_$DATE.aof
    echo "AOF backup: $REDIS_AOFFILE"
fi

# 压缩备份文件
cd $BACKUP_DIR
tar czf redis_backup_$DATE.tar.gz *.rdb *.aof 2>/dev/null
rm -f *.rdb *.aof

# 删除 7 天前的备份
find $BACKUP_DIR -name "redis_backup_*.tar.gz" -mtime +7 -delete

echo "Backup completed: redis_backup_$DATE.tar.gz"
ls -lh $BACKUP_DIR

 

3.2 恢复脚本

 

#!/bin/bash
# filename: redis_restore.sh
# Redis 数据恢复脚本

BACKUP_FILE=$1
REDIS_HOST="127.0.0.1"
REDIS_PORT="6379"
REDIS_PASSWORD="your_redis_password"

if [ -z "$BACKUP_FILE" ]; then
    echo "Usage: $0 "
    exit 1
fi

if [ ! -f "$BACKUP_FILE" ]; then
    echo "Error: Backup file not found"
    exit 1
fi

# 停止 Redis
echo "Stopping Redis..."
systemctl stop redis

# 备份当前数据
REDIS_DATA_DIR=$(redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD CONFIG GET dir | tail -1)
if [ -f "$REDIS_DATA_DIR/dump.rdb" ]; then
    mv $REDIS_DATA_DIR/dump.rdb $REDIS_DATA_DIR/dump.rdb.bak
fi
if [ -f "$REDIS_DATA_DIR/appendonly.aof" ]; then
    mv $REDIS_DATA_DIR/appendonly.aof $REDIS_DATA_DIR/appendonly.aof.bak
fi

# 解压备份文件
cd $REDIS_DATA_DIR
tar xzf $BACKUP_FILE

# 启动 Redis
echo "Starting Redis..."
systemctl start redis

# 验证数据
KEY_COUNT=$(redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD DBSIZE)
echo "Restored keys: $KEY_COUNT"

# 如果数据不对,恢复备份
if [ "$KEY_COUNT" -eq 0 ]; then
    echo "Warning: No data restored, restoring from .bak files"
    mv $REDIS_DATA_DIR/dump.rdb.bak $REDIS_DATA_DIR/dump.rdb
    systemctl restart redis
fi

 

4 安全加固

4.1 密码认证

 

# 设置密码(临时)
redis-cli CONFIG SET requirepass "your_strong_password"

# 设置密码(永久,redis.conf)
requirepass your_strong_password

# 使用密码连接
redis-cli -a your_strong_password
redis-cli -h 127.0.0.1 -p 6379 -a your_strong_password

# 使用密码认证
redis-cli
AUTH your_strong_password

# 设置多个密码(ACL,Redis 6.0+)
ACL SETUSER alice on >password ~cached:* +get +set +del +exists

 

4.2 绑定地址

 

# 只监听本地
bind 127.0.0.1

# 监听特定 IP
bind 192.168.1.100

# 监听多个 IP
bind 127.0.0.1 192.168.1.100

# 监听所有接口(危险!)
bind 0.0.0.0  # 禁止生产环境使用

 

4.3 禁用危险命令

 

# redis.conf

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

# 或者重命名为不易猜测的名字
rename-command FLUSHDB FLUSHDB_RENAMED
rename-command KEYS KEYSCMD

 

4.4 限制连接数

 

# 最大连接数
maxclients 10000

# TCP backlog
tcp-backlog 511

# 超时设置(客户端空闲多久断开)
timeout 300

# 保活设置
tcp-keepalive 300

 

4.5 防火墙设置

 

# iptables 限制访问
iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 6379 -j ACCEPT
iptables -A INPUT -p tcp --dport 6379 -j DROP

# 如果使用云服务器,使用安全组限制
# 只允许应用服务器 IP 访问 Redis

 

4.6 安全检查清单

 

#!/bin/bash
# filename: redis_security_check.sh
# Redis 安全检查脚本

echo "=== Redis 安全检查 ==="
echo ""

# 1. 检查是否设置了密码
REQUIREPASS=$(redis-cli CONFIG GET requirepass | tail -1)
if [ "$REQUIREPASS" = "" ] || [ "$REQUIREPASS" = "" ]; then
    echo "[WARN] Redis 未设置密码!"
else
    echo "[OK] Redis 已设置密码"
fi

# 2. 检查绑定地址
BIND=$(redis-cli CONFIG GET bind | tail -1)
if [[ "$BIND" == *"0.0.0.0"* ]]; then
    echo "[WARN] Redis 绑定了 0.0.0.0,可能存在安全风险!"
else
    echo "[OK] Redis 绑定地址: $BIND"
fi

# 3. 检查是否禁用危险命令
DEBUG=$(redis-cli CONFIG GET rename-command | grep -c DEBUG)
if [ $DEBUG -gt 1 ]; then
    echo "[WARN] DEBUG 命令未被禁用!"
else
    echo "[OK] DEBUG 命令已禁用或重命名"
fi

# 4. 检查最大连接数
MAXCLIENTS=$(redis-cli CONFIG GET maxclients | tail -1)
echo "最大连接数: $MAXCLIENTS"

# 5. 检查保护模式
PROTECTED=$(redis-cli CONFIG GET protected-mode | tail -1)
if [ "$PROTECTED" = "yes" ]; then
    echo "[OK] 保护模式已启用"
else
    echo "[WARN] 保护模式已关闭!"
fi

# 6. 检查是否使用 root 运行
REDIS_USER=$(ps aux | grep redis-server | grep -v grep | awk '{print $1}')
if [ "$REDIS_USER" = "root" ]; then
    echo "[WARN] Redis 使用 root 用户运行!"
else
    echo "[OK] Redis 使用 $REDIS_USER 用户运行"
fi

echo ""
echo "=== 检查完成 ==="

 

5 主从复制配置

5.1 主从配置

 

# 从库配置(redis.conf)
replicaof 192.168.1.100 6379

# 或者临时执行
redis-cli REPLICAOF 192.168.1.100 6379

# 取消复制(成为独立主库)
redis-cli REPLICAOF NO ONE

 

5.2 主从配置参数

 

# 从库配置
replicaof 192.168.1.100 6379
replica-serve-stale-data yes    # 主库失联时从库是否响应读请求
replica-read-only yes           # 从库只读
repl-diskless-sync no           # 是否使用无盘复制
repl-diskless-sync-delay 5     # 无盘复制延迟
repl-disable-tcp-nodelay no    # 是否禁用 TCP_NODELAY
replica-priority 100            # 从库优先级,哨兵选举时使用

 

5.3 验证复制状态

 

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

# 输出示例
# role:master
# connected_slaves:2
# slave0:ip=192.168.1.101,port=6379,state=online,offset=12345,lag=0
# slave1:ip=192.168.1.102,port=6379,state=online,offset=12345,lag=0

# 从库视角
# role:slave
# master_host:192.168.1.100
# master_port:6379
# master_link_status:up

# 检查复制延迟
redis-cli -h  REPLICAOF NO ONE
# 然后比较两边的 DBSIZE

 

6 哨兵集群

6.1 哨兵配置

 

# sentinel.conf

# 哨兵端口
port 26379

# 哨兵监控的主节点
# sentinel monitor    
sentinel monitor mymaster 192.168.1.100 6379 2

# 密码(如果有)
sentinel auth-pass mymaster your_password

# 主节点down后多久进行故障转移
sentinel down-after-milliseconds mymaster 30000

# 故障转移超时时间
sentinel failover-timeout mymaster 180000

# 故障转移时同时同步的新从库数量
sentinel parallel-syncs mymaster 1

# 自动发现其他哨兵
sentinel monitor mymaster 192.168.1.100 6379 2
sentinel known-replica mymaster 192.168.1.101 6379
sentinel known-sentinel mymaster 192.168.1.200 26379

 

6.2 启动哨兵

 

# 启动哨兵
redis-sentinel /etc/redis/sentinel.conf

# 或者
redis-server /etc/redis/sentinel.conf --sentinel

# 查看哨兵状态
redis-cli -p 26379 INFO sentinel

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

# 查看特定主节点的详细信息
redis-cli -p 26379 SENTINEL MASTER mymaster

# 查看主节点的所有从库
redis-cli -p 26379 SENTINEL REPLICAS mymaster

 

6.3 哨兵部署建议

至少部署 3 个哨兵实例

哨兵应该部署在不同的物理机器上

哨兵数量应该 >= (2n+1),其中 n 为主库数量

quorum 设置应该为 (哨兵数量/2)+1

 

# 3 个哨兵的配置
# sentinel.conf
sentinel monitor mymaster 192.168.1.100 6379 2

# 5 个哨兵的配置
# sentinel.conf
sentinel monitor mymaster 192.168.1.100 6379 3

 

7 集群模式

7.1 Redis Cluster 配置

 

# redis.conf (集群节点配置)
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
cluster-replica-validity-factor 10
cluster-migration-barrier 1
cluster-require-full-coverage yes

 

7.2 创建集群

 

# 假设有 6 个 Redis 实例
# 3 个主库: 192.168.1.101:6379, 192.168.1.102:6379, 192.168.1.103:6379
# 3 个从库: 192.168.1.104:6379, 192.168.1.105:6379, 192.168.1.106:6379

# 创建集群
redis-cli --cluster create 
    192.168.1.101:6379 
    192.168.1.102:6379 
    192.168.1.103:6379 
    192.168.1.104:6379 
    192.168.1.105:6379 
    192.168.1.106:6379 
    --cluster-replicas 1

# 参数说明:
# --cluster-replicas 1: 每个主库配置 1 个从库

 

7.3 集群管理命令

 

# 查看集群状态
redis-cli -c -h 192.168.1.101 -p 6379 CLUSTER INFO

# 查看节点列表
redis-cli -c -h 192.168.1.101 -p 6379 CLUSTER NODES

# 查看槽分配
redis-cli -c -h 192.168.1.101 -p 6379 CLUSTER SLOTS

# 添加新节点
redis-cli --cluster add-node 192.168.1.107:6379 192.168.1.101:6379

# 添加从库
redis-cli --cluster add-node 192.168.1.108:6379 192.168.1.101:6379 --cluster-slave

# 删除节点
redis-cli --cluster del-node 192.168.1.101:6379 

# 重新分片
redis-cli --cluster reshard 192.168.1.101:6379

# 均衡槽分布
redis-cli --cluster rebalance 192.168.1.101:6379

# 故障转移
# 从库执行
redis-cli -h 192.168.1.104 -p 6379 CLUSTER FAILFAILOVER

 

7.4 集群扩缩容

 

# 扩容:添加新主库
# 1. 启动新节点
redis-server /etc/redis/redis.conf --daemonize yes

# 2. 添加到集群
redis-cli --cluster add-node 192.168.1.107:6379 192.168.1.101:6379

# 3. 重新分片(分配槽)
redis-cli --cluster reshard 192.168.1.101:6379
# 按照提示输入目标节点 ID 和槽数量

# 缩容:移除主库
# 1. 将槽迁移到其他主库
redis-cli --cluster reshard 192.168.1.101:6379
# 选择一个节点接收 192.168.1.107 的槽

# 2. 删除节点
redis-cli --cluster del-node 192.168.1.101:6379 

 

8 监控与告警

8.1 INFO 命令详解

 

# 查看所有信息
redis-cli INFO

# 查看特定 section
redis-cli INFO server      # 服务器信息
redis-cli INFO clients     # 客户端信息
redis-cli INFO memory      # 内存信息
redis-cli INFO persistence # 持久化信息
redis-cli INFO stats      # 统计信息
redis-cli INFO replication # 复制信息
redis-cli INFO cpu        # CPU 信息
redis-cli INFO commandstats # 命令统计
redis-cli INFO latencystats # 延迟统计
redis-cli INFO sentinel    # 哨兵信息

 

8.2 关键监控指标

 

# 内存使用
redis-cli INFO memory | grep -E "used_memory_human|maxmemory_human|mem_fragmentation_ratio"

# 连接数
redis-cli INFO clients
# connected_clients: 100
# blocked_clients: 0
# tracking_clients: 0

# QPS
redis-cli INFO stats | grep -E "instantaneous_ops_per_sec|total_commands_processed"

# 复制延迟
redis-cli INFO replication | grep -E "master_repl_offset|replica_offset"

# 持久化状态
redis-cli INFO persistence | grep -E "rdb_last_bgsave_status|aof_last_write_status"

 

8.3 慢查询日志

 

# 开启慢查询日志
redis-cli CONFIG SET slowlog-log-slower-than 10000  # 10ms
redis-cli CONFIG SET slowlog-max-len 128

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

# 清空慢查询
redis-cli SLOWLOG RESET

# 查看慢查询数量
redis-cli SLOWLOG LEN

 

slowlog 条目字段:

 

1) (integer) 4           # 条目 ID
2) (integer) 1609459200  # Unix 时间戳
3) (integer) 5000        # 执行时间(微秒)
4) 1) "GET"             # 命令
   2) "mykey"           # 参数
5) "127.0.0.1:12345"   # 客户端 IP

 

8.4 监控脚本

 

#!/bin/bash
# filename: redis_monitor.sh
# Redis 监控脚本

ALERT_EMAIL="ops@example.com"
REDIS_HOST="127.0.0.1"
REDIS_PORT="6379"
REDIS_PASSWORD=""

WARN_MEMORY_PCT=80
CRIT_MEMORY_PCT=90

# 获取内存使用率
MEMORY_INFO=$(redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD INFO memory 2>/dev/null)
USED=$(echo "$MEMORY_INFO" | grep used_memory: | cut -d: -f2)
MAX=$(redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD CONFIG GET maxmemory | tail -1)
MEMORY_PCT=$(echo "scale=2; $USED*100/$MAX" | bc)

echo "内存使用率: ${MEMORY_PCT}%"

if (( $(echo "$MEMORY_PCT > $CRIT_MEMORY_PCT" | bc -l) )); then
    echo "严重: 内存使用率超过 ${CRIT_MEMORY_PCT}%" | mail -s "[CRITICAL] Redis 内存告警" $ALERT_EMAIL
elif (( $(echo "$MEMORY_PCT > $WARN_MEMORY_PCT" | bc -l) )); then
    echo "警告: 内存使用率超过 ${WARN_MEMORY_PCT}%" | mail -s "[WARNING] Redis 内存告警" $ALERT_EMAIL
fi

# 检查连接数
CLIENTS=$(redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD INFO clients | grep connected_clients | cut -d: -f2)
echo "连接数: $CLIENTS"

# 检查复制延迟
REPL_LAG=$(redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD INFO replication | grep -E "master_repl_offset|replica0:offset" | tail -2)
echo "复制状态: $REPL_LAG"

# 检查持久化状态
PERSISTENCE=$(redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD INFO persistence | grep -E "rdb_last_bgsave_status|aof_last_write_status")
echo "持久化状态: $PERSISTENCE"

 

9 常见问题与解决方案

9.1 OOM(内存溢出)

现象:

 

OOM command not allowed when used memory > 'maxmemory'

 

排查:

 

# 查看内存使用
redis-cli INFO memory | grep used_memory
redis-cli CONFIG GET maxmemory

# 查看大 key
redis-cli --bigkeys

# 查看 key 统计
redis-cli --scan | head -1000 | xargs -I {} redis-cli DEBUG OBJECT ENCODING {}

 

解决:

增加 maxmemory

调整淘汰策略

清理无用数据

使用 Redis Cluster 分片

9.2 持久化失败

现象:

 

Background saving error
BGSAVE failed

 

排查:

 

# 查看最后保存状态
redis-cli INFO persistence

# 查看磁盘空间
df -h

# 查看 Redis 数据目录权限
ls -la /var/lib/redis/

 

解决:

确保磁盘空间充足

确保 Redis 用户有写权限

修改 dir 路径到有空间的分区

9.3 复制断开

现象:

 

Disconnected from master
Master link status: down

 

排查:

 

# 查看复制状态
redis-cli INFO replication

# 检查主库是否可达
telnet 192.168.1.100 6379

# 检查网络
ping -c 5 192.168.1.100

 

解决:

确保主库可达

检查防火墙设置

如果是主库挂了,等待故障转移或手动切换

9.4 响应延迟

现象:Redis 响应变慢

排查:

 

# 检查慢查询
redis-cli SLOWLOG GET 10

# 检查大 key
redis-cli --bigkeys

# 检查 CPU 使用
top -p $(pidof redis-server)

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

 

解决:

优化慢查询命令

拆分大 key

整理内存碎片

增加 Redis 实例

10 总结

10.1 生产环境检查清单

检查项 建议
maxmemory 设置为物理内存的 70-80%
淘汰策略 缓存场景用 allkeys-lru
持久化 建议同时启用 RDB 和 AOF
AOF 策略 使用 everysec 平衡性能和安全
密码 必须设置强密码
绑定地址 只监听内网 IP
危险命令 重命名或禁用
备份 每日备份,保留 7 天
监控 监控内存、连接数、QPS
日志 开启慢查询日志

10.2 推荐配置模板

 

# redis.conf 生产环境推荐配置

# 网络配置
bind 192.168.1.100
port 6379
timeout 300
tcp-keepalive 300

# 安全配置
requirepass your_strong_password
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command DEBUG ""
rename-command KEYS ""

# 内存配置
maxmemory 8gb
maxmemory-policy allkeys-lru
maxmemory-samples 5

# 持久化配置
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes

appendonly yes
appendfsync everysec
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# 内存碎片
activedefrag yes

 

10.3 运维注意事项

不要在生产环境执行 KEYS 命令:会阻塞 Redis,使用 SCAN 替代

 

# 错误
redis-cli KEYS "user:*"

# 正确
redis-cli --scan --pattern "user:*" | head -1000

 

使用连接池:避免频繁创建和销毁连接

 

# Python 示例
import redis
pool = redis.ConnectionPool(host='127.0.0.1', port=6379, password='pass', max_connections=50)
r = redis.Redis(connection_pool=pool)

 

合理设置 TTL:避免 key 永不过期导致内存持续增长

 

# 设置 24 小时过期
SET session:12345 "data" EX 86400

# 或者
EXPIRE session:12345 86400

 

定期维护:定期检查内存、连接数、慢查询等指标

Redis 部署看起来简单,但生产环境中的坑很多。希望本文能帮助大家避坑,部署出稳定可靠的 Redis 服务。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分