跳到主要内容

MySQL 多服同步

默认的 SQLite 每个子服各自一份。多个子服填同一个 MySQL / MariaDB 后:

资料怎么共用
商店文件 shops/*.yml、menu.yml自动同步:在任何一个子服改,其他子服约 2 – 3 秒内跟着更新
限购 / 限售 / 库存写了 cross-server: true 的:所有子服加起来算,精准到最后一件;没写的各子服分开计算
动态价格cross-server: true 的共用一个行情(其他子服 30 秒内同步)
限时特卖 /cs sale全部子服生效(30 秒内)
交易记录写在同一个表,/cs logs 看得到所有子服的记录(每笔都记着子服名称,messages.yml 的 logs-buy / logs-sell 可用 {server} 显示)

设定​

每个子服的 config.yml:

config.yml
# 每个子服取一个不同的名字(留空 = 服务器文件夹名:端口)
server-id: 'survival-1'

database:
type: mysql
host: 127.0.0.1
port: 3306
database: cloudshop
username: root
password: '你的密码'
parameters: useSSL=false&characterEncoding=utf8&serverTimezone=UTC
table-prefix: cs_
pool-size: 2

sync:
enabled: true # false = 只共用限购 / 库存 / 行情,不同步商店文件
interval-seconds: 3 # 多久检查一次其他子服的修改

改数据库设定要重启服务器。所有子服的 timezone 请设成一样,限购才会在同一时刻重置。

商店文件同步​

数据库里存着每个文件最新的内容与版本号。每个子服每隔 interval-seconds 秒在背景问一次「有没有我还没看过的版本」(一个很小的查询),有就写进自己的 shops/ 并重新载入。

在本服做的修改会立刻上传:

其他子服收到时控制台显示:

[CloudShop] MySQL 同步:已从其他子服更新 2 个文件

第一次接上​

情况结果
数据库还没有任何商店资料这个子服的文件成为共用版本,全部上传
数据库已经有资料使用数据库的版本;本服和它不同的文件先备份到 backups/sync-<时间>/ 再覆盖
本服有、数据库没有的商店(离线时新建的)上传到数据库,其他子服也会拿到

所以:先在一个子服设好 MySQL 并开服,让它的商店成为共用版本,再把其他子服接上来。

只在部分子服开放的商店​

商店文件同步到所有子服,但可以用 servers 限制在哪些子服开放:

shops/nether.yml
servers: [nether-1, nether-2] # config.yml 的 server-id

其他子服打开时提示「这个商店不在本服开放」,主菜单也不显示它;出售箱与一键卖出只用本服开放的商店的回收价。管理介面的商店设定可以直接设定,说明里会显示本服的名称。

跨子服的限购与库存​

limit:
buy:
amount: 1
reset: daily
cross-server: true # 玩家今天在任何子服买过就算
stock:
amount: 20
restock: daily
cross-server: true # 所有子服共用 20 份

每次购买都在数据库里用条件更新预留名额:「目前已用 + 这次份数 ≤ 上限」才写入,在同一个交易里完成。两个子服的玩家同时抢最后一件,只有一边会成功,另一边提示已售罄,钱不会被扣。预留之后如果因为余额不足、背包满等原因没买成,名额会还回去。见 限购与库存。

实测​

两台 Paper 子服共用一个 MySQL 的自动化测试(10 项):A 服手改文件 + /cs reload 后 B 服跟着更新并写进自己的资料夹;B 服新建的商店出现在 A 服、A 服删除的商店在 B 服消失;在 A 服买满跨子服限购后 B 服也被挡下;共用库存的最后一件在 B 服卖出后两边都售罄;A 服开的特卖在 B 服生效。见 效能与测试。