跳到正文

运维

读模型重建手册

用 go-sequent 的 replay 流水线重建可丢弃的读模型:prepare、replay、catchup、optimize、golive,含库 API、CLI schema 阶段与运维提示。

读模型重建手册

Replay 流水线沿用 Sequent 8 的流程:prepare、replay、catchup、optimize、golive,另有可选的 abort。

账本与余额类 Projector(把事件写成查询用读模型,例如余额表)必须保持强一致,因此在线路径上仍是 SyncInTxn(在写事务里同步更新读模型)。重建用于可丢弃的读模型,或用历史数据填充一张新的读模型表。

库 API

pipe := &replay.Pipeline{
    Name:          "balances",
    Source:        eventSource, // 实现 StreamAll
    Publisher:     syncInTxnWithProjectorsOnly,
    Schema:        &replay.PostgresSchema{Pool: pool}, // 或 replay.NoopSchema{}
    State:         replay.NewMemoryState(),            // 或你应用里基于数据库的 StateStore
    ManagedTables: []string{"account_balances"},
}
if err := pipe.RunAll(ctx); err != nil {
    return err
}

Pipeline 还提供 Prepare、Replay、Optimize、GoLive 与 Abort,可以逐阶段运行。其他字段有 ReplaySchema、ViewSchema 与 BatchSize。BatchSize 为 0 时,Replay 使用 1000。

Publisher 通过 PublishProjectorsOnly 重放,它不包含 Workflow,所以重建不会重新触发邮件、付款这类副作用。

State 是一个 StateStore。replay.NewMemoryState() 在进程退出后会丢失进度。如果重建需要跨重启存活,请使用持久化的存储。迁移创建的 projector_replay_states 表可用于此。

各阶段

阶段 动作
prepare 创建 replay_* schema,用 CREATE TABLE … (LIKE …) 创建受管表,并清空
replay 把历史事件流式投入重放用的 Projector 和表
catchup 在在线系统继续运行的同时,应用高水位之后追加的事件
optimize 执行 ANALYZE,按需添加索引
golive 短暂切换:把在线表移开,把重放表提升到 view schema
abort DROP SCHEMA replay_* CASCADE

CLI:只有 schema 阶段

CLI 负责重建中与 schema 相关的部分:

go run ./cmd/go-sequent migrate -dsn "$GO_SEQUENT_PG_DSN"

go run ./cmd/go-sequent replay -dsn "$GO_SEQUENT_PG_DSN" \
  -projector balances -stage prepare -tables account_balances

# 之后按需:-stage optimize | golive | abort

CLI 接受 prepare、optimize、golive 与 abort 阶段。它无法流式读取事件,因为它不知道你注册了哪些 Projector。replay 与 catchup 阶段必须在你自己的应用二进制里,用上面的流水线运行。参见 Migrations 与 CLI。

运维提示

  • 按事件量设置 BatchSize。批次大意味着往返少,但事务更长。
  • golive 期间,如果你的切换不是无锁的,就暂停写入方,或短暂串行化。
  • golive 之后,余额的事实来源仍然是 SyncInTxn Projector。
  • 通过 projector_replay_states 或你自己的 StateStore 跟踪进度。
  • 如果 golive 前发现异常,执行 abort。此时在线表尚未被动过。

相关

文档随 go-sequent 源码更新;若与 API 不一致,以源码为准。