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 服生效。见 效能与测试。