Skip to content

这页专门解释一条很多服主会混淆的链路:

HNAttribute 里 Buff / DOT / HOT 的运行时状态,什么时候只在本地落库,什么时候会跨服广播,排查时该先看什么。

如果你只是想查命令怎么敲,先看:

如果你想看 perf 里的辅助状态字段是什么意思,再看:


一、这条链路到底管什么

当前版本里,运行时快照主要覆盖两类状态:

  1. 玩家 Buff
  2. 玩家目标周期实例(常见就是 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 是怎么工作的

当前版本里,运行时持久化不是每次状态变化就立刻同步写库,而是:

  1. 先把玩家标成 dirty
  2. 等 flush 定时任务按批次处理
  3. 主线程收集有限数量的 snapshot
  4. 异步写入持久化层
  5. 对需要跨服的玩家,再额外广播 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 cluster
  • refresh cluster
  • debug ... cluster
  • perf reset cluster
  • runtime ... 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 太慢

重点看:

  • throttled
  • flush 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。

HN 系列插件文档