<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>可靠性 on 追风笔记</title><link>https://4f0a9a3b.wangpeng.pages.dev/tags/%E5%8F%AF%E9%9D%A0%E6%80%A7/</link><description>Recent content in 可靠性 on 追风笔记</description><generator>Hugo</generator><language>zh</language><lastBuildDate>Tue, 25 Aug 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://4f0a9a3b.wangpeng.pages.dev/tags/%E5%8F%AF%E9%9D%A0%E6%80%A7/index.xml" rel="self" type="application/rss+xml"/><item><title>Kafka 可靠性与精确一次</title><link>https://4f0a9a3b.wangpeng.pages.dev/tech/kafka/reliability/</link><pubDate>Tue, 25 Aug 2026 00:00:00 +0000</pubDate><guid>https://4f0a9a3b.wangpeng.pages.dev/tech/kafka/reliability/</guid><description>&lt;p&gt;Kafka 的可靠性需要在 producer、broker、consumer 三端协同配置。下面从「不丢、不重、有序」三个目标展开。&lt;/p&gt;&#10;&lt;h2 id="producer-端的可靠性"&gt;Producer 端的可靠性&#10;&lt;/h2&gt;&#10;&lt;p&gt;通过 &lt;code&gt;acks&lt;/code&gt; 控制写入持久化级别：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;acks=0&lt;/code&gt;：发完即认为成功，可能丢消息，吞吐最高。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;acks=1&lt;/code&gt;：leader 写入即成功，leader 宕机可能丢。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;acks=all&lt;/code&gt;：ISR 全部同步才成功，最安全，配合 &lt;code&gt;min.insync.replicas&lt;/code&gt; 防单点。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;开启重试（&lt;code&gt;retries&lt;/code&gt;）可应对瞬时失败，但会带来&lt;strong&gt;重复&lt;/strong&gt;：网络抖动导致 producer 未收到 ack 而重试，同一条消息被写两次。&lt;/p&gt;&#10;&lt;h2 id="幂等-producer-与事务"&gt;幂等 Producer 与事务&#10;&lt;/h2&gt;&#10;&lt;p&gt;Kafka 提供 &lt;strong&gt;幂等 producer&lt;/strong&gt;（&lt;code&gt;enable.idempotence=true&lt;/code&gt;），broker 用 &lt;code&gt;producerId + 序列号&lt;/code&gt; 去重，保证单分区内不重不漏。需要跨分区、跨系统的原子写入时，使用&lt;strong&gt;事务&lt;/strong&gt;（&lt;code&gt;transactional.id&lt;/code&gt;）将多次 produce 与 offset 提交纳入一个事务：&lt;/p&gt;&#10;&lt;div class="td-code td-code--untitled" id="td-code-5a2edc9c-fence-0" data-td-code data-td-code-auto-id&#10; data-td-language="java" data-td-line-count="5"&gt;&#10; &lt;div class="td-code__viewport" id="td-code-5a2edc9c-fence-0-viewport" data-td-code-viewport&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;producer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initTransactions&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;producer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;beginTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;producer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;producer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;producer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commitTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;要么都成功&lt;/span&gt;&lt;span class="err"&gt;，&lt;/span&gt;&lt;span class="n"&gt;要么都不可见&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;h2 id="消费端去重与幂等"&gt;消费端去重与幂等&#10;&lt;/h2&gt;&#10;&lt;p&gt;即使 producer 幂等，consumer 在 rebalance 或位移提交时机不当时仍可能重复消费。消费端应保证&lt;strong&gt;业务幂等&lt;/strong&gt;：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;用唯一键（订单号等）做去重表/唯一索引。&lt;/li&gt;&#10;&lt;li&gt;将「处理 + 提交位移」放在同一事务（如消费写 DB 同时记录 offset）。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="分区顺序性"&gt;分区顺序性&#10;&lt;/h2&gt;&#10;&lt;p&gt;Kafka 只保证&lt;strong&gt;单分区内有序&lt;/strong&gt;。需要全局顺序只能单分区（牺牲并行）；需要业务顺序则按 key（如用户 id）分区，使同一 key 落到同一分区，从而在该 key 维度保持顺序。精确一次（EOS）正是幂等 + 事务 + 消费幂等三者叠加的结果。&lt;/p&gt;</description></item></channel></rss>