这里是全站文章的归档入口,下面是按时间倒序排列的全部文章。若想按主题浏览,请从首页的专题分类进入。
《Java 消息中间件·可靠消息与消费治理》14.3 恢复演练与 RTO/RPO
三节点 KRaft 上做一次带流量的完整演练:生产 15000 条、消费者常驻,中途停掉一台 broker。实测故障检测 4 秒、数据面恢复 29 秒、业务面 lag 归零 41 秒,生产者 0 失败。文章把这 41 秒拆成五段,说明哪一段是真 RTO、哪一段是人为停机窗口,并给出可重复的演练脚本要素与判据。
posts
这里是全站文章的归档入口,下面是按时间倒序排列的全部文章。若想按主题浏览,请从首页的专题分类进入。
三节点 KRaft 上做一次带流量的完整演练:生产 15000 条、消费者常驻,中途停掉一台 broker。实测故障检测 4 秒、数据面恢复 29 秒、业务面 lag 归零 41 秒,生产者 0 失败。文章把这 41 秒拆成五段,说明哪一段是真 RTO、哪一段是人为停机窗口,并给出可重复的演练脚本要素与判据。
kill -9 一个处理到一半的消费者,实测重复了 61 条:崩溃时处理到 offset 460,最后提交的是 400,重启从 400 继续。再用 SIGSTOP 冻结进程做对照,发现 10 秒后组里变成「no active members」,恢复后从 offset 0 重读。两次实验证明 session.timeout.ms 保护的是「进程卡住」,不是「进程死掉」。
三节点集群停掉一台,5 万条消息里 0 条失败,停机那 5 秒的平均延迟只从 5.8 毫秒升到 6.3 毫秒——因为 ISR 在 3 秒内收缩到 2,leader 自动换了人。同一时刻另一个 min.insync.replicas=3 的主题在 740 毫秒内重试三次后被拒。两种结果的区别不在故障,在配置。
跨集群复制是异步的,异步就有延迟、重复和位移错位。本篇在本机用两个单节点集群加 MirrorMaker2 实测:820 条消息 1:1 复制、逐条端到端延迟尾部 70–113 ms、offset-syncs 记录 0→0 与 519→519,并原样贴出一个与 offset-syncs 对不上的 checkpoint 记录,说明切换前为什么必须自己校验位移映射。
卷四前言:说明读者假设、13 章的组织方式、每章的统一结构、可运行 Go 实验工程的包划分、代码分级、规模与成本口径、三种阅读路径、代码阅读顺序、表格读法与退出条件,以及如何判断自己真的读懂了规模化决策;文中 Go 代码均可在本地逐字节复现。
配额管的是速率,认证和授权才管得住身份。本篇在本机单节点上起一个 SCRAM-SHA-256 加 ACL 的 broker,贴出未授权读取的 TopicAuthorizationException、错误密码的 SaslAuthenticationException、以及 topic 放行但 group 被拒的原始异常;并用同一份生产者对照 PLAINTEXT、SSL、SASL 的握手与稳态延迟。
客户端配额让吵闹的邻居变慢,而不是被踢掉。本篇在本机单节点上把 producer_byte_rate 配成 1024 B/s,用同一个 Java 生产者跑配额前后两组对照:385 ms 变成 15943 ms,客户端 produce-throttle-time 平均值 782 ms,16 条消息全部 ack、没有一条被拒;再给出按 client-id、按 user、按前缀与物理隔离的多租户方案。
fetch.min.bytes、fetch.max.wait.ms、max.poll.records 三个参数一起调时,批次不是越大越好。本机用 20 万条固定积压跑四组参数,1MB 组比 100 条组快 1.4 倍,而 8MB 组因为超过单次 fetch 上限,每次等待 1 秒、吞吐掉到二十四分之一。附 poll 延迟 p99 与调参顺序。
commitAsync 返回 void,失败既不抛异常也不改返回值;错误要么被丢弃,要么只能等下一次 poll 才在回调里出现。本机复现了被踢出组后异步提交失败、committed 仍为空的全过程,并对照 commitSync 的异常,附回调线程、阻塞与重入的实测。
一个消费者跑满一核、lag 却不降时,加线程有三种写法:每线程一个消费者、一个拉取线程加共享工作池、按分区亲和路由。本机用 4 分区 16 万条消息实测三种模型,贴出吞吐、线程数与逆序次数;结论是保序不贵、跨线程交接贵,池化模型必须把提交点压在处理完成之后。
消息里只放 URI、SHA-256 与长度,内容进对象存储,这是大消息的常规出路,但它把一次写入拆成两个系统,失败窗口也随之翻倍。本篇给出最小 claim-check 实现,实测文件被删与校验和不符两条失败路径,演示重试、兜底主题与位移提交的先后顺序。
同一批事件,gzip、snappy、lz4、zstd 的压缩比可以差两倍以上,CPU 可以差五倍;批次太小或数据本身不可压时,压缩还会让字节数变大。本篇用同一份真实结构的事件跑四种算法,贴出压缩后字节、发送耗时与 broker 落盘字节,并给出负收益判据。
一条消息要过四层尺寸参数:客户端 max.request.size、批量 batch.size、broker 与 topic 的 message.max.bytes、消费端 fetch 上限。本篇在本机逐级放大消息,记录每一档在哪一层被拦、异常原文与错误码,并实测压缩如何让 2 MiB 消息穿过 1 MiB 的 broker 上限。
分区数是 key 映射公式里的模数,改一次就有近一半的 key 要换分区。本篇用 20 000 个 key 算出 4→8、4→5、8→12 的落点变化比例,再跑一遍 6 000 条、3 000 个 key 的桥接迁移与双写切换,验证顺序不丢、条数对得上,并给出位移重置与回滚的检查清单。
单调递增的 id 在 Kafka 默认分区器下其实很均匀,12 000 条实测最大分区只有平均值的 1.04 倍;真正打满一个分区的是范围分区器、单个热 key 和错误的加盐。本篇用六组 12 000 条实验量出 12 倍、10.9 倍、2.85 倍的分布,并给出盐值与分区的落点校验方法。
卷四序:当「回声」从一条交易链路长成多业务、多地域、多团队共用的平台,架构的主要矛盾从「能不能实现」变成「能不能长大」。用一个单元路由配置事故说明规模化的代价,交代四条曲线、三个不能省的判断、13 章组织、三种读法与本卷不回答的问题与边界。
同一条消息在单分区里排队,才轮得到顺序。本篇把全局、分区、业务键三种粒度拆开,用 200 条同 key 消息在 in-flight 1/2/5 下各跑三遍,再用暂停 broker 四秒触发超时重试:幂等组 9 次运行全部 0 乱序、0 重复,非幂等组在途 5 时 20 处逆序、5 条重复。
最终一致不是一个形容词,而是一组可以画在面板上的数字。本篇给每条事件带上产生时间戳,在下游落库时计算端到端延迟,本机跑出基线 P50/P95/P99 与最长窗口,再注入 10% 的慢路径看尾延迟怎么变;最后写一个对账任务,故意漏发两条、重发一条,验证它能把条数、金额和重复同时报出来。
补偿会被重试、重放和并发再次执行;补偿本身不幂等时,一次失败会变成两次超还。本篇在 libraryd 库存场景里分别跑无条件反向更新、WHERE 守卫和补偿令牌三种写法,贴出同一条补偿执行两次的真实差异,并演示补偿服务持续不可用时进入人工队列、恢复后幂等重放的完整路径。
Saga 把跨服务的长事务拆成一组可补偿的本地动作。本篇用 libraryd 借阅场景实现一个可运行的编排式 Saga:创建借阅、预留库存、冻结额度三步,在第二步和第三步各失败一次,贴出本机真实的补偿轨迹与最终状态,并给出状态机表、崩溃恢复分析与落地清单。