MickeyMiao

起点草甸

MickeyMiao

code is cheap, show me your prompt

51 篇文章 · 18 个分类 · 4 位朋友

向下滑动,出发 (或按 1-6 直达)

服务器小镇

家里小主机上的 Minecraft 生存服,白名单制。加入:QQ 群

状态
读取中…
在线
-
版本
-
已开服
-

每 10 分钟更新一次

关于雪松林

嗨,我是王思淼

图形渲染开发工程师 @ 小米。喜欢图形学、游戏和折腾服务器。

完整介绍 GitHub Bilibili Steam

回到森林 Esc 关闭

游戏Minecraft

Minecraft 服务器的三层备份:冷备份、restic 增量快照与家用 NAS 异地副本

这是 mc-ops 系列的第三篇,讲服务器的备份方案:备份怎么做、存在哪里,以及最重要的一点:怎么证明它真的能恢复。

旧方案的问题

旧系统每天凌晨重启时打一个 tar.gz 冷备份,升级前再打一个快照。它简单可靠,可以直接解压,但有几个问题:

  • 一天只有一个恢复点。晚上八点出了事,只能回到当天凌晨,玩家一整天的进度都没了。
  • 没有去重,越存越大。每份完整备份 3 GB 左右,升级快照只增不减,备份目录涨到了 22 GB。
  • 全在同一块盘上。备份和世界存档在同一台机器的同一块硬盘上,硬盘坏了会一起丢。
  • 恢复要登录服务器手动操作,而且从来没有演练过。

现在的三层

层 频率 存在哪里 防什么
tar.gz 冷备份 每天 05:00 服务器本机 兜底:不需要任何工具,解压就能用
restic 增量快照 每 6 小时 服务器本机的 restic 仓库 误操作、熊孩子、刷物品 bug、区块损坏
异地副本 每次快照之后 家里的小米智能存储(NAS) 服务器硬盘损坏、系统出问题

第一层:每天的冷备份

每天 05:00,mc-ops 在游戏里倒计时通知玩家,然后停服、打包、开服,整个过程两分钟左右。停服状态下打包,世界文件一定是一致的。冷备份按数量保留,太旧的会自动清理。

保留它是因为它不依赖任何工具:万一 restic 仓库坏了,或者需要在一台什么都没装的机器上恢复,tar.gz 解压就能用。

第二层:restic 增量快照

restic 会把文件切块、去重、加密后存进仓库。每个快照在逻辑上都是一份完整的副本,但没变化的数据块只存一份。实际效果:7 个完整快照一共只占 6.7 GB,日常一次快照只新增几十到一百 MB。

不停服也要保证一致。 快照是在服务器运行时拍的。如果拍的过程中 MC 正在写区块文件,备份里的世界可能是"写到一半"的状态。所以每次拍快照前先让 MC 暂停自动保存并把内存里的数据写盘,拍完再恢复:

save-off
save-all flush
(restic backup ...)
save-on

这几条命令都通过 RCON 发送。restic 以低优先级运行(nice / ionice),尽量不影响游戏。

保留策略越近越密:

restic forget --keep-last 4 --keep-daily 14 --keep-weekly 8 --keep-monthly 6 --prune
  • 最近 4 个快照:按每 6 小时一个算,覆盖最近一天;
  • 再往前每天保留 1 个,保留 14 天;
  • 每周 1 个,保留 8 周;
  • 每月 1 个,保留半年。

第三层:异地副本,存到家里的 NAS

我家里有一台小米智能存储。它是封装好的 NAS,不能装软件、不能跑 Docker,也没有定时任务。好在它有一个"网络邻居"功能,其实就是 SMB 共享。

restic 本身不支持 SMB,但它可以用 rclone 做后端,而 rclone 支持直接读写 SMB。这样就不需要把共享挂载到本地,也不需要 root 权限:

# 在 rclone 配置里定义一个 smb 远端(密码用 rclone obscure 处理后再写进配置)
# 然后 restic 仓库地址写成:
restic -r rclone:nas:共享名/mc-ops/restic-repo snapshots

每次本地快照完成后,mc-ops 用 restic copy 把新快照复制到 NAS 上的仓库:

export RESTIC_FROM_REPOSITORY=/path/to/local-repo
export RESTIC_FROM_PASSWORD_FILE=...
restic -r rclone:nas:... copy

有几个细节:

  • 目标仓库初始化时要复制源仓库的分块参数: restic init --copy-chunker-params。不加的话,两个仓库切块的方式不一样,复制时去重就失效了,每次都要传大量重复数据。
  • 异地复制用单独的一把锁。 第一次全量复制要传 6 GB 多,花了半个小时。它和本地备份、定时重启不共用锁,所以不会挡住 05:00 的重启。
  • 复制失败会告警,但不影响本地快照。 将来如果配了多个异地目标,其中一个失败也不会影响其他目标。
  • 限速。 复制默认限速,因为家里的上行带宽同时还承载着玩家的游戏流量。

我也考虑过在腾讯云 COS 上再放一份,代码已经支持 S3 协议的目标。不过 NAS 已经能防住硬盘损坏和服务器本身出问题这类最常见的情况,对一台朋友之间玩的服务器来说够用了,所以暂时没开。它防不了整屋断电、失窃这种情况,这一点要心里有数。

小米智能存储的几个坑

  • 实际的共享名带一个自动生成的数字后缀。 在 App 里建的共享叫"mc-ops备份",但对外暴露的名字其实是"mc-ops备份-一串数字",按 App 里显示的名字连接会提示找不到。要先用 rclone lsd nas: 列出真实的共享名。
  • 用 IP,不要用局域网名称。 App 里显示的局域网名称在 Linux 上需要 NetBIOS 或 mDNS 才能解析,一般的服务器上没有,直接用 IP 更可靠。
  • 插着网线不代表 IP 固定。 它仍然通过 DHCP 获取地址,最好在路由器里做 IP 和 MAC 绑定。
  • 选"账号密码访问",不要选无密码访问。 无密码的共享,局域网里任何设备都能读写,包括各种智能家居设备。

恢复:没演练过的备份不算备份

面板上的"回退"

在面板的备份页选一个快照,点"回退",可以选两种范围:

  • 只回退世界:地图、箱子、玩家背包和进度回到那个时间点,Mod 和配置不动;
  • 世界 + Mod + 配置:连同 mods/、config/、server.properties、白名单、封禁名单一起回退。

执行流程:

游戏内倒计时 5 分钟 → 停服 → 给当前状态拍一个 pre-restore 快照
→ 从仓库解出目标快照 → 替换文件 → 开服

几个保护措施:

  • 先拍 pre-restore 快照:回退之后后悔了,还可以回退到回退前的状态;
  • 开服失败自动换回:被替换下来的文件先留着,新文件开服失败就自动换回去;
  • 停服前先检查:仓库能不能连上、快照存不存在,不满足就直接报错,不会白白停服;
  • 回退期间按钮禁用,也不会和定时重启同时执行。

为什么是先停服、再解快照,而不是先在后台解好、再停服替换?后者停服时间更短,但既然要回退,玩家在这段时间里玩的内容反正都会被覆盖。而且需要回退的时候,往往是世界已经出了问题,这时候让玩家继续玩,可能把问题弄得更糟。早点停服反而更干净。

两次实际演练

找了一个没人在线的上午,在生产服上实际做了两次回退:

从本机仓库 从 NAS 仓库
解出 4.3 GB 世界 20 秒 18.5 分钟
总停服时间 不到 1 分钟 约 19 分钟
结果 成功 成功

两次都成功了,回退前后的世界只差几个自然更新的区块文件。

从 NAS 恢复慢,查下来主要是服务器的网络:它连的是 2.4 GHz Wi-Fi,协商速率只有 50 到 60 Mbit/s 左右,平均只跑到约 4 MB/s。最后一段恢复的都是小文件,每个文件都要在 SMB 上来回请求一次,速度掉到了 1 MB/s 以下。换成千兆有线后,预计能缩短到一两分钟。

这次演练还有几个收获:

  • 平时用本机仓库回退,NAS 留给本机硬盘坏了的时候。
  • restic copy 之后快照 ID 会变。 同一个时间点的快照,在本机和 NAS 上的 ID 不一样。我一开始以为是一样的,第一次演练时没切到 NAS 标签,结果用的是本机仓库,看 ID 才发现。
  • 长任务需要进度。 18 分钟里面板上只有一行"正在解出快照",完全不知道还要多久。后来用 restic restore --json 输出的进度,在任务页加了进度条、速度和剩余时间。速度按最近 30 秒计算,这样小文件导致速度突然变慢时,剩余时间也能跟上。

下载备份

面板上也可以直接下载备份:冷备份直接下载 tar.gz,支持断点续传;restic 快照会现场用 restic dump 导出成 zip。下载要经过云主机转发,和玩家共用带宽,所以默认限速 512 KiB/s,同时只能有一个下载。

最容易被忽略的一件事:备份密码

restic 仓库是加密的,没有密码就解不开。我的仓库密码一开始只存在服务器的配置文件里。这意味着:如果服务器硬盘坏了,密码会跟着丢,NAS 上的备份就成了一堆打不开的数据。

所以加密备份的密码一定要另外保存一份,比如放进密码管理器,或者写在纸上收好。这个步骤不难,但很容易被忽略。

小结

  • 冷备份简单可靠,保留它作为兜底;
  • restic 让一天多次快照的成本变得很低,保留策略越近越密;
  • 异地副本不一定要上云,家里的 NAS 就能防住最常见的硬盘损坏;
  • 备份一定要实际演练恢复,演练时发现的问题(Wi-Fi 太慢、快照 ID 会变、缺少进度显示)比写代码时想到的多;
  • 加密备份的密码要和备份分开存放。

#Minecraft#备份#restic#rclone#SMB#NAS#运维

评论