以前服里塞满了散装小插件
早期做 mc.igng.net 网站的时候,每加一个新页面我就顺手写个小插件塞进服务器:管违规警告的一个、录 TPS 和在线人数的一个、传公屏聊天记录的一个、同步领地和权限组的又是一个。
时间一长,每个子服的 plugins 文件夹里都躺着五六个自家小插件,连的都是同一个数据库,配置改起来容易漏,出问题了还得挨个翻日志。2026 年 8 月 15 日(Commit adf400d),我下决心把它们全部收拢进 igng-dev/igngmc-plugin 七合一综合插件,外加一个跑在 Velocity 代理层基于 Netty 的边缘流量统计模块。到了 8 月下旬,我更给它划定了一条铁律:这个插件只做可靠的数据探针,绝不开放任何高风险的远程写操作接口,同时结合容器的 cgroup 接口采集真实的动态 CPU 配额,不再被宿主机的总核数骗了。
多服共用数据库,“全删全插”惹出的祸
插件合并完不久,9 月初就遇到了一个让人冒冷汗的隐患。当时为了把服里的 LuckPerms 权限组和领地列表同步到网页上展示,老代码省事用了“先清空本服旧记录、再批量插入新记录”的写法。
结果有两个坑撞在了一起:第一,如果新装的服务器忘了改配置,默认的 server-id=0 就会大家混用同一个 ID 互相覆盖;第二,在清空旧数据到插完新数据的这几百毫秒空窗期里,网页端如果刚好有人刷新,读出来的就是一张半截甚至全空的表!
Generation 版本号快照与指针翻转
2026 年 9 月 3 日到 4 日(Commit 07f58b0 等),我把这套同步逻辑彻底重写了一遍。首先给配置上了硬门槛:只要检测到还是默认的 server-id=0,插件启动时直接拒绝向数据库写任何数据,逼着运维先把每台子服的身份标识配清楚。
接着,把权限组和领地同步改成了按 generation(代数版本号)发布的原子快照模式:每次同步时,新数据先带着新的 generation 编号静静写进表里,这时候旧数据纹丝不动,网页端依然正常读旧版本号;等几百条新数据全部写完、校验无误后,再在一个极小的事务里翻转快照状态表的指针指向新世代,最后顺手清理掉过期的老世代数据。同时我还补上了玩家改名后的领地归属自动继承逻辑,从此网页上再也没出现过“刷新一下领地全没了”的惊吓。