Redis 集群模式优化和备份策略
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">现有系统环境</a></li><li><a href="#_label1">系统参数调优建议</a></li><ul class="second_class_ul"><li><a href="#_lab2_1_0">内存管理</a></li><li><a href="#_lab2_1_1">文件句柄 & 进程数</a></li><li><a href="#_lab2_1_2">网络 / TCP 调优</a></li><li><a href="#_lab2_1_3">CPU 调度与频率</a></li><li><a href="#_lab2_1_4">I/O 子系统 (SSD) 优化</a></li><li><a href="#_lab2_1_5">日志 & 服务调优</a></li><li><a href="#_lab2_1_6">整理参数</a></li></ul><li><a href="#_label2">参数说明</a></li><ul class="second_class_ul"></ul><li><a href="#_label3">注意事项</a></li><ul class="second_class_ul"></ul><li><a href="#_label4">Redis 应用参数调优建议</a></li><ul class="second_class_ul"></ul><li><a href="#_label5">调优方案</a></li><ul class="second_class_ul"></ul><li><a href="#_label6">具体配置建议</a></li><ul class="second_class_ul"></ul><li><a href="#_label7">Redis 配置整理</a></li><ul class="second_class_ul"></ul><li><a href="#_label8">注意事项</a></li><ul class="second_class_ul"></ul><li><a href="#_label9">Redis 备份</a></li><ul class="second_class_ul"></ul><li><a href="#_label10">操作方法</a></li><ul class="second_class_ul"><li><a href="#_lab2_10_7">获取主节点列表</a></li><li><a href="#_lab2_10_8">备份所有主节点 RDB和AOF</a></li></ul><li><a href="#_label11">Redis 集群恢复 (恢复 / 回滚) 操作命令</a></li><ul class="second_class_ul"><li><a href="#_lab2_11_9">单节点恢复</a></li><li><a href="#_lab2_11_10">集群级恢复 /重新加入集群</a></li></ul><li><a href="#_label12">注意事项</a></li><ul class="second_class_ul"></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>现有系统环境</h2><ul><li><strong>操作系统</strong>:Rocky Linux release 9.5</li><li><strong>内存</strong>:16G</li><li><strong>CPU</strong>:8核心</li><li><strong>SSD 存储</strong></li></ul>
<p class="maodian"><a name="_label1"></a></p><h2>系统参数调优建议</h2>
<p class="maodian"><a name="_lab2_1_0"></a></p><h3>内存管理</h3>
<ul><li><code>vm.swappiness</code><br />将 <code>vm.swappiness</code> 降低,以减少对 swap 的依赖。默认值是较高(通常 60),可以调成 <code>10</code> 或 <code>5</code>,根据你的工作负载决定。较低值能使系统更倾向于使用内存,而不是 swap。</li></ul>
<div class="jb51code"><pre class="brush:plain;"> vm.swappiness=10</pre></div>
<p>永久设置可以写入 <code>/etc/sysctl.d/99-sysctl.conf</code> 或者 <code>/etc/sysctl.conf</code>。</p>
<ul><li><code>vm.dirty_ratio</code> 和 <code>vm.dirty_background_ratio</code><br />控制内核将多少脏页 (dirty pages) 写回磁盘。对于 SSD,可以适当调高,以减少频繁的写回,但也不能太高。<br />例如:</li></ul>
<div class="jb51code"><pre class="brush:plain;">vm.dirty_background_ratio = 5
vm.dirty_ratio = 20</pre></div>
<p>这两个值需要结合实际 I/O 压力测试。</p>
<ul><li><p><strong>关闭或限制 swap(视具体情况)</strong></p>
<ul><li>如果应用对内存需求很大、且对 swap 延迟敏感,可以考虑关闭 swap(<code>swapoff</code> +从 fstab 移除 swap)。</li><li>或者使用 zram(压缩内存)来代替 swap。</li></ul></li></ul>
<p class="maodian"><a name="_lab2_1_1"></a></p><h3>文件句柄 & 进程数</h3>
<ul><li><code>fs.file-max</code><br />提高系统能打开的最大文件描述符数</li></ul>
<div class="jb51code"><pre class="brush:plain;">fs.file-max = 2000000</pre></div>
<p>这个值要根据并发连接数和负载调整。</p>
<ul><li><strong>用户级别的 file descriptors</strong><br />修改 <code>/etc/security/limits.d/</code> 下的配置(例如 <code>99-nofile.conf</code>),对于服务账号 (如应用进程) 提高 <code>nofile</code> 限制。</li></ul>
<p class="maodian"><a name="_lab2_1_2"></a></p><h3>网络 / TCP 调优</h3>
<ul><li><code>net.core.somaxconn</code><br />增加监听 socket 的 backlog 队列长度。</li></ul>
<div class="jb51code"><pre class="brush:plain;">net.core.somaxconn = 1024</pre></div>
<ul><li><code>net.ipv4.tcp_fin_timeout</code><br />调低 TIME_WAIT 状态持续时间(视场景慎用)</li></ul>
<div class="jb51code"><pre class="brush:plain;">net.ipv4.tcp_fin_timeout = 30</pre></div>
<ul><li><code>net.ipv4.tcp_tw_reuse</code><br />允许重用处于 TIME_WAIT 的 TCP socket</li></ul>
<div class="jb51code"><pre class="brush:plain;">net.ipv4.tcp_tw_reuse = 1</pre></div>
<ul><li><strong>接收 / 发送缓冲区</strong><br />可以适当调大 <code>rmem</code> 和 <code>wmem</code>:</li></ul>
<div class="jb51code"><pre class="brush:plain;">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</pre></div>
<p class="maodian"><a name="_lab2_1_3"></a></p><h3>CPU 调度与频率</h3>
<ul><li><strong>CPU 调频策略 (governor)</strong><br />根据负载选择合适的调频策略 (governor),例如 <code>performance</code>(高性能) 或 <code>schedutil</code> / <code>ondemand</code>。如果负载是较为稳定且追求响应性,可以设置为 <code>performance</code>。</li></ul>
<div class="jb51code"><pre class="brush:plain;"># 安装 cpupower(如果还没装)
dnf install kernel-tools
# 设置 governor
cpupower frequency-set --governor performance</pre></div>
<ul><li><strong>CPU 亲和性 (Affinity)</strong>
<ul><li>对关键服务 (应用进程 /关键线程) 设置 CPU 亲和性 (affinity),使它们跑在专门的核心上,减少调度开销。</li></ul></li><li><strong>调度器调优 (Scheduler)</strong><ul><li>默认 Linux 调度器 (CFS)对大多数场景不错。如果有特殊实时或延迟敏感任务,可以深入调度器参数 (但风险较高)</li></ul></li></ul>
<p class="maodian"><a name="_lab2_1_4"></a></p><h3>I/O 子系统 (SSD) 优化</h3>
<ul><li><strong>I/O 调度器 (Scheduler)</strong><br />对于 SSD (尤其是 NVMe),推荐使用 <code>noop</code> 或 <code>mq-deadline</code> 等轻量调度器或者直接使用 <code>none</code>(如果硬件和内核版本支持)。其实在现代内核中,NVMe 的默认调度器就非常高效。</li></ul>
<div class="jb51code"><pre class="brush:bash;">echo none > /sys/block/nvme0n1/queue/scheduler</pre></div>
<p>(替换为实际使用的设备名)</p>
<ul><li><strong>队列深度 (nr_requests / queue_depth)</strong>
<ul><li>可以调优每个块设备的 I/O 队列深度 (取决于硬件)。</li></ul></li><li><strong>刷盘 (flush) 策略</strong><ul><li>根据你的 SSD 特性和写负载,可以调整 <code>dirty_*</code> 参数(见上文)以控制内核何时将缓存写回磁盘。</li></ul></li><li><strong>文件系统选择与挂载选项</strong><ul><li>如果使用 XFS / EXT4 /其他文件系统,挂载时选择适合 SSD 的 mount 参数 (如 <code>noatime</code>, <code>nodiratime</code>)。</li><li>可以考虑启用 discard / fstrim (手动或定时),但 discard 对性能的影响依设备而异。</li></ul></li></ul>
<p class="maodian"><a name="_lab2_1_5"></a></p><h3>日志 & 服务调优</h3>
<ul><li><strong>关闭或禁用不必要的 systemd 服务</strong>
<ul><li>用 <code>systemd-analyze blame</code> 查看启动和运行时开销,禁用不必要的服务。</li></ul></li><li><strong>日志轮询 /日志级别</strong><ul><li>如果日志非常频繁 (例如大量 <code>rsyslog</code> 或 <code>journal</code>),考虑减少日志写频率或级别。长期高频日志会对 SSD 写入造成压力。</li></ul></li></ul>
<p class="maodian"><a name="_lab2_1_6"></a></p><h3>整理参数</h3>
<p>一定要先备份自己系统当前的参数在修改,万一有问题方便回退。</p>
<div class="jb51code"><pre class="brush:plain;"># /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
# === 其他网络 /系统选项 ===
# 可以根据需要打开更多,但这里是基础</pre></div>
<p>应用这个配置</p>
<div class="jb51code"><pre class="brush:plain;">sysctl --system</pre></div>
<p class="maodian"><a name="_label2"></a></p><h2>参数说明</h2>
<ul><li>上面 sysctl 设置中,<code>vm.swappiness=10</code> 是为了让系统尽量少用 swap。</li><li>Redis 的 <code>maxmemory</code> 设置 (12 GB) 是示例,根据 Redis 实例所在机器上同时运行的其他进程 +操作系统需求来决定。如果 Redis 是主要服务,可以设置得更高,但建议不要占用所有内存。</li><li><code>allkeys-lru</code> 淘汰策略是业界常用策略,适合缓存 +热点数据混合类型场景。</li><li><code>lazyfree-lazy-eviction</code> 等异步释放设置,可以减少 Redis 主线程因内存回收 (删除大对象) 的阻塞。</li><li>AOF 重写策略 (<code>auto-aof-rewrite-percentage</code> 和 <code>min-size</code>) 设置,能平衡磁盘写入和文件大小。</li><li><code>hz</code> 参数 (心跳 /后台任务频率) 控制周期性后台任务 (如过期检查) 的频率。调高可以更快响应但会增加 CPU 开销。</li></ul>
<p class="maodian"><a name="_label3"></a></p><p class="maodian"><a name="_label8"></a></p><p class="maodian"><a name="_label12"></a></p><h2>注意事项</h2>
<ul><li><strong>过度调优风险</strong>:如果参数设置不当(如非常低的 <code>swappiness</code> 或非常高的 <code>dirty_ratio</code>),可能导致系统内存压力过大或频繁写盘。</li><li><strong>SSD 写寿命</strong>:调高内存中的 “脏页” 写回策略会增加写量,需要权衡。</li><li><strong>系统稳定性</strong>:部分调优 (如 CPU governor 改为 performance) 会增加功耗和温度,需要监控硬件状态。</li><li><strong>版本兼容性</strong>:不同内核版本 (RHEL / Rocky) 对某些内核参数的默认值或支持可能不一样,调优前要确认。</li><li><strong>监控覆盖盲点</strong>:调优后必须有监控和报警机制,以便及时发现调优带来的副作用。</li></ul>
<p class="maodian"><a name="_label4"></a></p><h2>Redis 应用参数调优建议</h2>
<p class="maodian"><a name="_label5"></a></p><h2>调优方案</h2>
<ul><li><strong>集群模式</strong>:Redis Cluster</li><li><strong>节点</strong>:6 节点 —— 3 主 + 3 从</li><li><strong>每节点资源</strong>:16 GB 内存,8 核 CPU</li><li><strong>业务特性</strong>:混合读写,读略多于写;有较大的缓存空间需求;容许偶尔 key 淘汰(cache 模式)</li><li><strong>持久化需求</strong>:需要 AOF + RDB 混合以兼顾数据持久性和恢复速度</li></ul>
<p class="maodian"><a name="_label6"></a></p><h2>具体配置建议</h2>
<p>下面是建议写入 <code>redis.conf</code></p>
<table><thead><tr><th>配置</th><th>建议值 / 设置</th><th>说明与理由</th><th></th></tr></thead><tbody><tr><td><code>maxmemory</code></td><td>大约 <code>48 GB</code>(64 GB 节点的 ~75%)</td><td>留出一部分给操作系统 + fork 过程中的开销。</td><td></td></tr><tr><td><code>maxmemory-policy</code></td><td><code>allkeys-lru</code></td><td>选择 LRU 淘汰策略,以便在满内存时清除最少使用的 key。</td><td></td></tr><tr><td><code>maxmemory-samples</code></td><td><code>5</code></td><td>控制 LRU 近似采样的样本数,默认是 5,通常够用。</td><td></td></tr><tr><td><code>lazyfree-lazy-eviction</code></td><td><code>yes</code></td><td>使用后台异步释放内存(异步删除),减少主线程停顿。</td><td></td></tr><tr><td><code>lazyfree-lazy-expire</code></td><td><code>yes</code></td><td>异步过期 key 的内存释放。</td><td></td></tr><tr><td><code>appendonly</code></td><td><code>yes</code></td><td>启用 AOF。保证持久性。</td><td></td></tr><tr><td><code>appendfsync</code></td><td><code>everysec</code></td><td>每秒 fsync,一般来说在可靠性与性能之间是一个比较好的折中。</td><td></td></tr><tr><td><code>auto-aof-rewrite-percentage</code></td><td><code>100</code></td><td>当 AOF 大小增长到 100%(翻倍)时触发重写。这个值可根据实际 AOF 增长速度调整。</td><td></td></tr><tr><td><code>auto-aof-rewrite-min-size</code></td><td><code>64mb</code></td><td>最小 AOF 重写大小限制(避免过小文件频繁重写)</td><td></td></tr><tr><td><code>aof-load-truncated</code></td><td><code>yes</code></td><td>启动时如果 AOF 被截断,可以继续加载(更健壮)。 ()</td><td></td></tr><tr><td><code>lua-time-limit</code></td><td><code>5000</code>(ms)</td><td>限制 Lua 脚本最大执行时间,防止长脚本阻塞。</td><td></td></tr><tr><td>集群相关</td><td></td><td></td><td></td></tr><tr><td><code>cluster-enabled</code></td><td><code>yes</code></td><td>开启集群。</td><td></td></tr><tr><td><code>cluster-config-file</code></td><td><code>nodes.conf</code>(具体路径根据部署)</td><td>保存集群节点配置。</td><td></td></tr><tr><td><code>cluster-node-timeout</code></td><td><code>15000</code>(ms)</td><td>节点互连超时阈值,较常用值。</td><td></td></tr><tr><td><code>cluster-replica-validity-factor</code></td><td><code>10</code>(默认或视情况设)</td><td>决定从节点是否有资格做 failover(与 node-timeout 和 ping 周期有关)。</td><td></td></tr><tr><td><code>cluster-migration-barrier</code></td><td><code>1</code></td><td>控制当主节点只有一个从节点时,从节点是否可以迁移到其他主上。</td><td></td></tr><tr><td><code>cluster-require-full-coverage</code></td><td><code>no</code></td><td>即使某些 slot 没覆盖,也允许读写,提升容错性。</td><td></td></tr><tr><td>网络 & 性能</td><td></td><td></td><td></td></tr><tr><td><code>timeout</code></td><td><code>3000</code>(秒或 ms,根据版本)</td><td>客户端连接超时设置(视具体版本配置)</td><td></td></tr><tr><td><code>tcp-keepalive</code></td><td><code>60</code></td><td>保持空闲连接,避免连接过早关闭。</td><td></td></tr><tr><td>慢日志</td><td><code>slowlog-log-slower-than</code></td><td>比如 <code>10000</code>(微秒或微秒级,视版本)</td><td>记录慢命令,有助于调优。</td></tr><tr><td><code>slowlog-max-len</code></td><td><code>128</code></td><td>保存慢日志条数上限。</td><td></td></tr><tr><td>数据结构内存优化</td><td></td><td></td><td></td></tr><tr><td><code>hash-max-ziplist-entries</code> / <code>hash-max-ziplist-value</code></td><td><code>512 / 64</code>(示例)</td><td>对小 hash 使用 ziplist 编码节省内存。类似配置常见于实践。 ()</td><td></td></tr><tr><td><code>list-max-ziplist-entries</code> / <code>list-max-ziplist-value</code></td><td><code>512 / 64</code></td><td>同上,对 list 优化。</td><td></td></tr><tr><td>客户端 & 连接</td><td></td><td></td><td></td></tr><tr><td>使用连接池</td><td>是</td><td>建议客户端使用连接池(如 JedisPool、Lettuce 等),避免频繁建立连接。</td><td></td></tr><tr><td>使用 Pipeline(批量命令)</td><td>是</td><td>减少往返开销。</td><td></td></tr><tr><td>命令建模</td><td></td><td></td><td></td></tr><tr><td>避免 <code>KEYS *</code></td><td>使用 <code>SCAN</code></td><td><code>KEYS</code> 是阻塞命令,在大数据量下严重影响性能。</td><td></td></tr><tr><td>优化 Lua 脚本</td><td>简短、快速</td><td>防止脚本阻塞主线程,特别是在集群中。</td><td></td></tr></tbody></table>
<p class="maodian"><a name="_label7"></a></p><h2>Redis 配置整理</h2>
<div class="jb51code"><pre class="brush:plain;">########################################
# 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 ""</pre></div>
<h2>注意事项</h2>
<ul><li><strong>fork 延迟风险</strong>:RDB 快照或 AOF 重写时会 fork,如果数据量很大,fork 可能占用大量内存 + 导致延迟波动。</li><li><strong>内存碎片</strong>:频繁删除 / 写入大对象可能导致内存碎片化。要监控 <code>used_memory_rss</code> vs <code>used_memory</code>。</li><li><strong>AOF 重写失败</strong>:如果磁盘 I/O 不够快,重写可能失败或耗时过长。</li><li><strong>误配置淘汰策略</strong>:如果设置不当(例如 <code>noeviction</code>),可能写入失败(OOM),或策略太激进导致重要数据被淘汰。</li><li><strong>客户端不 cluster-aware</strong>:如果客户端不是集群感知 (cluster-aware),可能频繁 <code>MOVED</code> 重定向,影响性能。</li><li><strong>监控盲点</strong>:如果没有全面监控,可能看不出调优的负面影响(如重写延迟、failover 异常、内存碎片)。</li></ul>
<p class="maodian"><a name="_label9"></a></p><h2>Redis 备份</h2>
<p><strong>优先备份主节点</strong></p>
<ul><li>只对主节点 (master) 做快照 /持久化备份,因为副本 (replica) 节点上只是复制,备份主节点就可以恢复完整数据。</li></ul>
<p><strong>使用 RDB (快照) + AOF 组合</strong></p>
<ul><li>RDB 用于周期性冷备 (point-in-time snapshot)。</li><li>AOF 用于更高的数据持久性 (命令日志),减少数据丢失窗口。</li><li>混合使用可以兼顾恢复速度 (RDB) 和数据完整性 (AOF)</li></ul>
<p><strong>定期触发 BGREWRITEAOF 与 BGSAVE</strong></p>
<ul><li>对 AOF 做重写 (rewrite),防止日志无限增长。</li><li>对 RDB 做快照 (BGSAVE),用于冷备</li></ul>
<p><strong>备份文件长期保留与版本管理</strong></p>
<ul><li>将 RDB/AOF 备份文件复制 /归档到异地存储 (如 NAS、对象存储)。</li><li>为备份文件打时间戳 /版本,方便恢复时回滚。</li></ul>
<p><strong>校验与恢复演练</strong></p>
<ul><li>使用 <code>redis-check-aof</code> / <code>redis-check-rdb</code> 工具校验备份文件健康性</li><li>定期做恢复演练 (集群恢复、单节点恢复) 以验证备份策略有效。</li></ul>
<p class="maodian"><a name="_label10"></a></p><h2>操作方法</h2>
<p class="maodian"><a name="_lab2_10_7"></a></p><h3>获取主节点列表</h3>
<p>获取所有主节点</p>
<div class="jb51code"><pre class="brush:bash;">/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</pre></div>
<p>这条命令会列出所有 master 节点的</p>
<p class="maodian"><a name="_lab2_10_8"></a></p><h3>备份所有主节点 RDB和AOF</h3>
<p>注意:此脚本需要现在测试环境中测试没问题 再拿到生产环境中使用。</p>
<div class="jb51code"><pre class="brush:bash;">#!/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 "=== 所有节点备份完成 ==="</pre></div>
<p class="maodian"><a name="_label11"></a></p><h2>Redis 集群恢复 (恢复 / 回滚) 操作命令</h2>
<p class="maodian"><a name="_lab2_11_9"></a></p><h3>单节点恢复</h3>
<ol><li><strong>停止要恢复的节点</strong></li></ol>
<div class="jb51code"><pre class="brush:bash;"># 或者停止对应的 Redis 服务 / systemd 单元
redis-cli -h <ip> -p <port> SHUTDOWN</pre></div>
<ol start="2"><li><strong>将备份文件 (RDB / AOF) 放回该节点的数据目录</strong></li></ol>
<div class="jb51code"><pre class="brush:bash;">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</pre></div>
<ol start="3"><li><strong>设置正确权限</strong><br />确保文件所有者和权限与 Redis 进程一致,比如:</li></ol>
<div class="jb51code"><pre class="brush:bash;">chown redis:redis /var/lib/redis/$port/dump.rdb
chown redis:redis /var/lib/redis/$port/appendonly.aof</pre></div>
<ul><li><strong>启动 Redis 节点</strong>
<ul><li>启动 Redis,查看日志确认是否加载了 RDB / AOF。</li></ul></li><li>如果优先加载 AOF:在 redis.conf 中 <code>appendonly yes</code>,那么 Redis 启动时会优先用 AOF 恢复<ul><li>如果你先还原 RDB,再开 AOF,可以临时关闭 AOF,加载 RDB 后再打开</li></ul></li></ul>
<p>具体命令 (如果是 systemd):</p>
<div class="jb51code"><pre class="brush:bash;">systemctl start redis</pre></div>
<ol start="5"><li><strong>(可选)触发 BGREWRITEAOF</strong></li></ol>
<div class="jb51code"><pre class="brush:bash;">redis-cli -h <ip> -p <port> BGREWRITEAOF</pre></div>
<p class="maodian"><a name="_lab2_11_10"></a></p><h3>集群级恢复 /重新加入集群</h3>
<p>恢复一个节点之后,如果这个节点之前属于集群 (有 slot),你需要让它重新加入 (如果它是孤立恢复):</p>
<ol><li>与集群中的一个存活节点做 <code>CLUSTER MEET</code></li></ol>
<div class="jb51code"><pre class="brush:plain;">redis-cli -h <恢复节点 IP> -p <恢复节点 端口> CLUSTER MEET <任意健康节点 IP> <端口></pre></div>
<ol start="2"><li><strong>确认节点状态</strong><br />在恢复节点上运行:</li></ol>
<div class="jb51code"><pre class="brush:plain;">redis-cli -h <恢复节点 IP> -p <恢复端口> CLUSTER NODES</pre></div>
<p>看它是否成为了集群的一员 (节点状态应该是 <code>slave</code> 或 <code>master</code> 等)。</p>
<ul><li><strong>如果恢复的是主节点,并且有 slot,需要重新分配 slot</strong>
<ul><li>如果是原来的 master,要把 slot 分回去 (如果 slot 被迁移了)。</li><li>使用 <code>redis-cli --cluster reshard</code> 进行 slot 重分布 (reshard):将部分 slot 从其他节点迁移给该节点。</li></ul></li></ul>
<div class="jb51code"><pre class="brush:plain;">redis-cli --cluster reshard <一个集群节点 IP:端口> --from <其他节点列表,用逗号分隔> --to <恢复节点 id> --slots <slot 数量> --yes</pre></div>
<h2>注意事项</h2>
<ul><li><strong>恢复时间</strong>:如果集群节点很多、数据量大,恢复 (尤其是 AOF 重写) 可能比较慢。</li><li><strong>数据一致性</strong>:如果只是用 RDB 快照恢复,可能丢失最后一次快照后的写入。AOF 可以减少但也不能保证零丢失 (取决于 <code>appendfsync</code> 策略)。</li><li><strong>重写 (rewrite) 期间性能影响</strong>:AOF 重写是 fork 子进程,会占用内存和 CPU。</li><li><strong>磁盘空间</strong>:备份 RDB + AOF 文件可能占用大量磁盘空间,备份存储要规划好。</li><li><strong>安全</strong>:备份文件 (RDB / AOF) 本身也很敏感,应保证备份存储路径权限、安全传输 (如 SFTP、对象存储加密)。</li></ul>
頁:
[1]