Redis

关注公众号 jb51net

关闭
首页 > 数据库 > Redis > redis 集群模式

Redis 集群模式优化和备份策略

作者:文静小土豆

本文主要介绍了Linux系统和Redis集群模式的优化和备份策略,在Linux系统优化方面,重点介绍了内存管理、文件句柄、网络/TCP调优、CPU调度和频率、I/O子系统等参数的调整建议,感兴趣的朋友跟随小编一起看看吧

现有系统环境

系统参数调优建议

内存管理

 vm.swappiness=10

永久设置可以写入 /etc/sysctl.d/99-sysctl.conf 或者 /etc/sysctl.conf

vm.dirty_background_ratio = 5
vm.dirty_ratio = 20

这两个值需要结合实际 I/O 压力测试。

文件句柄 & 进程数

fs.file-max = 2000000

这个值要根据并发连接数和负载调整。

网络 / TCP 调优

net.core.somaxconn = 1024
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_tw_reuse = 1
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

CPU 调度与频率

# 安装 cpupower(如果还没装)
dnf install kernel-tools
# 设置 governor
cpupower frequency-set --governor performance

I/O 子系统 (SSD) 优化

echo none > /sys/block/nvme0n1/queue/scheduler

(替换为实际使用的设备名)

日志 & 服务调优

整理参数

一定要先备份自己系统当前的参数在修改,万一有问题方便回退。

# /etc/sysctl.d/99-performance.conf
# === 内存管理 ===
vm.swappiness = 10
vm.dirty_ratio = 20
vm.dirty_background_ratio = 5
# 可能还加 dirty_expire / writeback,根据具体测试调优
# vm.dirty_expire_centisecs = 500
# vm.dirty_writeback_centisecs = 100
# 可选:如果你知道内存不是特别紧张,可设置 overcommit
# vm.overcommit_memory = 1
# === 文件句柄限制 ===
fs.file-max = 2000000
# === 网络 / TCP 参数 ===
net.core.somaxconn = 8192  # 监听 backlog
net.core.netdev_max_backlog = 50000
# 接收 / 发送缓冲
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096   87380   16777216
net.ipv4.tcp_wmem = 4096   65536   16777216
# TIME_WAIT 和连接重用
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_tw_reuse = 1
# Keepalive
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
# 网络安全相关
kernel.sysrq = 0
net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_source_route  =0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.tcp_syncookies = 1
kernel.dmesg_restrict = 1
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
kernel.threads-max = 655350
# === 其他网络 /系统选项 ===
# 可以根据需要打开更多,但这里是基础

应用这个配置

sysctl --system

参数说明

注意事项

Redis 应用参数调优建议

调优方案

具体配置建议

下面是建议写入 redis.conf

配置建议值 / 设置说明与理由
maxmemory大约 48 GB(64 GB 节点的 ~75%)留出一部分给操作系统 + fork 过程中的开销。
maxmemory-policyallkeys-lru选择 LRU 淘汰策略,以便在满内存时清除最少使用的 key。
maxmemory-samples5控制 LRU 近似采样的样本数,默认是 5,通常够用。
lazyfree-lazy-evictionyes使用后台异步释放内存(异步删除),减少主线程停顿。
lazyfree-lazy-expireyes异步过期 key 的内存释放。
appendonlyyes启用 AOF。保证持久性。
appendfsynceverysec每秒 fsync,一般来说在可靠性与性能之间是一个比较好的折中。
auto-aof-rewrite-percentage100当 AOF 大小增长到 100%(翻倍)时触发重写。这个值可根据实际 AOF 增长速度调整。
auto-aof-rewrite-min-size64mb最小 AOF 重写大小限制(避免过小文件频繁重写)
aof-load-truncatedyes启动时如果 AOF 被截断,可以继续加载(更健壮)。 ([codingnote.cc][3])
lua-time-limit5000(ms)限制 Lua 脚本最大执行时间,防止长脚本阻塞。
集群相关
cluster-enabledyes开启集群。
cluster-config-filenodes.conf(具体路径根据部署)保存集群节点配置。
cluster-node-timeout15000(ms)节点互连超时阈值,较常用值。
cluster-replica-validity-factor10(默认或视情况设)决定从节点是否有资格做 failover(与 node-timeout 和 ping 周期有关)。
cluster-migration-barrier1控制当主节点只有一个从节点时,从节点是否可以迁移到其他主上。
cluster-require-full-coverageno即使某些 slot 没覆盖,也允许读写,提升容错性。
网络 & 性能
timeout3000(秒或 ms,根据版本)客户端连接超时设置(视具体版本配置)
tcp-keepalive60保持空闲连接,避免连接过早关闭。
慢日志slowlog-log-slower-than比如 10000(微秒或微秒级,视版本)记录慢命令,有助于调优。
slowlog-max-len128保存慢日志条数上限。
数据结构内存优化
hash-max-ziplist-entries / hash-max-ziplist-value512 / 64(示例)对小 hash 使用 ziplist 编码节省内存。类似配置常见于实践。 ([CNDBA][4])
list-max-ziplist-entries / list-max-ziplist-value512 / 64同上,对 list 优化。
客户端 & 连接
使用连接池建议客户端使用连接池(如 JedisPool、Lettuce 等),避免频繁建立连接。
使用 Pipeline(批量命令)减少往返开销。
命令建模
避免 KEYS *使用 SCANKEYS 是阻塞命令,在大数据量下严重影响性能。
优化 Lua 脚本简短、快速防止脚本阻塞主线程,特别是在集群中。

Redis 配置整理

########################################
# Redis 性能 +集群 配置示例
# 这个配置文件只做参考 不能直接拿来用 Redis 是不允许再参数后买你添加注释的直接使用会报错
########################################
# 内存管理
maxmemory 12gb           # 假设节点内存 16G,为 Redis 留约 12G
maxmemory-policy allkeys-lru   # 使用 LRU 淘汰所有键(适合缓存 + 数据混合场景)
maxmemory-samples 5
# 延迟释放
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
lazyfree-lazy-server-del yes
# 持久化 (RDB + AOF)
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
# RDB 快照 (可根据需要)
save 900 1
save 300 10
save 60 10000
# 集群配置 (如果是 Redis Cluster)
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 no
# 性能 /调度相关
hz 10
dynamic-hz yes
# Lua 脚本执行限制
lua-time-limit 5000  # 毫秒
# 慢日志 (监控慢命令)
slowlog-log-slower-than 10000   # 微秒 (10 ms) — 根据业务调整
slowlog-max-len 128
# 内存碎片 / 编码优化
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
# 安全性 (可选,根据场景启用)
# requirepass yourpassword
# rename-command FLUSHALL ""
# 其他 (可选,根据需求)
notify-keyspace-events ""

注意事项

Redis 备份

优先备份主节点

使用 RDB (快照) + AOF 组合

定期触发 BGREWRITEAOF 与 BGSAVE

备份文件长期保留与版本管理

校验与恢复演练

操作方法

获取主节点列表

获取所有主节点

/usr/local/redis/bin/redis-cli -h 192.168.1.11 -p 6379 -a ugwFsSNuzgS4e62e CLUSTER NODES|grep master | grep -v "fail" | awk '{print $2}' | cut -d@ -f1

这条命令会列出所有 master 节点的

备份所有主节点 RDB和AOF

注意:此脚本需要现在测试环境中测试没问题 再拿到生产环境中使用。

#!/bin/bash
REDIS_IP="192.168.1.11"         # 任意一个集群节点(用于获取节点列表)
REDIS_PORT="6379"
REDIS_PWD="ugwFsSNuzgS4e62e"
BACKUP_DIR="/root/backup/"
TIMEOUT=300  
mkdir -p "$BACKUP_DIR" || { echo "ERROR: 无法创建备份目录 $BACKUP_DIR"; exit 1; }
# 获取所有 master 节点
nodes=$(redis-cli -c -h "$REDIS_IP" -p "$REDIS_PORT" -a "$REDIS_PWD" CLUSTER NODES | \
  grep master | grep -v fail | awk '{print $2}' | cut -d@ -f1)
for node in $nodes; do
  ip=$(echo "$node" | cut -d: -f1)
  port=$(echo "$node" | cut -d: -f2)
  echo "=== 开始备份:Redis 节点 $ip:$port ==="
  # 触发 BGSAVE (RDB)
  redis-cli -h "$ip" -p "$port" -a "$REDIS_PWD" BGSAVE
  if [ $? -ne 0 ]; then
    echo "WARNING: BGSAVE 在 $ip:$port 执行失败"
  fi
  # 等待 BGSAVE 完成
  start_time=$(date +%s)
  while true; do
    inprog=$(redis-cli -h "$ip" -p "$port" -a "$REDIS_PWD" INFO persistence | \
      grep rdb_bgsave_in_progress | cut -d: -f2 | tr -d '\r')
    if [ "$inprog" = "0" ]; then
      echo "BGSAVE 完成:$ip:$port"
      break
    fi
    now=$(date +%s)
    elapsed=$(( now - start_time ))
    if [ $elapsed -gt $TIMEOUT ]; then
      echo "ERROR: BGSAVE 超时 ($elapsed 秒) 在 $ip:$port" >&2
      break
    fi
    echo "等待 BGSAVE 完成 ($elapsed 秒) ..."
    sleep 5
  done
  # 获取 RDB 文件路径
  DIR=$(redis-cli -h "$ip" -p "$port" -a "$REDIS_PWD" CONFIG GET dir | awk 'NR==2')
  DBFILE=$(redis-cli -h "$ip" -p "$port" -a "$REDIS_PWD" CONFIG GET dbfilename | awk 'NR==2')
  src_rdb="${DIR}/${DBFILE}"
  if [ ! -f "$src_rdb" ]; then
    echo "ERROR: 未找到 RDB 文件: $src_rdb" >&2
  else
    dst_rdb="${BACKUP_DIR}/${ip}_${port}_$(date +%Y%m%d_%H%M%S).rdb"
    cp "$src_rdb" "$dst_rdb" && echo "RDB 备份保存到 $dst_rdb"
  fi
  aof_enabled=$(redis-cli -h "$ip" -p "$port" -a "$REDIS_PWD" CONFIG GET appendonly | awk 'NR==2')
  if [ "$aof_enabled" = "yes" ]; then
    AOFDIR=$(redis-cli -h "$ip" -p "$port" -a "$REDIS_PWD" CONFIG GET appenddirname | awk 'NR==2')
    AOFNAME=$(redis-cli -h "$ip" -p "$port" -a "$REDIS_PWD" CONFIG GET appendfilename | awk 'NR==2')
    if [ -z "$AOFDIR" ]; then
      src_aof="${DIR}/${AOFNAME}"
      if [ -f "$src_aof" ]; then
        dst_aof="${BACKUP_DIR}/${ip}_${port}_$(date +%Y%m%d_%H%M%S).aof"
        cp "$src_aof" "$dst_aof" && echo "AOF 备份保存到 $dst_aof"
      else
        echo "ERROR: AOF 文件未找到: $src_aof" >&2
      fi
    else
      # Multi-Part AOF 模式 (Redis 7+)
      aof_dir_full="${DIR}/${AOFDIR}"
      if [ -d "$aof_dir_full" ]; then
        dst_mp_dir="${BACKUP_DIR}/${ip}_${port}_AOF_$(date +%Y%m%d_%H%M%S)"
        mkdir -p "$dst_mp_dir"
        cp "${aof_dir_full}"/* "$dst_mp_dir"/ && echo "MP-AOF 备份到 $dst_mp_dir"
      else
        echo "ERROR: AOF 目录不存在: $aof_dir_full" >&2
      fi
    fi
  else
    echo "AOF 未启用在 $ip:$port,跳过 AOF 备份"
  fi
done
echo "=== 所有节点备份完成 ==="

Redis 集群恢复 (恢复 / 回滚) 操作命令

单节点恢复

  1. 停止要恢复的节点
# 或者停止对应的 Redis 服务 / systemd 单元
redis-cli -h <ip> -p <port> SHUTDOWN
  1. 将备份文件 (RDB / AOF) 放回该节点的数据目录
cp /backup/redis/cluster/<ip>_<port>_YYYYMMDD_HHMMSS.rdb /var/lib/redis/$port/dump.rdb
# 如果是 aof
cp /backup/redis/cluster/<ip>_<port>_YYYYMMDD_HHMMSS.aof /var/lib/redis/$port/appendonly.aof
  1. 设置正确权限
    确保文件所有者和权限与 Redis 进程一致,比如:
chown redis:redis /var/lib/redis/$port/dump.rdb
chown redis:redis /var/lib/redis/$port/appendonly.aof

具体命令 (如果是 systemd):

systemctl start redis
  1. (可选)触发 BGREWRITEAOF
redis-cli -h <ip> -p <port> BGREWRITEAOF

集群级恢复 /重新加入集群

恢复一个节点之后,如果这个节点之前属于集群 (有 slot),你需要让它重新加入 (如果它是孤立恢复):

  1. 与集群中的一个存活节点做 CLUSTER MEET
redis-cli -h <恢复节点 IP> -p <恢复节点 端口> CLUSTER MEET <任意健康节点 IP> <端口>
  1. 确认节点状态
    在恢复节点上运行:
redis-cli -h <恢复节点 IP> -p <恢复端口> CLUSTER NODES

看它是否成为了集群的一员 (节点状态应该是 slavemaster 等)。

redis-cli --cluster reshard <一个集群节点 IP:端口> --from <其他节点列表,用逗号分隔> --to <恢复节点 id> --slots <slot 数量> --yes

注意事项

到此这篇关于Redis 集群模式优化和备份的文章就介绍到这了,更多相关redis 集群模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文