香港CN2链路下的备份军规:从物理冷备到逻辑热备的4ms延迟生死线
别急着看命令。先搞清楚一个事实:香港CN2服务器最大的优势是回程延迟低,但低延迟意味着你的备份架构必须重新设计。很多团队把内地IDC的备份思路原封不动搬过来,结果在跨境链路上跑出几百GB的垃圾流量,最后连rm都不敢执行。
我在轻云互联的一台香港CN2节点上做过一次彻底的备份体系重构。不是简单的换工具,而是把备份链路当作生产链路来调优。下面是我最终沉淀下来的三套方案,分别对应MySQL实例、Redis集群、以及海量小文件归档场景。
**第一刀:MySQL物理备份——XtraBackup的并行度陷阱**
很多教程会告诉你`--parallel=8`,但没人告诉你CN2链路上INNODB的redo log归档速度和物理文件复制速度存在严重的不匹配。如果`--parallel`设置过高,`xtrabackup`会在拷贝ibd文件时抢占所有磁盘IO,导致redo log线程饿死,最终报`log scanned up to` 异常。
正确的做法是分级并行。一级并行控制数据文件复制,二级并行控制压缩。
```bash
# 推荐:物理备份 + 流式压缩 + 加密,全程不落盘
xtrabackup --backup \
--slave-info \
--safe-slave-backup \
--parallel=4 \
--compress=zstd \
--compress-threads=2 \
--stream=xbstream \
--encrypt=AES256 \
--encrypt-key-file=/etc/backup/keyfile \
--target-dir=/data/backup/xtra | \
ssh -c aes128-gcm@sha256 -o Compression=no backup@10.0.0.2 "cat > /backup/$(date +%F_%H).xbstream"
```
注意这里的`--safe-slave-backup`。在香港CN2的高延迟环境下,如果你从从库备份,这个参数能保证复制线程在备份期间不落后太多。同时在SSH连接上必须禁用压缩,因为`zstd`已经做完了,再压一次纯属浪费CPU。
另外一个关键点:`innodb_buffer_pool_dump` 必须单独做,不要依赖`xtrabackup`。因为后者只备份数据文件,不触发buffer pool预热。很多人在大陆机房没感觉,但香港到内地的RTT哪怕只有40ms,buffer pool冷启动的代价也是致命的。
**第二刀:逻辑备份——mydumper的chunk机制与NEJ调度**
对于必须做逻辑备份的库(比如需要跨版本恢复),千万别用mysqldump。`mydumper`配合`--chunk-filesize` 比默认的`row`模式更稳。但在CN2链路下,最大的瓶颈不是导出速度,而是**insert语句的batch大小**。
直接上我的压箱底配置:
```bash
mydumper \
--host=127.0.0.1 \
--user=backup \
--password=*** \
--database=shop \
--outputdir=/data/backup/shop \
--threads=6 \
--chunk-filesize=256 \
--rows=500000 \
--trx-consistency-only \
--compress \
--build-empty-files \
--long-query-guard=300 \
--kill-long-queries
```
`--trx-consistency-only` 是关键。它只开启一个短暂的只读事务来获取一致性快照,而不是`--lock-all-tables`那种粗暴的全库锁定。在跨境链路上,锁表时间每延长1秒,主从延迟就多跳一个数量级。
另外,一定要盯死`--long-query-guard`。香港机房的网络抖动会导致mydumper的元数据锁等待时间异常拉长,如果超过300秒,直接杀掉查询,备份失败也比拖垮生产库强。
**第三刀:海量小文件归档——inotify+restic+b2 bucket的增量哲学**
这个场景最容易被忽视。很多香港站点的静态资源都在本地磁盘上,文件数量动辄几十万。`tar`那种全量打包的方式,在CN2链路上等同于自杀。
用`inotifywait`监听真实变更,配合`restic`做去重增量备份。核心是把备份窗口打散成秒级事件流,而不是夜间集中冲击。
```bash
inotifywait -m -r -e create,modify,delete --format '%w%f|%e' /data/www | \
while read entry; do
# 500ms窗口聚合,防止小文件风暴触发restic
file_path=$(echo $entry | cut -d'|' -f1)
event=$(echo $entry | cut -d'|' -f2)
if [[ "$event" == "DELETE" ]]; then
# 删除事件直接标记快照,restic forget后立即prune
restic backup /data/www --tag realtime --exclude-file=/etc/restic/exclude.txt
restic forget --prune --keep-hourly 24 --keep-daily 7 --keep-monthly 3
else
# 变更事件只备份该文件
restic backup "$file_path" --tag realtime
fi
done
```
别小看这个看起来简陋的while循环。在`轻云互联`的香港CN2实例上,我实测过单次restic backup的CPU开销在50ms以内,不会对nginx的worker进程产生任何争抢。
最后说一个从血泪里总结出来的经验:无论用哪种方案,**备份文件必须实时做校验和**。在跨境链路上,数据损坏的概率远高于内地机房。restic天生带`--check`,但xtrabackup的xbstream文件你得在备份脚本里手动加一个`sha256sum`,传到远端后比对,否则等到要恢复时才发现压缩流里暗了一块坏块,那才是真的欲哭无泪。
备份这事,平时0关注,关键时刻1秒定生死。参数调优是有上限的,备份体系的架构设计没有上限。别让香港CN2的低延迟优势,毁在一个只顾着跑通却从没做过故障演练的cron任务上。