主题
这页专门解释一条很多服主会混淆的链路:
HNAttribute 里 Buff / DOT / HOT 的运行时状态,什么时候只在本地落库,什么时候会跨服广播,排查时该先看什么。
如果你只是想查命令怎么敲,先看:
如果你想看 perf 里的辅助状态字段是什么意思,再看:
一、这条链路到底管什么
当前版本里,运行时快照主要覆盖两类状态:
- 玩家 Buff
- 玩家目标周期实例(常见就是 DOT / HOT)
你可以把它理解成:
- 装备属性、Lore、PDC、NBT 这类内容不走这条链路
- 它主要负责“玩家当前挂着哪些状态,以及离线/跨服时怎么恢复”
二、当前模型里有哪几层状态
1)运行时内存态
就是玩家当前在线时,服务器内存里真正跑着的 Buff / 周期实例。
2)持久化快照
就是写到持久化层的 snapshot,用来做:
- 离线恢复
- 重登恢复
- 手动排查
runtime show / load / clear
3)跨服广播
就是通过 HNCore ClusterBus 发出的 runtime-snapshot 消息,用来把需要跨服同步的状态变化送到其他节点。
三、local dirty 和 cross-server dirty 的区别
这是当前最容易误解的地方。
local dirty
表示:
- 这个玩家的运行时状态变了
- 需要落库
- 但不一定需要额外跨服广播
常见理解:
这更像“本地状态脏了,要写入持久化层”。
cross-server dirty
表示:
- 这个玩家的运行时状态变了
- 不仅要落库
- 还需要额外广播
runtime-snapshot
常见理解:
这更像“除了本地存起来,还要告诉别的服这次变化”。
四、flush 是怎么工作的
当前版本里,运行时持久化不是每次状态变化就立刻同步写库,而是:
- 先把玩家标成 dirty
- 等 flush 定时任务按批次处理
- 主线程收集有限数量的 snapshot
- 异步写入持久化层
- 对需要跨服的玩家,再额外广播
runtime-snapshot
这意味着:
- 本地变化会自动落库,通常不需要你手动
runtime flush runtime flush更像是手动强制落盘 / 排障命令- 当前实现还有最小 flush 间隔和单批上限,用来避免主线程抖动
五、哪些命令该怎么用
1)先看整体状态
text
/hnattr runtime status适合看:
- 服务是否启用
- 当前 dirty 总量
- local / cross-server dirty 各有多少
- flush in-progress
- throttled
- 单批上限
- reload 状态
2)看某个玩家的内存态和持久化态
text
/hnattr runtime show <玩家>适合回答:
- 当前运行时 Buff / 周期和存储快照是否一致
- updatedAt 是否明显异常
- 离线恢复到底有没有数据基础
3)强制落盘
text
/hnattr runtime flush <玩家>
/hnattr runtime flush <玩家> cluster适合:
- 你不想等定时 flush
- 你在做强制保存链路验证
- 你要顺便验证 cluster 广播
4)从持久化层恢复
text
/hnattr runtime load <玩家>
/hnattr runtime load <玩家> cluster适合:
- 你怀疑内存态已经乱了,想从持久化层重新读回
- 你要验证跨服下游是否能吃到同一份 snapshot
5)删除持久化快照
text
/hnattr runtime clear <玩家>
/hnattr runtime clear <玩家> cluster适合:
- 你想清空某个玩家的持久化残留
- 你想验证“没有快照时的恢复行为”
六、为什么“广播成功”却没跨服
因为真正决定有没有跨服的,不是命令提示本身,而是 HNCore ClusterBus 当前的 transport。
要特别区分:
transport=redis:真正跨服transport=loopback:消息会进总线,但只在本服本进程内可见
所以只要你在排查:
reload clusterrefresh clusterdebug ... clusterperf reset clusterruntime ... cluster
都应该先看:
text
/hncore cluster status
/hncore status不要只看 HNAttribute 自己的提示文案。
七、推荐排查顺序
场景 A:玩家离线后 Buff / HOT 没恢复
按这个顺序:
text
/hnattr runtime status
/hnattr runtime show <玩家>
/hnattr runtime flush <玩家>
/hnattr runtime load <玩家>重点看:
- 持久化层里到底有没有 snapshot
- updatedAt 是否正常推进
- 当前 dirty 队列是不是一直在堆
场景 B:你怀疑跨服广播没真正出去
按这个顺序:
text
/hnattr runtime status
/hnattr sync status
/hncore cluster status
/hncore status重点看:
- HNAttribute 这边是不是还在
cross-server dirty - HNCore transport 是
redis还是loopback
场景 C:你怀疑只是本地 flush 太慢
重点看:
throttledflush in-progress单批上限
如果这几个字段一直高,说明更像是本地持久化链路在排队,不一定是跨服总线问题。
八、和二开 / Java API 的关系
当前公开 API 里,跨服相关主要是:
java
HNAttributeAPI.isSharedSyncAvailable();
HNAttributeAPI.getSharedSyncService();
HNAttributeAPI.broadcastReload();
HNAttributeAPI.broadcastRefreshEquipment(player);但要注意:
- 目前没有单独公开一套完整的 runtime snapshot 静态操作 API
- 运行时 snapshot 更偏内部同步与运维链路
- 二开通常更适合:
- 直接用 Buff API
- 直接用属性 API
- 再按需用 cluster 广播 API
九、一句话记忆版
本地状态变化先进 dirty 队列,flush 负责异步落库;只有跨服相关变化才会额外广播
runtime-snapshot,而真正能不能跨服要看 HNCore 的 transport。
