使用 BorgBackup 備份你的 Minecraft 地圖
Minecraft 地圖是伺服器最重要的資產,但它也是最容易壞的東西之一:玩家不小心炸壞家、插件升級導致 region 檔損毀、硬碟偶發 I/O 錯誤……任何一個意外都可能讓玩家數個月的努力付諸流水。
過去我在磐石伺服器是用 git 來備份地圖,但 git 並不適合處理大量二進位的 region 檔,repo 一下就膨脹到幾百 GB。後來換成 BorgBackup,整個世界從此清爽。
為什麼是 BorgBackup?
最直接的理由:區塊級去重 (chunk-level deduplication)。
Minecraft 的地圖會切成一個個 region 檔(r.x.z.mca),每個 region 大約 32×32 個 chunk。玩家活動時,往往只有幾個 chunk 真的有改動,但整個 region 檔的 mtime 會被刷新——對 rsync、tar、git 這類工具來說,整個檔案都得重傳一次。
Borg 不一樣:它會把每個檔案切成內容定址 (content-addressed) 的小區塊,只有真的改變的區塊才會被新增到 repo。對 Minecraft 來說,這個特性簡直是天作之合。
來看磐石伺服器目前的實際數字:1
2
3
4
5
6$ borg info /data/backup/world-borg
Original size Compressed size Deduplicated size
All archives: 2.51 TB 1.45 TB 208.68 GB
Unique chunks Total chunks
Chunk index: 255500 1783167
7 份每日快照、原始資料 2.51 TB,最後實際佔用磁碟只有 208 GB——壓縮率約 12 倍。如果換成 git 或單純 tar,這個數字大概會嚇死人。
安裝與初始化
Ubuntu 直接用 apt 就好:1
sudo apt install borgbackup
接著建立 repo。我把 repo 放在另一顆掛載到 /data 的硬碟上,這樣即使系統碟掛掉也還救得回來:1
borg init --encryption=none /data/backup/world-borg
如果 repo 是放在自己看得到的本機硬碟,
--encryption=none即可。如果是丟到 NAS、VPS 或共享儲存上,請改用repokey或keyfile模式,這樣即使 repo 外洩也不會被讀走。
最基本的備份指令
1 | REPO=/data/backup/world-borg |
幾個重點:
::{now:%Y-%m-%d_%H%M%S}是 archive 的命名格式,Borg 會在執行時把{now:...}換成當下時間,每次跑就是一個新的快照。--compression zstd,3用 zstd 壓縮等級 3,速度與壓縮比的甜蜜點。對 region 檔的內部資料壓縮效果非常好。- 三個 world 一次傳進去,Borg 會在同一份 archive 裡記錄它們,省下一次次開關 repo 的 overhead。
第一次跑會花比較久(要建立完整的 chunk index),之後每天的增量備份在我的伺服器上只要幾分鐘。
Hot Backup:不停機的備份才是真備份
直接 borg create 看似可行,但其實有個地雷:Minecraft 隨時都在寫入 region 檔。如果你在它寫到一半時讀走,可能會拿到一個半新半舊的檔案,將來還原時就會看到莫名其妙的洞或者 region corrupt 的訊息。
正確做法是搭配 Minecraft 的 console 指令:1
2
3
4save-off # 暫停自動存檔
save-all flush # 把目前記憶體的東西全部 flush 到磁碟
borg create ... # 此時磁碟上的 region 檔是一致的,可以安心備份
save-on # 恢復自動存檔
磐石伺服器這段邏輯是用 Python 包出來的,重點摘錄如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15say('地圖備份即將開始(不停機)')
borg_success = False
try:
server_util.exec_server_cmd('save-off')
server_util.exec_server_cmd('save-all flush')
# 等 log 出現 "Saved the game" 才繼續
_wait_for_save_complete(timeout=60)
server_util.exec_cmd_checked(
f'borg create --stats --compression {compression} {archive} {sources}')
borg_success = True
finally:
# 不管備份成功與否,一定要恢復自動存檔,否則伺服器會永遠不存檔
server_util.exec_server_cmd('save-on')
兩個非常重要的細節:
- 要等
Saved the game真的出現在 log 才開始 borg create。save-all flush是非同步的,馬上接borg create有機會撈到還沒寫完的檔案。 save-on一定要包在finally裡。如果 borg 中途出錯而沒呼叫save-on,伺服器就會永遠不存檔,下一次當機你會哭出來。
Prune:自動清掉舊備份
Borg 的 prune 可以照保留策略自動刪除舊 archive。磐石的設定是「保留最近 7 天」:1
2borg prune --stats --keep-daily=7 /data/backup/world-borg
borg compact /data/backup/world-borg
--keep-daily=7:每天只保留一份,總共保留 7 份。Borg 也支援--keep-weekly、--keep-monthly、--keep-yearly,可以混搭。borg compact是 Borg 1.2 之後新增的步驟,它會把 prune 之後 repo 裡的空洞真正釋放回磁碟,否則你會發現「明明刪了卻沒變小」。
還原
備份的價值在於你真的能還原。先看一下有哪些 archive:1
borg list /data/backup/world-borg
1
2
3
42026-04-08_030011 Wed, 2026-04-08 03:00:12
2026-04-09_030010 Thu, 2026-04-09 03:00:10
...
2026-04-14_025503 Tue, 2026-04-14 02:55:03
要把某個 archive 完整解出來:1
2mkdir /tmp/restore && cd /tmp/restore
borg extract /data/backup/world-borg::2026-04-13_025506
只想拿出某個玩家家附近的 region 檔?Borg 支援 path 過濾:1
2borg extract /data/backup/world-borg::2026-04-13_025506 \
home/codingman/server/world/region/r.0.0.mca
如果只是想瀏覽備份內容而不解開,可以用 borg mount 把 repo 掛成 FUSE 檔案系統,超方便。
異地備份:別把雞蛋放在同一個籃子
本機 borg repo 再可靠,硬碟壞掉還是一切歸零。磐石的做法是在備份完成後,順手把整個 repo 用 gsutil rsync 到 Google Cloud Storage:1
2gsutil -m rsync -r -i -j -d \
/data/backup/world-borg gs://rock-mc-usa
Borg repo 的好處是它本身已經是去重壓縮過的檔案集合,rsync 上去的流量也會跟著省。對於只想要「萬一機房整個炸了還能重建世界」的需求來說,這個組合相當划算。
結語
從 git 換到 BorgBackup 之後,磐石伺服器再也不用擔心 repo 膨脹、push 卡住,每天自動跑、自動 prune、自動上雲,凌晨三點完成,玩家完全感覺不到。如果你也在維護 Minecraft 伺服器(或任何「大量檔案、小幅修改」的工作負載),非常推薦試試看 Borg。
最後再強調一次最重要的 checklist:
save-off→save-all flush→ 等 log →borg create→save-on,順序不能亂。save-on必須在finally裡。prune之後記得compact,不然空間不會真的釋放。- repo 要做異地備份,本機 repo 不算「備份」,只算「方便還原的副本」。