Skip to content
清晨的一缕阳光
返回

Redis 持久化性能优化

Redis 持久化性能优化

持久化是 Redis 数据安全的基础,但不当的配置会严重影响性能。本文将深入持久化性能优化,分享实战经验。

一、性能影响分析

1.1 RDB 性能影响

RDB 的性能开销

RDB 触发流程:
1. fork() 子进程(阻塞主线程)
2. 子进程写磁盘(不阻塞)
3. 父进程继续服务(可能受 fork 影响)

性能影响点:
┌─────────────────────────────────────┐
│ fork() 阻塞                         │
│ - 数据量越大,阻塞越久               │
│ - 典型值:1GB 数据约 10-30ms        │
├─────────────────────────────────────┤
│ 写磁盘 IO 竞争                      │
│ - 子进程写 RDB 文件                  │
│ - 可能影响主进程 IO                  │
├─────────────────────────────────────┤
│ 内存开销                            │
│ - fork 使用 COW(写时复制)          │
│ - 写操作频繁时,内存消耗增加         │
└─────────────────────────────────────┘

测试数据

数据量fork 时间推荐触发间隔
1GB~10ms每小时
5GB~50ms每 2 小时
10GB~100ms每 4 小时
50GB~500ms每天

1.2 AOF 性能影响

AOF 的性能开销

AOF 写入流程:
1. 命令写入 AOF 缓冲区
2. 根据 appendfsync 策略刷盘
3. AOF 重写(定期)

性能影响点:
┌─────────────────────────────────────┐
│ 命令写入开销                        │
│ - 每次写操作都要记录 AOF            │
│ - 增加约 5-10% 延迟                 │
├─────────────────────────────────────┤
│ 刷盘开销(appendfsync)             │
│ - always:每次写操作都 fsync        │
│ - everysec:每秒 fsync(推荐)       │
│ - no:由 OS 决定                    │
├─────────────────────────────────────┤
│ AOF 重写开销                        │
│ - fork 子进程重写                   │
│ - 类似 RDB 的 fork 阻塞             │
└─────────────────────────────────────┘

appendfsync 性能对比

# 测试命令
redis-benchmark -q -t set -n 100000

# appendfsync always
# SET: 10000.00 requests per second (最慢)

# appendfsync everysec
# SET: 80000.00 requests per second (推荐)

# appendfsync no
# SET: 100000.00 requests per second (最快)

1.3 混合持久化性能

混合持久化的优势

混合持久化性能特点:
1. AOF 重写时,前半部分写 RDB(快速)
2. 后半部分写增量命令(少量)
3. 总体比重写纯 AOF 快 30-50%

性能对比(10GB 数据):
┌─────────────────────────────────────┐
│ 纯 AOF 重写:~300 秒                │
│ 混合持久化:~180 秒                 │
│ 提升:约 40%                        │
└─────────────────────────────────────┘

二、配置优化

2.1 RDB 优化配置

# ==================== 优化 save 配置 ====================

# 避免过于频繁的保存
# 不推荐:save 60 1000(太频繁)
# 推荐:
save 900 1        # 15 分钟至少 1 个键变化
save 300 10       # 5 分钟至少 10 个键变化
save 60 10000     # 1 分钟至少 10000 个键变化

# 或者完全关闭自动保存,手动触发
# save ""

# ==================== 优化 RDB 文件名 ====================

dbfilename dump.rdb

# ==================== 优化工作目录 ====================

# 使用 SSD 硬盘
dir /data/redis/ssd

# ==================== 压缩优化 ====================

# 开启 RDB 压缩(默认开启)
rdbcompression yes

# 压缩算法(Redis 5.0+)
# lzf:快速,压缩率低
# zstd:慢速,压缩率高
rdbcompression lzf

# ==================== 校验和 ====================

# 开启 RDB 校验和(轻微性能影响)
rdbchecksum yes

2.2 AOF 优化配置

# ==================== 基础配置 ====================

# 开启 AOF
appendonly yes

# AOF 文件名
appendfilename "appendonly.aof"

# AOF 目录(Redis 7.0+)
appenddirname "appendonlydir"

# ==================== 刷盘策略(关键) ====================

# 推荐:everysec(平衡性能和安全)
appendfsync everysec

# 高性能场景:no(可能丢失数据)
# appendfsync no

# 高安全场景:always(性能最低)
# appendfsync always

# ==================== 重写优化 ====================

# 重写期间不 fsync(避免 IO 竞争)
no-appendfsync-on-rewrite yes

# 自动重写触发条件
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 128mb

# ==================== 混合持久化 ====================

# 开启混合持久化(Redis 4.0+)
aof-use-rdb-preamble yes

# 加载截断的 AOF 文件
aof-load-truncated yes

# ==================== 重写触发优化 ====================

# 根据业务调整重写阈值
# 写操作频繁:提高阈值
auto-aof-rewrite-percentage 200
auto-aof-rewrite-min-size 512mb

# 写操作少:降低阈值
auto-aof-rewrite-percentage 50
auto-aof-rewrite-min-size 64mb

2.3 混合持久化优化

# 最佳实践配置

# 开启 AOF
appendonly yes

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

# 每秒刷盘
appendfsync everysec

# 重写期间不 fsync
no-appendfsync-on-rewrite yes

# 合理设置重写阈值
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 256mb

# 允许加载不完整 AOF
aof-load-truncated yes

三、系统调优

3.1 磁盘 IO 优化

# ==================== 使用 SSD ====================

# 检查磁盘类型
lsblk -d -o name,rota
# 0 = SSD, 1 = HDD

# 查看磁盘性能
iostat -x 1

# ==================== 文件系统优化 ====================

# 使用 ext4 或 xfs
# 挂载选项优化
mount -o noatime,nodiratime,data=writeback /dev/sda1 /data

# /etc/fstab 配置
/dev/sda1  /data  xfs  noatime,nodiratime  0  0

# ==================== IO 调度器优化 ====================

# 查看当前调度器
cat /sys/block/sda/queue/scheduler
# 输出:[mq-deadline] kyber bfq none

# 设置为 none(SSD 推荐)
echo none > /sys/block/sda/queue/scheduler

# 永久生效
# /etc/default/grub
GRUB_CMDLINE_LINUX="elevator=none"
update-grub

# ==================== 预读取优化 ====================

# 减少预读取(Redis 是随机访问)
blockdev --setra 256 /dev/sda

# 查看当前值
blockdev --getra /dev/sda

3.2 内存优化

# ==================== 透明大页 ====================

# 禁用透明大页(避免 fork 延迟)
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

# 永久生效
# /etc/rc.local
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

# ==================== 过度分配 ====================

# 允许过度分配(避免 fork 失败)
echo 1 > /proc/sys/vm/overcommit_memory

# 永久生效
# /etc/sysctl.conf
vm.overcommit_memory = 1

# ==================== 交换空间 ====================

# 禁用 swap(或设置 swappiness=0)
sysctl vm.swappiness=0
swapoff -a

# 永久生效
# /etc/sysctl.conf
vm.swappiness = 0

3.3 网络优化

# ==================== TCP 参数 ====================

# /etc/sysctl.conf

# 增加 backlog
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 8192

# 快速回收
net.ipv4.tcp_tw_reuse = 1

# 保持连接
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 60
net.ipv4.tcp_keepalive_probes = 3

# 应用配置
sysctl -p

四、监控与诊断

4.1 关键指标监控

#!/bin/bash
# monitor_persistence.sh

REDIS_HOST="127.0.0.1"
REDIS_PORT="6379"

# 获取持久化信息
INFO=$(redis-cli -h $REDIS_HOST -p $REDIS_PORT INFO Persistence)

# 提取关键指标
RDB_CHANGES=$(echo "$INFO" | grep "rdb_changes_since_last_save" | cut -d: -f2 | tr -d '\r')
RDB_LAST_TIME=$(echo "$INFO" | grep "rdb_last_save_time" | cut -d: -f2 | tr -d '\r')
RDB_LAST_STATUS=$(echo "$INFO" | grep "rdb_last_bgsave_status" | cut -d: -f2 | tr -d '\r')
RDB_LAST_TIME_SEC=$(echo "$INFO" | grep "rdb_last_bgsave_time_sec" | cut -d: -f2 | tr -d '\r')

AOF_ENABLED=$(echo "$INFO" | grep "aof_enabled" | cut -d: -f2 | tr -d '\r')
AOF_REWRITE=$(echo "$INFO" | grep "aof_rewrite_in_progress" | cut -d: -f2 | tr -d '\r')
AOF_LAST_TIME=$(echo "$INFO" | grep "aof_last_rewrite_time_sec" | cut -d: -f2 | tr -d '\r')
AOF_CUR_SIZE=$(echo "$INFO" | grep "aof_current_size" | cut -d: -f2 | tr -d '\r')

echo "=== RDB 指标 ==="
echo "上次保存后变化:$RDB_CHANGES"
echo "上次保存时间:$(date -d @$RDB_LAST_TIME)"
echo "上次保存状态:$RDB_LAST_STATUS"
echo "上次保存耗时:${RDB_LAST_TIME_SEC}秒"

echo ""
echo "=== AOF 指标 ==="
echo "AOF 开启:$AOF_ENABLED"
echo "重写进行中:$AOF_REWRITE"
echo "上次重写耗时:${AOF_LAST_TIME}秒"
echo "当前文件大小:$(($AOF_CUR_SIZE / 1024 / 1024))MB"

# 告警检查
if [ "$RDB_LAST_STATUS" != "ok" ]; then
    echo "⚠️  告警:RDB 保存失败"
fi

if [ "$RDB_LAST_TIME_SEC" -gt 300 ]; then
    echo "⚠️  告警:RDB 保存时间过长(>${RDB_LAST_TIME_SEC}秒)"
fi

if [ "$AOF_LAST_TIME" -gt 300 ]; then
    echo "⚠️  告警:AOF 重写时间过长(>${AOF_LAST_TIME}秒)"
fi

if [ "$AOF_CUR_SIZE" -gt 1073741824 ]; then
    echo "⚠️  告警:AOF 文件过大(>1GB)"
fi

4.2 慢查询监控

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

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

# 输出示例
# 1) 1) (integer) 123
#    2) (integer) 1730793600
#    3) (integer) 15000
#    4) 1) "BGSAVE"
#    5) "127.0.0.1:6379"
#    6) ""
#    7) ""

# 分析慢查询
redis-cli SLOWLOG LEN
redis-cli SLOWLOG RESET

4.3 延迟监控

#!/bin/bash
# latency_monitor.sh

REDIS_HOST="127.0.0.1"
REDIS_PORT="6379"

echo "开始延迟监控(按 Ctrl+C 停止)..."

while true; do
    # 测量 PING 延迟
    START=$(date +%s%N)
    redis-cli -h $REDIS_HOST -p $REDIS_PORT PING > /dev/null
    END=$(date +%s%N)
    
    LATENCY=$((($END - $START) / 1000000))
    
    # 测量 SET 延迟
    START=$(date +%s%N)
    redis-cli -h $REDIS_HOST -p $REDIS_PORT SET __latency_test__ test > /dev/null
    END=$(date +%s%N)
    
    SET_LATENCY=$((($END - $START) / 1000000))
    
    # 清理
    redis-cli -h $REDIS_HOST -p $REDIS_PORT DEL __latency_test__ > /dev/null
    
    echo "$(date '+%Y-%m-%d %H:%M:%S') - PING: ${LATENCY}ms, SET: ${SET_LATENCY}ms"
    
    # 告警
    if [ $LATENCY -gt 10 ]; then
        echo "⚠️  PING 延迟过高:${LATENCY}ms"
    fi
    
    if [ $SET_LATENCY -gt 20 ]; then
        echo "⚠️  SET 延迟过高:${SET_LATENCY}ms"
    fi
    
    sleep 1
done

4.4 使用 Redis 内置延迟监控

# Redis 2.8.13+ 提供延迟监控工具

# 延迟监控
redis-cli --latency

# 历史记录
redis-cli --latency-history -i 1

# 延迟分布
redis-cli --latency-dist

# 测试延迟
redis-cli --test-memory 1024

五、最佳实践

5.1 配置建议

# 生产环境推荐配置

# RDB 配置
save 900 1
save 300 10
save 60 10000
rdbcompression yes
rdbchecksum yes

# AOF 配置
appendonly yes
appendfsync everysec
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 256mb

# 混合持久化
aof-use-rdb-preamble yes
aof-load-truncated yes

5.2 运维建议

  1. 定期检查持久化状态

    # 每天检查
    redis-cli INFO Persistence
    
    # 检查 RDB 文件
    redis-check-rdb dump.rdb
    
    # 检查 AOF 文件
    redis-check-aof appendonly.aof
  2. 定期备份

    # 备份脚本
    # /usr/local/bin/redis-backup.sh
    
    BACKUP_DIR="/backup/redis"
    DATE=$(date +%Y%m%d_%H%M%S)
    
    # 触发 BGSAVE
    redis-cli BGSAVE
    
    # 等待完成
    sleep 5
    
    # 复制 RDB
    cp /var/lib/redis/dump.rdb $BACKUP_DIR/dump_$DATE.rdb
    
    # 删除 7 天前备份
    find $BACKUP_DIR -name "dump_*.rdb" -mtime +7 -delete
    
    # 添加到 crontab
    # 0 2 * * * /usr/local/bin/redis-backup.sh
  3. 性能基准测试

    # 定期性能测试
    redis-benchmark -q -t set,get -n 100000 -c 50
    
    # 记录结果,对比历史数据
  4. 监控告警

    • RDB/AOF 失败告警
    • 持久化时间过长告警
    • AOF 文件过大告警
    • 延迟过高告警

5.3 故障处理

# 问题 1:RDB 保存失败
# 解决:检查磁盘空间、权限
df -h
ls -la /var/lib/redis/

# 问题 2:AOF 文件增长过快
# 解决:调整重写阈值
redis-cli CONFIG SET auto-aof-rewrite-percentage 200
redis-cli CONFIG SET auto-aof-rewrite-min-size 512mb

# 问题 3:fork 时间过长
# 解决:减少数据量、优化内存
# - 设置 maxmemory
# - 使用内存淘汰策略
redis-cli CONFIG SET maxmemory 4gb
redis-cli CONFIG SET maxmemory-policy allkeys-lru

# 问题 4:写延迟高
# 解决:调整刷盘策略
redis-cli CONFIG SET appendfsync everysec
# 或(如果可以接受数据丢失)
redis-cli CONFIG SET appendfsync no

六、总结

6.1 性能优化要点

  1. RDB 优化

    • 合理设置 save 条件
    • 使用 SSD 硬盘
    • 避免频繁 fork
  2. AOF 优化

    • 选择合适刷盘策略(推荐 everysec)
    • 开启混合持久化
    • 合理设置重写阈值
  3. 系统优化

    • 禁用透明大页
    • 允许过度分配
    • 优化 IO 调度器

6.2 性能基准

配置QPS延迟数据安全性
appendfsync always10k~1ms最高
appendfsync everysec80k~1ms
appendfsync no100k~0.5ms
无持久化120k~0.3ms

参考资料


分享这篇文章到:

上一篇文章
企业级 RAG 系统架构设计
下一篇文章
Kafka 监控体系与可观测性实战