跳到主要內容

    幻嵐 Minecraft 伺服器架構,10 個 Paper 分流怎麼共用 Redis 與 MySQL

    幻嵐是 Java 版 Minecraft 伺服器,一台 Velocity 後面掛 10 個 Paper 分流,分流之間不直接連線,共用狀態全部經過 Redis 和 MySQL。這篇寫每一層是什麼、怎麼接起來。

    10 分鐘

    重點

    • 兩台主機。代理主機跑 Velocity、Redis、MySQL;MC 主機只跑 10 個 Paper 分流,不對外開任何 port。
    • 分流之間不直接連線。換分流靠有 TTL 的 Redis key,即時通知用 pub/sub,要可靠的更新用資料庫版本號輪詢。
    • 只能做一次的事(結算、寫回資料庫、送通知)都交給大廳這一台主分流。
    • 10 個 JVM 吃掉 96 GB 裡的約 88 GB,尖峰時 CPU 還有八成閒置,瓶頸在記憶體。
    目錄

    幻嵐是 Java 版 Minecraft 伺服器,一台 Velocity 代理後面掛 10 個 Paper 分流,分流之間不直接連線,共用狀態全部經過一套 Redis 和一台 MySQL。

    這篇寫每一層是什麼、怎麼接起來。數字都是 2026 年 10 月的狀態。

    架構全貌

    玩家(Java 版正版) SRV → 上游轉發 送 PROXY protocol 標頭 代理主機 Velocity 驗正版、轉發玩家 TAB、轉服外掛 Redis 快取、轉服 key pub/sub、佇列 MySQL 一個外掛 一個資料庫 modern forwarding Jedis/JDBC MC 主機 i9-13900K・96 GB・不對外開 port lobby_login lobby redstone ads_01 ads_02 ads_03 stst01 stst02 stst03 rpg 一個分流一個 JVM、一個 tmux,10 台合計約 88 GB
    MC 主機不開任何對外 port,玩家只能從 Velocity 進來。

    兩台實體機都在內網。代理主機跑 Velocity、Redis、MySQL。MC 主機只跑 10 個 Paper,不做 port forwarding。

    入口:玩家怎麼連進來

    玩家連的是網域,DNS 用 SRV 記錄指到上游的轉發服務,再由它連到 Velocity。轉發服務在連線開頭送 PROXY protocol 標頭,帶玩家真正的 IP,所以 Velocity 開了 haproxy-protocol。

    Velocity 開 online-mode 驗正版。分流全部 online-mode=false,改用 modern forwarding:代理把玩家資料連同 HMAC 簽章送給分流,分流用共享密鑰驗證,驗不過就踢。就算有人在內網直連分流的 port 也進不去。

    RCON 全關。對分流下指令用 tmux send-keys 送進主控台,用 tmux capture-pane 讀回來,走既有的 SSH。

    Tab 列表、頁首頁尾、側邊記分板都畫在代理上的 TAB,分流只裝 TAB-Bridge 回報變數,玩家換分流時名單不用重畫。

    10 個分流怎麼切

    分流 角色
    lobby_login 登入服。確認大廳活著、發材質包
    lobby 主大廳,也是主分流
    ads_01~03 生存
    stst01~03 副本,MythicMobs 設定最重,一台七百到近千個設定檔
    redstone 紅石,沒裝 MythicMobs
    rpg 另一個 RPG 世界

    切分的原則是把會互相拖累的負載拆開。副本分流的負擔是 MythicMobs 的怪物和技能,生存分流是玩家蓋的農場和漏斗,紅石分流整天在跑機關。放在同一個 JVM,一座農場就會讓打副本的人一起卡。

    行程模型

    開機分三層:

    1. systemd 的 minecraft-start.service(Type=oneshot)跑一支啟動腳本。
    2. 啟動腳本讀分流清單,每個分流開一個同名 tmux session 跑 start.sh。
    3. start.sh 是 while true 迴圈,java 結束 5 秒後再開一次,所以主控台打 stop 就等於重啟。

    不讓 systemd 直接管 java,是因為要能隨時 attach 進主控台。代價是 10 個 java 都在同一個 service 的 cgroup 裡,這個 service 被重啟,10 個分流會一起重開,自動更新的 needrestart 要把它排除。

    每日重啟由 UltimateAutoRestart 觸發,錯開排程:大廳和紅石 02:00,生存三台從 04:00 起每 15 分鐘一台,副本三台從 05:00 起每 15 分鐘一台,rpg 05:45,登入服不重啟。一台開機要 200 到 245 秒,9 台同時開會互搶到每台 375 到 454 秒,所以一定錯開。

    主機資源

    MC 主機是 i9-13900K(32 執行緒)、96 GB 記憶體、NVMe。晚上尖峰時,10 個 JVM 合計約 88 GB RSS,平均一台約 8.8 GB,可用記憶體只剩幾 GB,CPU 還有約 80% 閒置。

    瓶頸在記憶體。要多開一台分流,得先關掉或合併一台。

    資料層:MySQL 和 Redis 各放什麼

    MySQL 和 Redis 都在代理主機上,各一台。

    MySQL 是持久資料。慣例是一個外掛開一個資料庫,現在有二十幾個。要搬走或拆掉一個外掛,只動它自己的庫。

    Redis 放分流之間要共用、要快的東西:

    用途 內容
    餘額快取 14 種貨幣,加扣點先寫 Redis 標成 dirty,主分流每 60 秒批次寫回 MySQL
    換分流 hu_redirect:<UUID> → 目標分流,10 秒過期
    在線名單 玩家名 → UUID 的 Hash,加每人目前在哪台,代理每分鐘整批刷新
    跨服訊息 pub/sub 頻道:跨服 TPA、全服事件廣播
    佇列 要送到 Discord 的通知,由主分流消費
    玩家狀態 材質包接受與否(7 天過期),各分流照這個決定送圖示版還是純文字版的訊息

    餘額的加扣點用 WATCH/MULTI 做樂觀鎖。這裡一定要原子,兩個分流同時對同一人加點,「讀出來、算完、整筆寫回」會互相蓋掉。

    分流之間怎麼溝通

    分流之間不直接連線。跨服的事寫進 Redis 或 MySQL,由需要的那一方去拿。現在並存三種做法:

    做法 用在哪 特性
    寫一個有 TTL 的 key,對方輪詢 換分流 對方晚一點讀也拿得到,沒人處理的 key 自己過期
    Redis pub/sub 跨服 TPA、全服事件廣播 即時,但即發即忘,訂閱者重啟期間的訊息就沒了
    資料庫版本號,各分流輪詢 副本模板更新 版本號是持久的,分流重啟後自己追上;寫資料和加版本號同交易

    換分流的流程:分流寫 hu_redirect:<UUID>,代理上的轉服外掛每秒把所有在線玩家的 key 用一次 MGET 讀回來,有值就送過去,再整批刪掉。延遲最多一秒。

    跨服 TPA 兩種都用到:請求和同意走 pub/sub,每台都收得到,目標玩家在哪台就由那台處理;同意後寫一個 30 秒的 key 記傳送目的地,再走上面的換分流;玩家進目標分流時讀這個 key,傳送到對方身邊。

    副本模板改完要讓 10 台都重讀。這裡刻意不用 pub/sub:寫模板時在同一個 MySQL 交易裡把版本號加一,各分流每 5 秒讀一次版本號,變了就重讀。

    主分流

    有些事全服只能做一次:全服事件的結算、餘額寫回資料庫、送 Discord 通知、每週輪替。這些都只在大廳跑。每個外掛啟動時比對設定檔裡的 MainServer 和自己的 server-name,決定要不要啟動這些排程。

    其他分流判定事件任務達成時 publish 一則訊息,大廳收到先檢查事件是不是已經結束,所以重複收到也只結算一次。全服共用的等級每台都會加經驗,升級用 Lua 比對再寫,保證同一級只升一次。

    登入服

    登入服是 Velocity 後面的第一站,只裝一支守門外掛:

    • 探大廳。每 5 秒對大廳做一次 Server List Ping,連續 3 次失敗就判定停機,擋住進大廳的指令並顯示維護中。只看 port 不夠,Paper 開 port 之後到 Done 還要約 40 秒,要真的拿到狀態 JSON 才算開好。
    • 發材質包。CI 把材質包傳到物件儲存,更新一份帶檔名和 sha1 的 latest.json。登入服每 5 分鐘讀一次,在登入的 configuration 階段發給玩家。server.properties 的 resource-pack 留空。

    背包同步和物品定義

    背包跨分流用 HuskSync 同步。HuskSync 搬的是玩家身上的物品,MythicMobs 物品的定義卻寫在各分流自己的設定檔。物品只定義在一台,玩家帶到別台就失效。

    所以共用的物品和物品技能只寫在大廳,再用 rsync 同步到其他 9 台。分流自己只放怪物、怪物技能、掉落表、生怪點。

    還沒解決的

    • 單一主機。10 個分流都在同一台,主機出事就是全服。
    • 大廳是單點。結算、寫回、通知都在大廳,大廳重啟的那幾分鐘,別台發出的訊息沒人收。
    • 記憶體快滿。下一步要嘛合併分流,要嘛加一台主機把分流拆過去。

    常見問題

    Velocity 的 modern forwarding 跟 BungeeCord forwarding 差在哪?

    modern forwarding 會用共享密鑰對玩家的 UUID、名稱和皮膚資料簽章,分流驗過才放人進來。BungeeCord 的 legacy forwarding 沒有簽章,分流的 port 被直連就能冒用任何 UUID,只能靠防火牆擋。

    Minecraft 多分流伺服器怎麼換分流?

    分流把目標寫進一個 10 秒過期的 Redis key,Velocity 上的外掛每秒用一次 MGET 讀所有在線玩家的 key,有值就把玩家送過去再刪掉 key。

    一台主機跑 10 個 Paper 伺服器要多少記憶體?

    幻嵐 10 個 JVM 合計約 88 GB RSS,平均一台約 8.8 GB,主機 96 GB 已經快滿。CPU 是 i9-13900K,晚上尖峰還有八成閒置。

    分享LINEThreadsX