<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>消息中间件 on PlumePHP</title><link>https://plumephp.com/tags/%E6%B6%88%E6%81%AF%E4%B8%AD%E9%97%B4%E4%BB%B6/</link><description>Recent content in 消息中间件 on PlumePHP</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Thu, 29 Oct 2026 08:58:00 +0800</lastBuildDate><atom:link href="https://plumephp.com/tags/%E6%B6%88%E6%81%AF%E4%B8%AD%E9%97%B4%E4%BB%B6/index.xml" rel="self" type="application/rss+xml"/><item><title>《Java 消息中间件·事件驱动架构》附录 B 架构决策记录模板</title><link>https://plumephp.com/java-mq-arch-appendix-b-adr-templates/</link><pubDate>Thu, 29 Oct 2026 08:58:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-appendix-b-adr-templates/</guid><description>五份架构决策记录模板覆盖技术选型、事件契约、一致性、迁移与治理场景，每份含背景、选项对比、结论与验证条件。附纯 JDK 实现的 ADR 完整性校验器，确保决策在代码变更前落盘。</description></item><item><title>《Java 消息中间件·事件驱动架构》附录 A 术语表</title><link>https://plumephp.com/java-mq-arch-appendix-a-glossary/</link><pubDate>Thu, 29 Oct 2026 08:57:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-appendix-a-glossary/</guid><description>六十条事件驱动领域术语，覆盖事件基础、Kafka 生态、一致性模型、流处理与治理五个维度，附中英对照、一句话定义与易混词辨析，可作为架构评审的共同语言速查参考。</description></item><item><title>《Java 消息中间件·事件驱动架构》15.3 全书验收</title><link>https://plumephp.com/java-mq-arch-15-3-acceptance-criteria/</link><pubDate>Thu, 29 Oct 2026 08:56:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-15-3-acceptance-criteria/</guid><description>三卷验收汇总不是检查完就结束了，而是明确知道哪些结论仍依赖真实环境验证。本文用纯 JDK 生成卷一到卷三的能力矩阵与遗留风险清单，给出后续演进方向的三阶段实施路线图、量化验收标准、持续改进闭环机制以及验收的投入产出评估。</description></item><item><title>《Java 消息中间件·事件驱动架构》15.2 故障演练剧本</title><link>https://plumephp.com/java-mq-arch-15-2-disaster-recovery/</link><pubDate>Thu, 29 Oct 2026 08:55:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-15-2-disaster-recovery/</guid><description>故障演练的核心不是出了故障再临时应对，而是在系统正常运转时主动模拟各类故障场景并验证恢复能力。本文给出 broker 挂、消费者挂、投影错、契约破坏四个剧本的完整执行步骤、环境要求、回滚方案与检查清单，用纯 JDK 模拟演练自动化检查器与改进工单生成流程。</description></item><item><title>《Java 消息中间件·事件驱动架构》15.1 SLO 与容量</title><link>https://plumephp.com/java-mq-arch-15-1-production-checklist/</link><pubDate>Thu, 29 Oct 2026 08:54:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-15-1-production-checklist/</guid><description>事件链路的 SLO 不是拍脑袋定的承诺，而是基于 SLI 的量化约束与可验证的业务承诺。本文用纯 JDK 模拟延迟分布的 p50、p99、p99.9 计算与新鲜度检测，完整展示容量规划与 SLO 联动的四条规则、过载保护的阈值设计与多维度评审机制。</description></item><item><title>《Java 消息中间件·事件驱动架构》14.3 架构评审清单</title><link>https://plumephp.com/java-mq-arch-14-3-alerting/</link><pubDate>Thu, 29 Oct 2026 08:53:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-14-3-alerting/</guid><description>事件驱动架构正式投产前，二十五条评审问题按契约、一致性、运维与成本四个维度排列，每条附重要性说明与可验证的通过标准。本文给出评审会上逐条过章的检查表流程、自动化判定逻辑、常见驳回案例与完整实施路线图，直接支撑上线验收决策与风险前置措施，避免架构带病上线。</description></item><item><title>《Java 消息中间件·事件驱动架构》12.2 从单体到事件的迁移</title><link>https://plumephp.com/java-mq-arch-12-2-eventual-consistency/</link><pubDate>Thu, 29 Oct 2026 08:51:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-12-2-eventual-consistency/</guid><description>单体迁移到事件驱动的最大风险从来不是技术难度而是回滚能力缺失导致出错后无法体面回退。本文用绞杀者模式拆解迁移四阶段，用纯 JDK 完整模拟双写一致性检测、实际回滚窗口验证与回退演练，确保每步迁移都经过验证的可靠退路方案和明确的回退成本评估。</description></item><item><title>《Java 消息中间件·事件驱动架构》11.3 配额与成本分摊</title><link>https://plumephp.com/java-mq-arch-11-3-compatibility-testing/</link><pubDate>Thu, 29 Oct 2026 08:49:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-11-3-compatibility-testing/</guid><description>在多业务线共享事件平台的场景下，配额超限策略是保障长期稳定运行的生命线。告警阈值必须早于拒绝阈值，给运维团队留出排查根因的时间窗口。本文用纯 JDK 完整模拟按业务线配额管理器，展示硬配额直接拒绝、软配额告警后放行与延迟到下一窗口处理的三种策略。</description></item><item><title>《Java 消息中间件·事件驱动架构》11.2 Topic 命名与生命周期</title><link>https://plumephp.com/java-mq-arch-11-2-version-migration/</link><pubDate>Thu, 29 Oct 2026 08:48:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-11-2-version-migration/</guid><description>Kafka Topic 命名规范与生命周期治理：domain.event.action.vN 格式、CREATING→ACTIVE→DEPRECATED→RETAINED→DELETED 五态机，以及孤儿主题自动清理。Java 模拟命名校验与非法状态转换拦截。</description></item><item><title>《Java 消息中间件·事件驱动架构》11.1 事件平台自助化</title><link>https://plumephp.com/java-mq-arch-11-1-schema-evolution/</link><pubDate>Thu, 29 Oct 2026 08:47:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-11-1-schema-evolution/</guid><description>事件平台自助化的本质不是取消审批，而是把命名违规、权限越级等拒绝条件精准前置到成本最低的节点。本文用纯 JDK 完整模拟工单审批状态机，展示技术初审与安全审计的职责分工、拒绝条件列表与每一步产出物，为共建自助化事件平台提供可落地的流程设计与治理体系。</description></item><item><title>《Java 消息中间件·事件驱动架构》10.3 事件血缘与影响分析</title><link>https://plumephp.com/java-mq-arch-10-3-event-lineage/</link><pubDate>Thu, 29 Oct 2026 08:46:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-10-3-event-lineage/</guid><description>事件血缘必须覆盖字段级而非仅主题级，否则无法精确判断某一个字段被多少个下游消费者消费。本文用纯 JDK、零外部依赖的方式构建最小血缘图，模拟三个生产者、五个主题、八个消费者与十二条血缘边的完整事件拓扑，演示字段级变更后的影响面自动遍历与下游列表生成。</description></item><item><title>《Java 消息中间件·事件驱动架构》10.2 端到端延迟度量</title><link>https://plumephp.com/java-mq-arch-10-2-e2e-latency/</link><pubDate>Thu, 29 Oct 2026 08:45:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-10-2-e2e-latency/</guid><description>端到端延迟必须分段度量而不能依赖均值。本文用纯 JDK、零外部依赖的方式模拟一千条事件跨越生产、Broker、消费与投影四段的延迟分布，输出各段 p50、p99 与端到端总延迟分位值，揭示并发缓冲与流水线重叠使得端到端延迟不等于各段简单相加的根本原因。</description></item><item><title>《Java 消息中间件·事件驱动架构》10.1 事件链路的追踪</title><link>https://plumephp.com/java-mq-arch-10-1-trace-propagation/</link><pubDate>Thu, 29 Oct 2026 08:44:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-10-1-trace-propagation/</guid><description>事件链路追踪的核心在于保证 traceId 跨越 topic 边界时不被截断、不被重置。本文用纯 JDK 模拟 TraceContext 在三条消费者间的头传递，输出 span 树、采样一致性校验与链路断裂点标记，验证消息场景下追踪与同步场景的根本差异。</description></item><item><title>《Java 消息中间件·事件驱动架构》14.2 游戏与 IoT 场景</title><link>https://plumephp.com/java-mq-arch-14-2-monitoring/</link><pubDate>Thu, 29 Oct 2026 08:43:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-14-2-monitoring/</guid><description>游戏与 IoT 场景在事件驱动架构下面临独特挑战：高频小消息、设备离线与乱序到达，与业务事件的强一致性要求完全不同。本文对比游戏状态同步、IoT 批量上报与业务事件在吞吐量、丢失容忍与顺序要求上的差异与独立配置策略，给出可落地的场景选型建议。</description></item><item><title>《Java 消息中间件·事件驱动架构》14.1 库存类场景</title><link>https://plumephp.com/java-mq-arch-14-1-performance-tuning/</link><pubDate>Thu, 29 Oct 2026 08:42:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-14-1-performance-tuning/</guid><description>库存类场景的核心矛盾是超卖、预占与释放的并发控制与幂等保证。本文对比库存扣减、预占锁定与释放通知三种事件链路，用纯 JDK 模拟超卖检测与幂等恢复，展示库存事件顺序与幂等边界在真实并发与高并发环境下的完整设计策略、恢复流程与扩展模式选型选择。</description></item><item><title>《Java 消息中间件·事件驱动架构》13.3 libraryd 事件流</title><link>https://plumephp.com/java-mq-arch-13-3-libraryd-events/</link><pubDate>Thu, 29 Oct 2026 08:41:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-13-3-libraryd-events/</guid><description>libraryd 借阅系统事件流实战：定义 LoanCreated/Renewed/Returned/Overdue 四种领域事件，用内存追加日志模拟 Kafka 分区保序语义，实现投影状态重建、幂等重放验证、按借阅单过滤追踪与事件因果链可视化。</description></item><item><title>《Java 消息中间件·事件驱动架构》13.2 libraryd 命令设计</title><link>https://plumephp.com/java-mq-arch-13-2-libraryd-commands/</link><pubDate>Thu, 29 Oct 2026 08:40:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-13-2-libraryd-commands/</guid><description>libraryd 借阅系统命令设计实战：定义 BorrowBook/ReturnBook/RenewLoan 三种命令类型，验证构造期参数校验、幂等去重、乐观并发版本控制，以及命令被接受或拒绝的显式结果语义与命令到事件的 1:1 映射规则。</description></item><item><title>《Java 消息中间件·事件驱动架构》13.1 libraryd 领域模型</title><link>https://plumephp.com/java-mq-arch-13-1-libraryd-domain/</link><pubDate>Thu, 29 Oct 2026 08:39:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-13-1-libraryd-domain/</guid><description>libraryd 借阅系统核心领域模型实战：纯 JDK 实现聚合根 Loan、实体 Book/Member 与值对象 ISBN/LoanPeriod，验证构造校验、不可变性、相等性、不变量约束与乐观并发版本控制机制，涵盖内存仓储查询与值对象等价性，零 Spring 依赖。</description></item><item><title>《Java 消息中间件·事件驱动架构》12.3 一致性边界</title><link>https://plumephp.com/java-mq-arch-12-3-consistency-boundaries/</link><pubDate>Thu, 29 Oct 2026 08:38:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-12-3-consistency-boundaries/</guid><description>一致性不是全局属性，而是由聚合边界、消费者归属和关键程度共同决定的局部属性。本文给出一张判定表和一段可运行的 H2 代码，按「是否跨聚合消费」「是否关键聚合」两维推导每个聚合的一致性级别，输出明确的 STRONG 与 EVENTUAL 判定报告。</description></item><item><title>《Java 消息中间件·事件驱动架构》12.1 Outbox 模式</title><link>https://plumephp.com/java-mq-arch-12-1-outbox-pattern/</link><pubDate>Thu, 29 Oct 2026 08:36:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-12-1-outbox-pattern/</guid><description>Outbox 模式用数据库本地事务保证业务写入与事件的原子性，再由中继可靠投递到 Kafka。本文用 H2 + kafka-clients 写一段可运行的 outbox 演示，故意构造一条不一致记录，展示对账检测、自动重发、幂等标记与至少一次语义的完整流程与本机实测输出。</description></item><item><title>《Java 消息中间件·事件驱动架构》9.3 事件存储</title><link>https://plumephp.com/java-mq-arch-09-3-event-store/</link><pubDate>Thu, 29 Oct 2026 08:29:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-09-3-event-store/</guid><description>事件存储是事件溯源的基础设施。本节比较自建事件存储与直接使用 Kafka 作为事件存储的权衡，指出 Kafka compacted topic 的局限，并用 Java 实测消费者把事件追加到本地 SQLite 日志表并重放到任意版本的完整流程。</description></item><item><title>《Java 消息中间件·事件驱动架构》9.2 快照与性能</title><link>https://plumephp.com/java-mq-arch-09-2-snapshot/</link><pubDate>Thu, 29 Oct 2026 08:28:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-09-2-snapshot/</guid><description>快照截断事件流以减少重建时的 apply 次数。本节讨论事件数阈值与时间窗口两种快照触发策略、快照与底层事件的版本一致性约束、快照失效时的降级回退方案与多版本保留策略，并用 H2 内存数据库实测 1000 条事件全量重建与快照恢复的性能对比与一致性验证。</description></item><item><title>《Java 消息中间件·事件驱动架构》9.1 事件溯源概述</title><link>https://plumephp.com/java-mq-arch-09-1-event-sourcing-intro/</link><pubDate>Thu, 29 Oct 2026 08:27:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-09-1-event-sourcing-intro/</guid><description>事件溯源把状态变更历史作为唯一数据来源，本节厘清它与 CQRS + 投影的根本区别，给出适用场景、决策代价与三种常见反模式，讨论事件版本管理与外部系统交互策略，并用 H2 内存数据库演示从纯事件流重建聚合的完整过程与实测输出，佐证状态可复现性。</description></item><item><title>《Java 消息中间件·事件驱动架构》8.3 流增强</title><link>https://plumephp.com/java-mq-arch-08-3-stream-enrichment/</link><pubDate>Thu, 29 Oct 2026 08:26:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-08-3-stream-enrichment/</guid><description>Kafka Streams 中 Stream enrichment（增强）的三种方式：join 做参照表 lookup、branch+merge 做条件分流重组、flatMap 做一对多展开。本节真跑 flatMap 增强拓扑，验证 1 条输入产生 2 条输出。</description></item><item><title>《Java 消息中间件·事件驱动架构》8.2 KTable 的 Join</title><link>https://plumephp.com/java-mq-arch-08-2-table-join/</link><pubDate>Thu, 29 Oct 2026 08:25:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-08-2-table-join/</guid><description>KTable-KTable 内连接与外键、KStream-KTable 左外连接的语义差异与常见错误。本机实测 KStream-KTable left join：key 不存在时输出 null 占位，对比 inner join 的数据丢失行为。</description></item><item><title>《Java 消息中间件·事件驱动架构》8.1 表与流的互转</title><link>https://plumephp.com/java-mq-arch-08-1-stream-table-duality/</link><pubDate>Thu, 29 Oct 2026 08:24:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-08-1-stream-table-duality/</guid><description>Kafka Streams 中 KStream（无界增量事件流）与 KTable（有界快照）的本质差异：同一个 topic 用不同算子消费，输出完全不同。本节真跑「stream -&gt; table -&gt; stream」拓扑，展示中间状态与最终输出。</description></item><item><title>《Java 消息中间件·事件驱动架构》7.3 窗口与聚合</title><link>https://plumephp.com/java-mq-arch-07-3-window-aggregation/</link><pubDate>Thu, 29 Oct 2026 08:23:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-07-3-window-aggregation/</guid><description>Kafka Streams 的窗口操作是时间维度聚合的核心。本节通过编译运行 TimeWindowedKStream 拓扑，展示滚动窗口、跳跃窗口和会话窗口三种类型的边界行为与输出差异，讨论窗口大小与 topic retention 的耦合关系，并给出迟到数据的处理策略与性能影响分析。</description></item><item><title>《Java 消息中间件·事件驱动架构》7.2 状态存储</title><link>https://plumephp.com/java-mq-arch-07-2-state-store/</link><pubDate>Thu, 29 Oct 2026 08:22:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-07-2-state-store/</guid><description>Kafka Streams 的状态存储是本地 RocksDB 实例，与 changelog topic 配合实现故障恢复。本节通过编译运行带状态存储的拓扑，观察 state.dir 目录下的文件结构与大小，对比 KeyValueStore、WindowStore 和 SessionStore 三种类型，并给出状态丢失的重建策略与监控指标。</description></item><item><title>《Java 消息中间件·事件驱动架构》7.1 Streams 的拓扑与处理器</title><link>https://plumephp.com/java-mq-arch-07-1-topology-processor/</link><pubDate>Thu, 29 Oct 2026 08:21:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-07-1-topology-processor/</guid><description>Kafka Streams 的拓扑模型是事件驱动系统的计算引擎。本节通过编译运行真实拓扑获取 Topology.describe() 输出，逐行解析 Source、Processor、Sink 三节点模型，展示有状态处理器的本地 RocksDB 存储结构与 changelog topic 自动创建机制，提供诊断命令与监控指标对照表。</description></item><item><title>《Java 消息中间件·事件驱动架构》6.3 消费者驱动的契约</title><link>https://plumephp.com/java-mq-arch-06-3-consumer-driven-contract/</link><pubDate>Thu, 29 Oct 2026 08:20:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-06-3-consumer-driven-contract/</guid><description>消费者契约不是生产者的单元测试，而是消费者声明「我依赖这些字段」，再由 CI 验证生产者是否遵守。本文用纯 Java 实现契约断言，完整展示「生产者改了字段，测试红了」的四场景输出，并给出一个可嵌入 Maven verify 阶段的契约测试骨架。</description></item><item><title>《Java 消息中间件·事件驱动架构》6.2 兼容性与 Schema 管理</title><link>https://plumephp.com/java-mq-arch-06-2-compat-and-schema/</link><pubDate>Thu, 29 Oct 2026 08:19:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-06-2-compat-and-schema/</guid><description>Schema Registry 不是架构演进的银弹。本文讨论 Registry 的适用边界与三条限制，给出两种无 Registry 的替代方案——消息体内嵌版本信封与代码内版本路由表，并用 Jackson 实测新旧双版本并存解析，展示默认值的回填逻辑。</description></item><item><title>《Java 消息中间件·事件驱动架构》6.1 事件版本化</title><link>https://plumephp.com/java-mq-arch-06-1-event-versioning/</link><pubDate>Thu, 29 Oct 2026 08:18:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-06-1-event-versioning/</guid><description>事件版本号放在主题名、消息信封还是字段里，每种方案在落盘、回放与消费端的成本各不相同。本文用 Java 实测三种版本化方案的兼容性判定逻辑，覆盖加字段、删字段、改名三类变更，按 FORWARD/BACKWARD/FULL 给出可复用的判定表。</description></item><item><title>《Java 消息中间件·事件驱动架构》5.3 并发控制与版本</title><link>https://plumephp.com/java-mq-arch-05-3-versioning-concurrency/</link><pubDate>Thu, 29 Oct 2026 08:17:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-05-3-versioning-concurrency/</guid><description>乐观并发控制通过版本号解决多写者冲突。本节给出 CAS 风格版本号检查的可运行 Java 代码，模拟两个消费者同时写同一聚合根时的检测与重试流程，对比乐观锁与悲观锁的适用边界，包含重试退避策略、libraryd 并发修改场景与生产者幂等联动机制的深度分析。</description></item><item><title>《Java 消息中间件·事件驱动架构》5.2 幂等边界的设计</title><link>https://plumephp.com/java-mq-arch-05-2-idempotence-boundary/</link><pubDate>Thu, 29 Oct 2026 08:16:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-05-2-idempotence-boundary/</guid><description>幂等不是全局属性，而是应用层边界函数。本节深入讨论业务键、消息 ID、自然键三种幂等方案，给出可运行的对照判定代码，演练重平衡导致消息重发时的幂等防护机制，对比生产者幂等与消费者幂等的分界，附带去重表存储成本估算、排查清单与一致性注意事项。</description></item><item><title>《Java 消息中间件·事件驱动架构》5.1 事件顺序与业务顺序</title><link>https://plumephp.com/java-mq-arch-05-1-business-ordering/</link><pubDate>Thu, 29 Oct 2026 08:15:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-05-1-business-ordering/</guid><description>Kafka 分区有序不等于业务有序也不等于因果有序。本机实验模拟乱序到达（COMPLETE→INIT→PAIR），对比时间戳排序与版本号排序两组策略，证明业务因果序必须由事件体自身携带单调版本号维护，时间戳因生产者时钟偏移与发送时序而不可信。</description></item><item><title>《Java 消息中间件·事件驱动架构》4.3 补偿与最终一致性</title><link>https://plumephp.com/java-mq-arch-04-3-compensation/</link><pubDate>Thu, 29 Oct 2026 08:14:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-04-3-compensation/</guid><description>「最终一致」里的「最终」必须是一个可度量的分布，不是一句安慰。本文给出一致性窗口的度量代码：事件产生时打时间戳，下游写库提交后再打一个，按分位统计。本机两段负载实测显示窗口随积压线性增长，慢消费者下 p99 从 81ms 变成 4387ms。据此讨论补偿的触发条件、补偿失败的人工出口，以及一致性窗口该怎么承诺。</description></item><item><title>《Java 消息中间件·事件驱动架构》4.2 本地消息表与对账</title><link>https://plumephp.com/java-mq-arch-04-2-outbox-reconcile/</link><pubDate>Thu, 29 Oct 2026 08:13:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-04-2-outbox-reconcile/</guid><description>卷二讲过 outbox 这个模式，这一节讲它落地要写哪几张表、中继怎么保证至少一次、对账为什么必须三方比对。用 H2 内存库真跑一遍：六个借阅、四类差异（有库无事件、有事件无库、写侧内容不一致、读侧内容不一致），输出差异报告，再演示读模型重建能修复哪一类、修不了哪一类。</description></item><item><title>《Java 消息中间件·事件驱动架构》4.1 分布式事务的三种落地</title><link>https://plumephp.com/java-mq-arch-04-1-distributed-tx/</link><pubDate>Thu, 29 Oct 2026 08:12:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-04-1-distributed-tx/</guid><description>跨服务之后「事务」这个词只剩下一半含义。本文把 2PC、TCC、最终一致三种落地拆开：各自要求什么前提、把不确定性放在哪里、失败时留下什么残局，并用一张四维对照表（一致性强度、可用性、实现成本、失败模式）说明为什么大多数业务最终选了第三种，以及哪两类场景不该选它。</description></item><item><title>《Java 消息中间件·事件驱动架构》3.3 模型重建与重放</title><link>https://plumephp.com/java-mq-arch-03-3-rebuild-replay/</link><pubDate>Thu, 29 Oct 2026 08:11:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-03-3-rebuild-replay/</guid><description>投影表是可丢弃的派生视图。本节真跑一次完整重建实验：先投影 20 条库存事件，清空表后从位移 0 重放重建并对比两次耗时与一致性，验证事件日志作为唯一事实来源的可复现性，深入讨论重建触发条件、快照优化策略、业务低峰期执行建议与常见注意事项。</description></item><item><title>《Java 消息中间件·事件驱动架构》3.2 投影与视图构建</title><link>https://plumephp.com/java-mq-arch-03-2-projection/</link><pubDate>Thu, 29 Oct 2026 08:10:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-03-2-projection/</guid><description>投影是从事件流到读模型的单向转换。本节用 H2 内存表做投影目标，实测 Kafka 消费者消费事件进投影表的全过程，展示幂等写入、顺序处理、查询验证与错误恢复策略，并对比关系型数据库、Redis、Elasticsearch 等多种存储后端。</description></item><item><title>《Java 消息中间件·事件驱动架构》3.1 CQRS 基础</title><link>https://plumephp.com/java-mq-arch-03-1-cqrs-basics/</link><pubDate>Thu, 29 Oct 2026 08:09:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-03-1-cqrs-basics/</guid><description>CQRS 通过命令与读取分离化解读写冲突。本节用 H2 内存数据库演示命令写入、事件生成与投影更新的完整分离流程，给出可运行的 Java 代码示例，深入对比同步双写与异步事件总线两种同步策略，并提供典型应用场景、反模式警示与事件日志操作日志的区别分析。</description></item><item><title>《Java 消息中间件·事件驱动架构》2.3 事件目录与契约</title><link>https://plumephp.com/java-mq-arch-02-3-event-catalog/</link><pubDate>Thu, 29 Oct 2026 08:08:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-02-3-event-catalog/</guid><description>事件目录不是文档，是可执行的契约。本节给出 libraryd 的 events.yaml 全量示例，逐字段说明 name、topic、version、owner、key、schema、consumers、compat 各自约束什么；再把目录与 Java record 做双向漂移检查，实测抓出一次字段改名和两个未登记字段，修复后 224 项检查全绿。</description></item><item><title>《Java 消息中间件·事件驱动架构》2.2 事件边界与聚合</title><link>https://plumephp.com/java-mq-arch-02-2-boundary-aggregate/</link><pubDate>Thu, 29 Oct 2026 08:07:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-02-2-boundary-aggregate/</guid><description>事件粒度由聚合根决定，不由表结构决定。本节用 libraryd 的借阅流程画出 Loan、Book、Hold 三个聚合的边界，说明一个事务只改一个聚合、一次状态迁移只发一条事件、跨聚合用事件而不是共享表；并用共享表建模的对照实验给出 3 条事件、19 个字段、四轮级联 120 条的结构比例。</description></item><item><title>《Java 消息中间件·事件驱动架构》2.1 领域事件识别</title><link>https://plumephp.com/java-mq-arch-02-1-domain-event-discovery/</link><pubDate>Thu, 29 Oct 2026 08:06:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-02-1-domain-event-discovery/</guid><description>事件不是表变更的别名。本节用 libraryd 的六个业务动作演示识别过程：先把动作、状态迁移与表写入分开列，再从迁移里提取过去时事实，最后用确定性 lint 挡掉 UpdateBookStatus、BookRowUpdated 这类伪事件，给出六个事件的命名对照与 12 个候选名的实测判定。</description></item><item><title>《Java 消息中间件·事件驱动架构》1.3 事件驱动成熟度模型</title><link>https://plumephp.com/java-mq-arch-01-3-maturity-model/</link><pubDate>Thu, 29 Oct 2026 08:05:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-01-3-maturity-model/</guid><description>把事件驱动分成五级：消息传递、领域事件、契约治理、流处理、事件溯源。逐级说明能力、代价与常见误判，给出一份 20 题、按 0/1/2 打分的自评表，并用可运行程序算出 libraryd 当前处在第 2 级、升到第 3 级还差哪两项，最后给出升级动作与不该升级的理由。</description></item><item><title>《Java 消息中间件·事件驱动架构》1.2 事件驱动 vs 请求驱动</title><link>https://plumephp.com/java-mq-arch-01-2-event-vs-request/</link><pubDate>Thu, 29 Oct 2026 08:04:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-01-2-event-vs-request/</guid><description>事件驱动不是默认答案。先用四个信号判断什么时候该用事件，再用一张决策树把请求驱动、命令、查询、事件分开；接着用 libraryd 的两个反例说明用错位置的代价：借书前异步查库存导致超卖，借完立刻查列表却读不到。文末附串行调用与扇出的对照实验，并说明延迟收益为何不是主要理由。</description></item><item><title>《Java 消息中间件·事件驱动架构》1.1 事件、命令与查询</title><link>https://plumephp.com/java-mq-arch-01-1-event-command-query/</link><pubDate>Thu, 29 Oct 2026 08:03:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-01-1-event-command-query/</guid><description>从 libraryd 的借阅动作出发，把事件、命令、查询当成三种不同的句子：过去时的事实、祈使的请求、只读的提问。用三个 Java record 和一组可运行的进程内总线实验，展示多播与单接收的差别，并演示命令被广播、事件被点对点投递之后各自坏在哪里。</description></item><item><title>《Java 消息中间件·事件驱动架构》目录与学习路径</title><link>https://plumephp.com/java-mq-arch-toc/</link><pubDate>Thu, 29 Oct 2026 08:02:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-toc/</guid><description>卷三全 50 篇的完整目录：五部分、15 章、45 节，加序、前言与两个附录。每章标注它回答的那个架构问题，并给出三条阅读路径——架构师、开发、评审——以及哪些章节可以跳读、哪些必须配着代码看、每节末尾那条判据在评审时该怎么用，还给出三种路径之外的极简读法。</description></item><item><title>《Java 消息中间件·事件驱动架构》前言：实验环境、Kafka Streams 与案例口径</title><link>https://plumephp.com/java-mq-arch-preface/</link><pubDate>Thu, 29 Oct 2026 08:01:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-preface/</guid><description>把这一卷的实验底座写清楚：机器与工具链、Kafka Streams 的最小可运行验证、三个必须自己补的依赖，以及 libraryd-mq 的工程结构与架构图的画法约定。最后说明本卷的验证规矩——什么样的内容算实测，什么情况下必须标注未在本机执行。</description></item><item><title>《Java 消息中间件·事件驱动架构》 · 全书目录与章节索引</title><link>https://plumephp.com/posts/books/java%E6%B6%88%E6%81%AF%E6%9E%B6%E6%9E%84/</link><pubDate>Thu, 29 Oct 2026 08:00:00 +0800</pubDate><guid>https://plumephp.com/posts/books/java%E6%B6%88%E6%81%AF%E6%9E%B6%E6%9E%84/</guid><description>《Java 消息中间件》卷三：把业务需求翻译成事件契约、读模型、一致性方案与治理规则。覆盖事件与命令的分界、CQRS 与投影、Saga 与补偿、Kafka Streams 的流表模型、可观测与迁移路径，最后用 libraryd 全链路与场景对照收束。本页为章节索引，逐篇链接随正文落盘补全。</description></item><item><title>《Java 消息中间件·事件驱动架构》序：别把消息队列当 RPC</title><link>https://plumephp.com/java-mq-arch-foreword/</link><pubDate>Thu, 29 Oct 2026 08:00:00 +0800</pubDate><guid>https://plumephp.com/java-mq-arch-foreword/</guid><description>把消息队列当成更可靠的 HTTP，是事件驱动架构最常见也最贵的误用。本序拆开三种典型误用——用 MQ 做同步调用、削峰却不管积压、用事件掩盖领域边界——说明它们各自的失效方式与代价，给出本卷的五条立场和五个自检问题：事件是事实的记录，不是调用的替代品。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》附录 B 幂等与事务模板</title><link>https://plumephp.com/java-mq-reliable-appendix-b-idempotent-templates/</link><pubDate>Thu, 29 Oct 2026 07:49:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-appendix-b-idempotent-templates/</guid><description>四份可以直接复制的模板：带唯一约束的去重表、状态机迁移、同库同事务的 outbox 与其 relay、以及消费—处理—生产的事务生产者。每份都标注它解决哪一类重复、在什么位置仍会留下窗口、以及拼在一起时不能混用的边界条件，另附一张按场景选模板的决策表。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》15.3 libraryd-mq 卷二验收</title><link>https://plumephp.com/java-mq-reliable-15-3-acceptance/</link><pubDate>Thu, 29 Oct 2026 07:48:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-15-3-acceptance/</guid><description>把卷二四十五章的实验汇总成十八个验收场景，每条给出可执行的判据、证据章节和结论；另外单独列出十项本机做不出来因而不能算通过的检查，说明各自的风险。文末附一份可以直接改造成脚本的检查骨架、0/1/2 打分口径，以及卷二遗留问题与卷三的分工安排，方便团队评审时直接对照使用。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》附录 A 可靠性配置矩阵</title><link>https://plumephp.com/java-mq-reliable-appendix-a-config-matrix/</link><pubDate>Thu, 29 Oct 2026 07:48:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-appendix-a-config-matrix/</guid><description>生产端、消费端、broker 端三张配置表，每一项只回答两个问题：它保住了什么，代价是什么。附六组看起来没问题、实际互相抵消的危险组合，以及一份可以直接抄走的基线配置。默认值按 Kafka 4.3.0 与 kafka-clients 4.3.0 列出。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》15.2 容量与成本核算</title><link>https://plumephp.com/java-mq-reliable-15-2-cost/</link><pubDate>Thu, 29 Oct 2026 07:46:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-15-2-cost/</guid><description>可靠性每一项配置都有账单：副本数乘存储、acks 乘内部复制流量、保留期乘天数、跨集群乘出网。本篇不谈具体价格，只给可核算的量——一天 1000 万条 1 KiB 消息，三档方案各需要多少 GB·天、多少出网流量，以及故障时才支付的副本重建成本。每一档都标出它能防住哪种故障，以及哪一笔钱其实可以不花。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》14.3 恢复演练与 RTO/RPO</title><link>https://plumephp.com/java-mq-reliable-14-3-drill-rto-rpo/</link><pubDate>Thu, 29 Oct 2026 07:45:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-14-3-drill-rto-rpo/</guid><description>三节点 KRaft 上做一次带流量的完整演练：生产 15000 条、消费者常驻，中途停掉一台 broker。实测故障检测 4 秒、数据面恢复 29 秒、业务面 lag 归零 41 秒，生产者 0 失败。文章把这 41 秒拆成五段，说明哪一段是真 RTO、哪一段是人为停机窗口，并给出可重复的演练脚本要素与判据。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》15.1 可靠性验收清单</title><link>https://plumephp.com/java-mq-reliable-15-1-reliability-checklist/</link><pubDate>Thu, 29 Oct 2026 07:45:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-15-1-reliability-checklist/</guid><description>三十条可靠性检查项，分生产端、消费端、broker 与主题、数据链路、运维演练五组。每一条都给可观测的判据、对应的章节、以及不达标时的修改动作——判据都是「做一件具体的事，看一次结果」，不是「已配置」。五组各自附一节最容易做错的地方，末附打分口径与按边际效率排序的修改顺序。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》14.2 故障注入：消费端崩溃</title><link>https://plumephp.com/java-mq-reliable-14-2-fault-consumer-crash/</link><pubDate>Thu, 29 Oct 2026 07:43:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-14-2-fault-consumer-crash/</guid><description>kill -9 一个处理到一半的消费者，实测重复了 61 条：崩溃时处理到 offset 460，最后提交的是 400，重启从 400 继续。再用 SIGSTOP 冻结进程做对照，发现 10 秒后组里变成「no active members」，恢复后从 offset 0 重读。两次实验证明 session.timeout.ms 保护的是「进程卡住」，不是「进程死掉」。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》14.1 故障注入：broker 宕机</title><link>https://plumephp.com/java-mq-reliable-14-1-fault-broker-down/</link><pubDate>Thu, 29 Oct 2026 07:42:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-14-1-fault-broker-down/</guid><description>三节点集群停掉一台，5 万条消息里 0 条失败，停机那 5 秒的平均延迟只从 5.8 毫秒升到 6.3 毫秒——因为 ISR 在 3 秒内收缩到 2，leader 自动换了人。同一时刻另一个 min.insync.replicas=3 的主题在 740 毫秒内重试三次后被拒。两种结果的区别不在故障，在配置。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》13.3 跨集群复制</title><link>https://plumephp.com/java-mq-reliable-13-3-cross-cluster/</link><pubDate>Thu, 29 Oct 2026 07:41:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-13-3-cross-cluster/</guid><description>跨集群复制是异步的，异步就有延迟、重复和位移错位。本篇在本机用两个单节点集群加 MirrorMaker2 实测：820 条消息 1:1 复制、逐条端到端延迟尾部 70–113 ms、offset-syncs 记录 0→0 与 519→519，并原样贴出一个与 offset-syncs 对不上的 checkpoint 记录，说明切换前为什么必须自己校验位移映射。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》13.2 SASL/ACL 与传输加密</title><link>https://plumephp.com/java-mq-reliable-13-2-sasl-acl/</link><pubDate>Thu, 29 Oct 2026 07:40:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-13-2-sasl-acl/</guid><description>配额管的是速率，认证和授权才管得住身份。本篇在本机单节点上起一个 SCRAM-SHA-256 加 ACL 的 broker，贴出未授权读取的 TopicAuthorizationException、错误密码的 SaslAuthenticationException、以及 topic 放行但 group 被拒的原始异常；并用同一份生产者对照 PLAINTEXT、SSL、SASL 的握手与稳态延迟。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》13.1 多租户与配额</title><link>https://plumephp.com/java-mq-reliable-13-1-multi-tenant-quota/</link><pubDate>Thu, 29 Oct 2026 07:39:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-13-1-multi-tenant-quota/</guid><description>客户端配额让吵闹的邻居变慢，而不是被踢掉。本篇在本机单节点上把 producer_byte_rate 配成 1024 B/s，用同一个 Java 生产者跑配额前后两组对照：385 ms 变成 15943 ms，客户端 produce-throttle-time 平均值 782 ms，16 条消息全部 ack、没有一条被拒；再给出按 client-id、按 user、按前缀与物理隔离的多租户方案。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》12.3 消费端性能调优</title><link>https://plumephp.com/java-mq-reliable-12-3-consumer-tuning/</link><pubDate>Thu, 29 Oct 2026 07:38:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-12-3-consumer-tuning/</guid><description>fetch.min.bytes、fetch.max.wait.ms、max.poll.records 三个参数一起调时，批次不是越大越好。本机用 20 万条固定积压跑四组参数，1MB 组比 100 条组快 1.4 倍，而 8MB 组因为超过单次 fetch 上限，每次等待 1 秒、吞吐掉到二十四分之一。附 poll 延迟 p99 与调参顺序。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》12.2 异步提交的陷阱</title><link>https://plumephp.com/java-mq-reliable-12-2-async-commit-pitfall/</link><pubDate>Thu, 29 Oct 2026 07:37:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-12-2-async-commit-pitfall/</guid><description>commitAsync 返回 void，失败既不抛异常也不改返回值；错误要么被丢弃，要么只能等下一次 poll 才在回调里出现。本机复现了被踢出组后异步提交失败、committed 仍为空的全过程，并对照 commitSync 的异常，附回调线程、阻塞与重入的实测。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》12.1 消费者多线程模型</title><link>https://plumephp.com/java-mq-reliable-12-1-consumer-threading/</link><pubDate>Thu, 29 Oct 2026 07:36:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-12-1-consumer-threading/</guid><description>一个消费者跑满一核、lag 却不降时，加线程有三种写法：每线程一个消费者、一个拉取线程加共享工作池、按分区亲和路由。本机用 4 分区 16 万条消息实测三种模型，贴出吞吐、线程数与逆序次数；结论是保序不贵、跨线程交接贵，池化模型必须把提交点压在处理完成之后。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》11.3 大消息的 claim-check 模式</title><link>https://plumephp.com/java-mq-reliable-11-3-claim-check/</link><pubDate>Thu, 29 Oct 2026 07:35:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-11-3-claim-check/</guid><description>消息里只放 URI、SHA-256 与长度，内容进对象存储，这是大消息的常规出路，但它把一次写入拆成两个系统，失败窗口也随之翻倍。本篇给出最小 claim-check 实现，实测文件被删与校验和不符两条失败路径，演示重试、兜底主题与位移提交的先后顺序。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》11.2 压缩算法选择</title><link>https://plumephp.com/java-mq-reliable-11-2-compression-choice/</link><pubDate>Thu, 29 Oct 2026 07:34:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-11-2-compression-choice/</guid><description>同一批事件，gzip、snappy、lz4、zstd 的压缩比可以差两倍以上，CPU 可以差五倍；批次太小或数据本身不可压时，压缩还会让字节数变大。本篇用同一份真实结构的事件跑四种算法，贴出压缩后字节、发送耗时与 broker 落盘字节，并给出负收益判据。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》11.1 消息大小与批量参数</title><link>https://plumephp.com/java-mq-reliable-11-1-message-size/</link><pubDate>Thu, 29 Oct 2026 07:33:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-11-1-message-size/</guid><description>一条消息要过四层尺寸参数：客户端 max.request.size、批量 batch.size、broker 与 topic 的 message.max.bytes、消费端 fetch 上限。本篇在本机逐级放大消息，记录每一档在哪一层被拦、异常原文与错误码，并实测压缩如何让 2 MiB 消息穿过 1 MiB 的 broker 上限。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》10.3 重分区与历史数据</title><link>https://plumephp.com/java-mq-reliable-10-3-repartition/</link><pubDate>Thu, 29 Oct 2026 07:32:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-10-3-repartition/</guid><description>分区数是 key 映射公式里的模数，改一次就有近一半的 key 要换分区。本篇用 20 000 个 key 算出 4→8、4→5、8→12 的落点变化比例，再跑一遍 6 000 条、3 000 个 key 的桥接迁移与双写切换，验证顺序不丢、条数对得上，并给出位移重置与回滚的检查清单。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》10.2 热点分区与 key 设计</title><link>https://plumephp.com/java-mq-reliable-10-2-hot-partition/</link><pubDate>Thu, 29 Oct 2026 07:31:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-10-2-hot-partition/</guid><description>单调递增的 id 在 Kafka 默认分区器下其实很均匀，12 000 条实测最大分区只有平均值的 1.04 倍；真正打满一个分区的是范围分区器、单个热 key 和错误的加盐。本篇用六组 12 000 条实验量出 12 倍、10.9 倍、2.85 倍的分布，并给出盐值与分区的落点校验方法。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》10.1 顺序的粒度与代价</title><link>https://plumephp.com/java-mq-reliable-10-1-ordering-granularity/</link><pubDate>Thu, 29 Oct 2026 07:30:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-10-1-ordering-granularity/</guid><description>同一条消息在单分区里排队，才轮得到顺序。本篇把全局、分区、业务键三种粒度拆开，用 200 条同 key 消息在 in-flight 1/2/5 下各跑三遍，再用暂停 broker 四秒触发超时重试：幂等组 9 次运行全部 0 乱序、0 重复，非幂等组在途 5 时 20 处逆序、5 条重复。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》9.3 最终一致性的度量</title><link>https://plumephp.com/java-mq-reliable-09-3-eventual-consistency-metrics/</link><pubDate>Thu, 29 Oct 2026 07:29:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-09-3-eventual-consistency-metrics/</guid><description>最终一致不是一个形容词，而是一组可以画在面板上的数字。本篇给每条事件带上产生时间戳，在下游落库时计算端到端延迟，本机跑出基线 P50/P95/P99 与最长窗口，再注入 10% 的慢路径看尾延迟怎么变；最后写一个对账任务，故意漏发两条、重发一条，验证它能把条数、金额和重复同时报出来。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》9.2 补偿事务的幂等</title><link>https://plumephp.com/java-mq-reliable-09-2-compensation-idempotence/</link><pubDate>Thu, 29 Oct 2026 07:28:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-09-2-compensation-idempotence/</guid><description>补偿会被重试、重放和并发再次执行；补偿本身不幂等时，一次失败会变成两次超还。本篇在 libraryd 库存场景里分别跑无条件反向更新、WHERE 守卫和补偿令牌三种写法，贴出同一条补偿执行两次的真实差异，并演示补偿服务持续不可用时进入人工队列、恢复后幂等重放的完整路径。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》9.1 Saga：编排与协同</title><link>https://plumephp.com/java-mq-reliable-09-1-saga/</link><pubDate>Thu, 29 Oct 2026 07:27:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-09-1-saga/</guid><description>Saga 把跨服务的长事务拆成一组可补偿的本地动作。本篇用 libraryd 借阅场景实现一个可运行的编排式 Saga：创建借阅、预留库存、冻结额度三步，在第二步和第三步各失败一次，贴出本机真实的补偿轨迹与最终状态，并给出状态机表、崩溃恢复分析与落地清单。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》8.3 Schema Registry 的取舍</title><link>https://plumephp.com/java-mq-reliable-08-3-schema-registry/</link><pubDate>Thu, 29 Oct 2026 07:26:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-08-3-schema-registry/</guid><description>集中式 schema 管理能给你版本查找、兼容性门禁和跨语言契约，代价是多一个服务、多一次依赖和一套客户端耦合。本篇不引入任何第三方 registry 客户端，只用消息头、schema 文件和 CI 脚本，搭一个能跑的最小自管方案，并给出该不该上 registry 的判定表。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》8.2 schema 演进与兼容性</title><link>https://plumephp.com/java-mq-reliable-08-2-schema-evolution/</link><pubDate>Thu, 29 Oct 2026 07:25:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-08-2-schema-evolution/</guid><description>加字段、删字段、改类型、改字段名，四种变更分别能不能兼容？本篇用同一份 JSON payload，让老消费者读新消息、新消费者读旧消息，八个方向逐个跑，贴出 ClassCastException 与 NullPointerException 的原文，并给出双写双读的发布顺序、回滚判据与七条上线前检查清单。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》8.1 领域事件建模</title><link>https://plumephp.com/java-mq-reliable-08-1-domain-event-modeling/</link><pubDate>Thu, 29 Oct 2026 07:24:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-08-1-domain-event-modeling/</guid><description>事件是已经发生的事实，不是请求也不是状态快照。本篇先划清事件体该放什么、不该放什么，再给出 libraryd 六个事件的 record 定义，逐字段说明它为什么存在、缺了会怎样；最后用一次本机实测说明事件 ID 与增量字段如何决定重放是否可重复。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》7.3 事件溯源入门</title><link>https://plumephp.com/java-mq-reliable-07-3-event-sourcing-intro/</link><pubDate>Thu, 29 Oct 2026 07:23:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-07-3-event-sourcing-intro/</guid><description>只存当前状态，你能回答「现在是什么」，回答不了「为什么变成这样」。事件溯源把状态变更本身作为唯一事实来源，状态由重放推导。本篇用纯 JDK 实现最小事件存储，追加 8 个库存事件后从 0 重放得到 stock=9、reserved=12，再用 version=4 的快照加 4 条增量重放，两条路径结果逐字段相等；并实测乐观并发与重复 eventId 两种拒绝。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》7.2 CDC：增量快照与变更捕获</title><link>https://plumephp.com/java-mq-reliable-07-2-cdc/</link><pubDate>Thu, 29 Oct 2026 07:22:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-07-2-cdc/</guid><description>日志挖掘读数据库的变更日志，查询轮询读一张带水位列的表，两者在 op 语义、删除可见性和业务侵入上完全不同。本篇手写轮询版 CDC 实测 c/u/d 三种变更，用同一毫秒的两行证明单列时间水位会漏数据，再用快照前取水位与快照后取水位两种顺序，说明衔接为什么只有前者能得到一致状态；Debezium 仅做架构对照并标注未在本机执行。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》7.1 Outbox 模式</title><link>https://plumephp.com/java-mq-reliable-07-1-outbox/</link><pubDate>Thu, 29 Oct 2026 07:21:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-07-1-outbox/</guid><description>先写库再发消息，会在进程崩溃时留下「有业务行、无事件」的孤儿数据。本篇用同库同事务的 outbox 表消除这个窗口，给出轮询发布器的完整实现，并在本机用嵌入式数据库真实 kill -9：写入 5 笔后崩溃、发送 3 条未标记就崩溃，重启补发后业务行 5、outbox 行 5、Kafka 8 条记录 5 个事件 ID，逐条对上。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》6.3 毒消息隔离与人工干预</title><link>https://plumephp.com/java-mq-reliable-06-3-poison-message/</link><pubDate>Thu, 29 Oct 2026 07:20:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-06-3-poison-message/</guid><description>毒消息不是「处理失败」，而是每次都以同样方式失败、无法自愈的消息。本篇在本机让一条坏消息把整个分区卡住 30 秒：消费位移停在 2，LAG 从 4 涨到 9；再演示转入隔离主题、提交位移、分区恢复消费，并用 libraryd 的退货事件给出人工修复后回灌必须满足的幂等前提。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》6.2 重试主题与退避</title><link>https://plumephp.com/java-mq-reliable-06-2-retry-topic/</link><pubDate>Thu, 29 Oct 2026 07:19:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-06-2-retry-topic/</guid><description>原地重试会占住分区，进程一崩还会丢掉等待中的重试。本篇用三级重试主题把等待外置，实测一条消息从主主题到 DLT 的完整时间轨迹（5 秒、15 秒、45 秒三档退避），量化重试带来的记录放大：100 条业务消息产生 140 条记录，并给出可落地的参数与观测判据。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》6.1 死信队列的设计</title><link>https://plumephp.com/java-mq-reliable-06-1-dlq-design/</link><pubDate>Thu, 29 Oct 2026 07:18:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-06-1-dlq-design/</guid><description>死信队列不是失败消息的垃圾桶，而是一份可回放的失败证据。本篇给出进入死信的判据、必须随消息搬运的元信息清单，并在 Kafka 4.3.0 上跑通完整链路：九条消息中一条重试耗尽进入 DLT，贴出死信头原文，再把修复后的消息回灌原主题，最后给出可验收的判据与反模式清单。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》5.3 消费速率控制与背压</title><link>https://plumephp.com/java-mq-reliable-05-3-consume-backpressure/</link><pubDate>Thu, 29 Oct 2026 07:17:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-05-3-consume-backpressure/</guid><description>下游只有每秒 870 条的能力，消费者硬拉会怎样？实测不限速时 3.7 秒把 3 万条全拉进 JVM，队列峰值 29783，客户端内 p99 滞留 29.7 秒；用 pause/resume 把队列压到 1995，p99 降到 1.9 秒。附一份可运行的背压实现与 AIMD 限速器。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》5.2 积压处置：扩容、跳过与降级</title><link>https://plumephp.com/java-mq-reliable-05-2-backlog-playbook/</link><pubDate>Thu, 29 Oct 2026 07:16:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-05-2-backlog-playbook/</guid><description>积压处置的第一步不是扩容，而是算清楚「追得上还是追不上」。本篇用 9 万条真实积压，分别走加消费者、提高批量和跳过三条路径，记录每秒采样的 LAG 曲线：3 个消费者只快 1.4 倍、批量放大 10 倍只快 13%、跳过 7.2 万条要先等组变空。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》5.1 lag 的三种口径与误读</title><link>https://plumephp.com/java-mq-reliable-05-1-lag-definitions/</link><pubDate>Thu, 29 Oct 2026 07:15:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-05-1-lag-definitions/</guid><description>同一时刻同一分区，kafka-consumer-groups.sh 报 LAG=800，客户端 records-lag-max 显示 900，手算 LEO−position 是 600。三个数都不是 bug，而是三种口径。本篇用一次真实取数把这三种口径拆开，附源码依据与 70 秒空转后指标变 NaN 的实测。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》4.3 扩缩容与优雅停机</title><link>https://plumephp.com/java-mq-reliable-04-3-scale-graceful-shutdown/</link><pubDate>Thu, 29 Oct 2026 07:14:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-04-3-scale-graceful-shutdown/</guid><description>扩容一个消费者会触发整组再平衡，停机的姿势决定了消息是重复、丢失还是要等会话超时。本篇给出一份完整可运行的优雅停止代码，用 1200 条消息实测 SIGTERM 后零重复零丢失；再让一个消费者停 poll 25 秒，贴出 max.poll.interval.ms 踢出的原始 WARN 日志，并数清 1212 次投递里的重复。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》4.2 分配策略与消费者倾斜</title><link>https://plumephp.com/java-mq-reliable-04-2-assignment-skew/</link><pubDate>Thu, 29 Oct 2026 07:13:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-04-2-assignment-skew/</guid><description>7 个分区、2 到 3 个消费者，range、round-robin、sticky、cooperative-sticky 四种策略各跑一遍：谁撤销了全部分区，谁只撤销搬走的那几个，谁多花一轮协议，谁把 8 个分区分成 4-2-2。本篇把分配结果、迁移分区数、再平衡耗时与倾斜成因放进同一组实测数据，并给出观测与选型方法。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》4.1 消费组设计：按业务还是按分区</title><link>https://plumephp.com/java-mq-reliable-04-1-group-design/</link><pubDate>Thu, 29 Oct 2026 07:12:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-04-1-group-design/</guid><description>消费组不是一个进程列表，而是一份职责加一套位移。本篇用 600 条消息、两个快慢不同的消费者和三个订阅同一主题的组，量出「同组能力必须一致」与「多组订阅的复制成本」，再给出按业务域、按处理职责、按分区手工分配三种方案的对照，以及组 ID 命名、空组回收与选择清单。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》3.3 事务的性能与运维代价</title><link>https://plumephp.com/java-mq-reliable-03-3-transaction-cost/</link><pubDate>Thu, 29 Oct 2026 07:11:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-03-3-transaction-cost/</guid><description>事务不是免费的：多一次协调器往返、多一个状态主题、多一段 LSO 阻塞，还要为 abort 的数据付磁盘钱。本篇用 broker 请求日志数出每个事务多发了哪些 RPC，用两组单次运行对比事务与非事务的发送耗时，并给出判断「什么时候不该用事务」的工程判据。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》3.2 事务超时、fencing 与 abort</title><link>https://plumephp.com/java-mq-reliable-03-2-transaction-timeout/</link><pubDate>Thu, 29 Oct 2026 07:10:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-03-2-transaction-timeout/</guid><description>事务不会永远开着：transaction.timeout.ms 到期后由协调器主动中止，客户端下一次提交只会收到一个致命错误。本篇实测超时事务的 abort 时点与数据形态，再用两个同 transactional.id 的生产者复现 fencing，说明僵尸写入为什么会被拒绝。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》3.1 事务生产者与 read_committed</title><link>https://plumephp.com/java-mq-reliable-03-1-transaction-producer/</link><pubDate>Thu, 29 Oct 2026 07:09:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-03-1-transaction-producer/</guid><description>事务生产者把多条消息与消费位移放进一个原子单元。本篇跑通 transactional.id、initTransactions、begin/commit/abort 全流程，用同一份数据分别喂给 read_committed 与 read_uncommitted 消费者，对照提交与中止的可见性，并解释 LSO 为什么会挡住事务之后的消息。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》2.3 恰好一次的两种实现与成本</title><link>https://plumephp.com/java-mq-reliable-02-3-exactly-once-cost/</link><pubDate>Thu, 29 Oct 2026 07:08:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-02-3-exactly-once-cost/</guid><description>Kafka 事务保证的是「多条记录与位移一起提交或一起回滚」，业务恰好一次保证的是「副作用只发生一次」，两者覆盖的范围不同。本篇实测每条一事务、十条一批事务与非事务发送的耗时，再用一个 read_committed 消费者重放已提交记录，展示事务提交后业务仍然重复的完整链路，并给出两种方案的对照表与成立前提清单。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》2.2 幂等消费：唯一键、状态机与去重表</title><link>https://plumephp.com/java-mq-reliable-02-2-idempotent-consume/</link><pubDate>Thu, 29 Oct 2026 07:07:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-02-2-idempotent-consume/</guid><description>唯一约束、去重表、状态机是三种成本不同的幂等实现，选错一种会在并发或重放时失效。本篇先比较三者的写放大、存储与失效边界，再给出一份完整可运行的 IdempotentConsumer：按业务键串行化、PROCESSING/DONE 状态、失败不记账、TTL 惰性清理、容量硬上限，并用 3000 次重复投递和 16 线程同键并发验证它。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》2.1 重复的四种来源</title><link>https://plumephp.com/java-mq-reliable-02-1-duplicate-sources/</link><pubDate>Thu, 29 Oct 2026 07:06:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-02-1-duplicate-sources/</guid><description>重复不是一种故障，而是四种：生产侧重试、消费者再平衡、位移回退、下游重放。本篇用单节点 Kafka 分别构造四类重复，给出每类的原始输出与可识别特征——位移是否相同、eventId 是否相同、是否留下新的生产者序列号，并据此给出一张排查判据表。最后给出处理账本的最小设计，让四类重复在日志里可被区分。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》1.3 消费端：手动提交与位移管理</title><link>https://plumephp.com/java-mq-reliable-01-3-consumer-commit/</link><pubDate>Thu, 29 Oct 2026 07:05:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-01-3-consumer-commit/</guid><description>自动提交提交的是「拉取位置」而不是「处理进度」：一次 close 就把 20 条里没处理的 15 条永久跳过。本机用 40 条消息对照 auto-close、auto-kill 与手动提交三种写法，给出已提交位移、重启后重读范围与源码调用链，并划清提交失败时哪些异常可以重试、哪些必须重新加入消费组。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》1.2 生产端：acks、重试与幂等</title><link>https://plumephp.com/java-mq-reliable-01-2-producer-reliability/</link><pubDate>Thu, 29 Oct 2026 07:04:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-01-2-producer-reliability/</guid><description>acks=all 只是必要条件：还要看 min.insync.replicas 是否被副本数钳制、ISR 当时够不够、以及是否发生不干净选举。本篇用一个 controller 加三个 broker 杀掉两任 leader，对照 acks=1 的 100 条静默丢失与 acks=all 的完整保留，再拆开 retries、delivery.timeout.ms 与幂等生产者的边界。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》1.1 端到端可靠性的责任边界</title><link>https://plumephp.com/java-mq-reliable-01-1-reliability-boundary/</link><pubDate>Thu, 29 Oct 2026 07:03:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-01-1-reliability-boundary/</guid><description>一条消息从 send() 到下游落库要经过生产端、broker、消费端、下游存储四段，每段对「成功」的定义都不同。本篇给出四段责任表与各自的失败模式，并用 8 条消息把一次完整追踪和一次崩溃恢复跑出来，说明「消息不丢」到底停在哪一段，以及三段交接处必须写明的契约。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》目录与学习路径</title><link>https://plumephp.com/java-mq-reliable-toc/</link><pubDate>Thu, 29 Oct 2026 07:02:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-toc/</guid><description>卷二全 50 篇的完整目录：五部分、15 章、45 节，加序、前言与两个附录。每章标注它回答的那一个问题，并给出三条阅读路径——赶时间只看判据的、要落地一条链路的、准备做演练与验收的，另外标明哪些实验可以跳过、哪些必须亲手做，以及每节末尾那条判据该怎么用。</description></item><item><title>《Java 消息中间件·可靠消息与消费治理》前言：实验环境与故障注入口径</title><link>https://plumephp.com/java-mq-reliable-preface/</link><pubDate>Thu, 29 Oct 2026 07:01:00 +0800</pubDate><guid>https://plumephp.com/java-mq-reliable-preface/</guid><description>把这一卷的实验底座写清楚：单节点与三节点集群怎么起、客户端工程怎么配，以及最关键的故障注入口径——stop、kill、pause、改配置四种手段各自模拟什么、ISR 何时收缩、本机实测到多少，还有哪些故障本机做不出来、必须标注为未执行并说明它影响哪一条结论。</description></item></channel></rss>