<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Append-Only-Log on Hemant Sethi</title>
    <link>https://www.sethihemant.com/tags/append-only-log/</link>
    <description>Recent content in Append-Only-Log on Hemant Sethi</description>
    <generator>Hugo -- 0.146.0</generator>
    <language>en-us</language>
    <lastBuildDate>Wed, 04 Dec 2024 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://www.sethihemant.com/tags/append-only-log/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Kafka</title>
      <link>https://www.sethihemant.com/notes/kafka-2011/</link>
      <pubDate>Wed, 04 Dec 2024 00:00:00 +0000</pubDate>
      <guid>https://www.sethihemant.com/notes/kafka-2011/</guid>
      <description>&lt;p&gt;&lt;strong&gt;Paper:&lt;/strong&gt; &lt;a href=&#34;https://notes.stephenholiday.com/Kafka.pdf&#34;&gt;Kafka&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;kafkadistributed-messaging-system&#34;&gt;Kafka/Distributed Messaging System&lt;/h2&gt;
&lt;h3 id=&#34;goal&#34;&gt;Goal&lt;/h3&gt;
&lt;p&gt;Design a &lt;strong&gt;distributed&lt;/strong&gt; &lt;strong&gt;messaging system&lt;/strong&gt; that can &lt;strong&gt;reliably&lt;/strong&gt; transfer a &lt;strong&gt;high throughput&lt;/strong&gt; of &lt;strong&gt;messages&lt;/strong&gt; between different entities.&lt;/p&gt;
&lt;h3 id=&#34;background&#34;&gt;Background&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;One common challenge in distributed systems is handling &lt;strong&gt;continuous influx of data from multiple sources&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;E.g. Imagine a &lt;strong&gt;log aggregation service&lt;/strong&gt; that can receive hundreds of log entries per second from different sources. Function of this log aggregation service is to store these logs on a disk at a shared server and build an index on top of these logs so that they can be searched later.&lt;/li&gt;
&lt;li&gt;Challenges of this service?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Distributed Messaging Systems&lt;/strong&gt;(or Asynchronous processing paradigm) can help.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;what-is-a-messaging-system&#34;&gt;What is a messaging System?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;System responsible for &lt;strong&gt;transferring data amongst various disparate systems&lt;/strong&gt; like apps, services, processes, servers etc, w/o &lt;strong&gt;introducing additional coupling&lt;/strong&gt; b/w producers and consumers, and by providing &lt;strong&gt;asynchronous&lt;/strong&gt; way of communicating b/w sender and receiver.&lt;/li&gt;
&lt;li&gt;Two types of Messaging Systems&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;queue&#34;&gt;Queue&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;A Particular message can be consumed by one consumer only.&lt;/li&gt;
&lt;li&gt;Once a message is consumed, it&amp;rsquo;s removed from the queue.&lt;/li&gt;
&lt;li&gt;Limits the system as the same messages can’t be read by the multiple consumers.
&lt;img loading=&#34;lazy&#34; src=&#34;https://www.sethihemant.com/images/notes/kafka-2011/image-1.png&#34;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;publish-subscribe-messaging-system&#34;&gt;Publish-Subscribe Messaging System&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;In the Pub-Sub model, messages are written into Partitions/Topics.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>Paper:</strong> <a href="https://notes.stephenholiday.com/Kafka.pdf">Kafka</a></p>
<hr>
<h2 id="kafkadistributed-messaging-system">Kafka/Distributed Messaging System</h2>
<h3 id="goal">Goal</h3>
<p>Design a <strong>distributed</strong> <strong>messaging system</strong> that can <strong>reliably</strong> transfer a <strong>high throughput</strong> of <strong>messages</strong> between different entities.</p>
<h3 id="background">Background</h3>
<ul>
<li>One common challenge in distributed systems is handling <strong>continuous influx of data from multiple sources</strong>.</li>
<li>E.g. Imagine a <strong>log aggregation service</strong> that can receive hundreds of log entries per second from different sources. Function of this log aggregation service is to store these logs on a disk at a shared server and build an index on top of these logs so that they can be searched later.</li>
<li>Challenges of this service?</li>
<li><strong>Distributed Messaging Systems</strong>(or Asynchronous processing paradigm) can help.</li>
</ul>
<h3 id="what-is-a-messaging-system">What is a messaging System?</h3>
<ul>
<li>System responsible for <strong>transferring data amongst various disparate systems</strong> like apps, services, processes, servers etc, w/o <strong>introducing additional coupling</strong> b/w producers and consumers, and by providing <strong>asynchronous</strong> way of communicating b/w sender and receiver.</li>
<li>Two types of Messaging Systems</li>
</ul>
<h3 id="queue">Queue</h3>
<ul>
<li>A Particular message can be consumed by one consumer only.</li>
<li>Once a message is consumed, it&rsquo;s removed from the queue.</li>
<li>Limits the system as the same messages can’t be read by the multiple consumers.
<img loading="lazy" src="/images/notes/kafka-2011/image-1.png"></li>
</ul>
<h3 id="publish-subscribe-messaging-system">Publish-Subscribe Messaging System</h3>
<ul>
<li>
<p>In the Pub-Sub model, messages are written into Partitions/Topics.</p>
</li>
<li>
<p>Producers write the messages to topics that get persisted in the messaging system.</p>
</li>
<li>
<p>Subscribers subscribe to those topics to receive each message that was published.</p>
</li>
<li>
<p>Pub-Sub model allows multiple consumers to read the same message.</p>
</li>
<li>
<p>Messaging system that stores and handles messages is called a Broker.
<img loading="lazy" src="/images/notes/kafka-2011/image-2.png"></p>
</li>
<li>
<p>Provides a loose coupling b/w producers and consumers so they don’t need to be synchronized. They can read and write <strong>messages at different rates</strong>.</p>
</li>
<li>
<p>Also provides <strong>fault-tolerance</strong>. Messages don’t get lost.</p>
</li>
<li>
<p>A messaging system can be deployed for various reasons:</p>
</li>
</ul>
<h3 id="kafka">Kafka</h3>
<h3 id="agenda">Agenda</h3>
<ul>
<li>What is Kafka</li>
<li>Background</li>
<li>Kafka Use Cases</li>
</ul>
<h3 id="what-is-kafka">What is Kafka?</h3>
<ul>
<li>Open source pub-sub messaging system</li>
<li>Can work as a message-queue as well.</li>
<li>Distributed, Fault tolerant, highly scalable by design.</li>
<li>Fundamentally a system that takes streams of messages from producers, store reliably on a central cluster(with a set of brokers), and allows those messages to be delivered to consumers.
<img loading="lazy" src="/images/notes/kafka-2011/image-3.png"></li>
</ul>
<h3 id="background-1">Background</h3>
<ul>
<li>
<p>Created at LinkedIn in 2010 to track <strong>Page Views(events)</strong>, <strong>Messages</strong> from Messaging Systems, and <strong>Logs</strong> from Various services.</p>
</li>
<li>
<p>Kafka is also known as a <strong>Distributed Commit log or Write Ahead Log or a Transaction Log.</strong></p>
</li>
<li>
<p><strong>Commit Log</strong> is an append-only data structure that can persistently store a sequence of records.</p>
</li>
<li>
<p>Records are always appended to the end of the log, and once added, records cannot be deleted or modified. Reading from a commit log always happens from left to right (or old to new).
<img loading="lazy" src="/images/notes/kafka-2011/image-4.png"></p>
</li>
<li>
<p>Stores all messages on disk and reads and writes take advantage of sequential disk reads/writes.</p>
</li>
</ul>
<h3 id="kafka-use-cases">Kafka Use Cases</h3>
<ul>
<li>Can be used for collecting huge amounts(Big Data) events and do real-time stream processing of those events.</li>
<li><strong>Metrics:</strong> Can collect and aggregate monitoring data. Different services can write their metrics which can be later pulled from Kafka to produce aggregate statistics.</li>
<li><strong>Log Aggregation:</strong> Collect logs from various sources, and make them available in standard format to multiple consumers.</li>
<li><strong>Stream Processing:</strong> Cases where data undergoes transformation after reading. E.g. Raw data consumed from the topic is transformed, enriched, aggregated, and pushed to a new topic for further consumption. Sort of creating a derived view of data from the source of record data.</li>
<li><strong>Commit Log:</strong> Can be used as an external commit log for distributed systems which can keep track of their states.</li>
<li><strong>Website Activity Tracking:</strong> One of the original use cases was to build a User-Activity tracking pipeline. Like Page clicks searches, are published to separate topics. These topics are made available for later processing like Loading data into Hadoop(for Batch Processing), Data Warehousing systems for Analytics or reporting. Can also be fed into <strong>Product Suggestion or Recommendations systems</strong> which can power, Similar Products that you may like, or people have bought etc.</li>
</ul>
<h3 id="high-level-architecture">High Level Architecture</h3>
<h3 id="agenda-1">Agenda</h3>
<ul>
<li>Kafka Common Terms</li>
<li>High-Level Architecture</li>
</ul>
<h3 id="kafka-common-terms">Kafka Common Terms</h3>
<ul>
<li>
<p><strong>Brokers</strong></p>
</li>
<li>
<p><strong>Records</strong>
<img loading="lazy" src="/images/notes/kafka-2011/image-5.png"></p>
</li>
<li>
<p><strong>Topics</strong>
<img loading="lazy" src="/images/notes/kafka-2011/image-6.png"></p>
</li>
<li>
<p><strong>Producers</strong></p>
</li>
<li>
<p><strong>Consumers</strong></p>
</li>
<li>
<p>In Kafka, producers and consumers are fully decoupled and agnostic of each other, which is a key design element to achieve the high scalability that Kafka is known for. For example, producers never need to wait for consumers.</p>
</li>
</ul>
<h3 id="high-level-architecture-1">High Level Architecture</h3>
<h3 id="kafka-cluster">Kafka Cluster</h3>
<ul>
<li>Kafka is run as a cluster of one or more servers, where each server is responsible for running one Kafka broker.</li>
</ul>
<h3 id="zookeeper">ZooKeeper</h3>
<ul>
<li><strong>ZooKeeper</strong> is a <strong>highly read optimized</strong> <strong>distributed key-value store</strong> and is used for coordination and storing configurations.</li>
<li>In Original Version of Kafka, Kafka had used Zookeeper to coordinate between Kafka brokers; ZooKeeper maintains metadata information about the Kafka cluster
<img loading="lazy" src="/images/notes/kafka-2011/image-7.png"></li>
</ul>
<h3 id="kafka-deep-dive">Kafka Deep Dive</h3>
<p>Related Notes: Alex XU II</p>
<h3 id="agenda-2">Agenda</h3>
<ul>
<li>Topic Partitions</li>
<li>High-Water Mark
Kafka is simply a collection of topics. As topics can get quite big, they are split into partitions of a smaller size for better performance and scalability.</li>
</ul>
<h3 id="topic-partitions">Topic Partitions</h3>
<ul>
<li>
<p>Kafka Topics are partitioned, and these partitions are placed on separate nodes/brokers.</p>
</li>
<li>
<p>When a new message is published to a topic, it gets appended to one of the topic’s partitions, usually decided by using the Customer specified Partition Key.</p>
</li>
<li>
<p>A <strong>partition</strong> is an ordered sequence of messages.</p>
</li>
<li>
<p>Kafka Guarantees <strong>FIFO Ordering</strong> between messages of a single partition. No ordering guarantees across partitions or at a topic level.
<img loading="lazy" src="/images/notes/kafka-2011/image-8.png"></p>
</li>
<li>
<p>A Unique Sequence ID called a <strong>Partition Offset</strong> gets assigned to every message added to a partition. Used to identify a message’s sequential position within a partition.</p>
</li>
<li>
<p>Offset sequences are unique to a single partition. Messages are uniquely located using <strong>(Topic, Partition, Offset)</strong>.</p>
</li>
<li>
<p>Producers can choose to publish messages to any partition. If Ordering within a partition is not needed, a <strong>Round-Robin strategy</strong> can be used for evenly partitioning data across nodes.</p>
</li>
<li>
<p>Placing partitions on separate brokers allows for multiple consumers to read from a topic in a parallel, i.e. Different consumers can concurrently read different partitions on separate brokers. However, for multiple consumers within the same Consumer Group, only 1 consumer from a consumer Group can read the data from a Partition at any time.</p>
</li>
<li>
<p>Messages once written to a partition are immutable(Append Only Log).</p>
</li>
<li>
<p>Producer specifies a <strong>Partition Key</strong>, to any message that it publishes so that data is written to the same partition.</p>
</li>
<li>
<p>Each broker can manage a set of partitions from across various topics.
<img loading="lazy" src="/images/notes/kafka-2011/image-9.png"></p>
</li>
<li>
<p>Follows the principle of <strong>Dumb Broker</strong> and <strong>Smart Consumer</strong>.</p>
</li>
<li>
<p>Kafka doesn’t keep a record of what records are read by the consumer. Consumers poll kafka for new messages and specify which records(specified by partition Offset) they want to read from the topic.</p>
</li>
<li>
<p>Consumers are allowed to increment/decrement the offset to replay and reprocess the messages.</p>
</li>
<li>
<p>Each Topic partition has one leader broker and multiple replica(followers) brokers.</p>
</li>
</ul>
<h3 id="leaders-and-followers">Leaders and Followers</h3>
<ul>
<li>A <strong>leader</strong> is the node responsible for all reads and writes for the given partition. Every partition has one Kafka broker acting as a leader.</li>
<li>To handle Single Point of Failure and to enable Fault Tolerance, Kafka replicates partitions and distributes them across multiple brokers.</li>
<li>Each follower’s responsibility is to replicate the leader&rsquo;s data to serve as a backup partition.</li>
<li>A follower can take over the leadership if the leader of a partition goes down.</li>
<li>Kafka stores the location of the leader of each partition in ZooKeeper</li>
<li>As all writes/reads happen at/from the leader, producers and consumers directly talk to ZooKeeper to find a partition leader.
<img loading="lazy" src="/images/notes/kafka-2011/image-10.png"></li>
</ul>
<h3 id="in-sync-replicasisr">In Sync Replicas(ISR)</h3>
<ul>
<li>An in-sync replica (ISR) is a broker that has the latest data for a given partition.</li>
<li>A follower is an in-sync replica only if it has fully caught up to the partition it is following.</li>
<li><strong>Only ISRs are eligible to become partition leaders.</strong></li>
<li>Kafka can choose the minimum number of ISRs required before the data becomes available for consumers to read.</li>
</ul>
<h3 id="high-water-mark">High Water Mark</h3>
<ul>
<li>To ensure data consistency, the leader broker never returns (or exposes) messages which have not been replicated to a minimum set of ISRs.</li>
<li>Broker uses High Water Mark which is the <strong>highest offset that all ISRs of a particular partition share</strong>.</li>
<li>The leader exposes data only up to the high-water mark offset and propagates the high-water mark offset to all followers.</li>
<li>This avoids the case of a <strong>Non-Repeatable read</strong> in case the Leader crashes before Replicas get the latest messages.
<img loading="lazy" src="/images/notes/kafka-2011/image-11.png"></li>
</ul>
<h3 id="consumer-groups">Consumer Groups</h3>
<h3 id="agenda-3">Agenda</h3>
<ul>
<li>What is a Consumer Group?</li>
<li>Distributing Partitions to a consumer within Consumer Groups.</li>
</ul>
<h3 id="what-is-a-consumer-group">What is a Consumer Group?</h3>
<ul>
<li>A consumer group is basically a set of one or more consumers working together in parallel to consume messages from topic partitions.</li>
<li>No two consumers within the same Consumer group can attach to the same partition at a time. Thus no two consumers within CG receive the same message.</li>
</ul>
<h3 id="distributing-partitions-to-a-consumer-within-consumer-groups">Distributing Partitions to a consumer within Consumer Groups.</h3>
<ul>
<li>
<p>Kafka ensures that only a single consumer reads messages from any partition within a consumer group</p>
</li>
<li>
<p>Topic partitions are a unit of parallelism</p>
</li>
<li>
<p>If a consumer stops, Kafka spreads partitions across the remaining consumers in the same consumer group</p>
</li>
<li>
<p>Every time a consumer is added to or removed from a group, the consumption is rebalanced within the group.
<img loading="lazy" src="/images/notes/kafka-2011/image-12.png"></p>
</li>
<li>
<p>Parallelizing processing across multiple partitions of a topic, helps support very high Throughput.</p>
</li>
<li>
<p>Kafka stores the current offset per consumer group per topic per partition? <strong>What? Initially we said Kafka is DUMB and that Consumer tracks the offset? [Research]</strong></p>
</li>
<li>
<p>Kafka uses any unused consumers as failovers when there are more consumers than partitions. Extra Consumers are idle in the meantime.</p>
</li>
<li>
<p>Rebalancing happens as Consumers are added and removed from the ConsumerGroups.</p>
</li>
</ul>
<h3 id="kafka-workflow">Kafka Workflow</h3>
<h3 id="agenda-4">Agenda</h3>
<ul>
<li>Kafka Workflow as Pub-Sub messaging</li>
<li>Kafka Workflow for Consumer Group</li>
<li>Kafka provides both pub-sub and queue-based messaging systems in a fast, reliable, persisted, fault-tolerance, and zero downtime manner.</li>
<li>In both cases, producers simply send the message to a topic, and consumers can choose any one type of messaging system depending on their need</li>
</ul>
<h3 id="kafka-workflow-as-pub-sub-messaging">Kafka Workflow as Pub-Sub Messaging</h3>
<ul>
<li>Producer publishes a message to a topic.</li>
<li>Broker stores messages in the partitions configured for that topic. If no partition keys were specified, Broker spreads the messages evenly across partitions.</li>
<li>Consumer subscribes to a specific Topic. Broker provides the current offset of that Topic back to Consumer and saves that Offset to ZooKeeper.</li>
<li>Consumers will request Brokers at regular intervals for new messages and process it once kafka sends those messages.</li>
<li>Once the consumer processes the message, it sends an acknowledgement back to the broker. Broker Updates the processed offsets in the ZooKeeper.</li>
<li>Consumers can rewind/skip to the desired offset and read subsequent messages.</li>
</ul>
<h3 id="role-of-zookeeper">Role of Zookeeper</h3>
<h3 id="agenda-5">Agenda</h3>
<ul>
<li>What is ZooKeeper?</li>
<li>ZooKeeper as Central Coordinator.</li>
</ul>
<h3 id="what-is-zookeeper">What is ZooKeeper?</h3>
<ul>
<li>Distributed configuration and synchronization service.</li>
<li>Serves as the coordination interface between the Kafka brokers, producers, and consumers.</li>
<li>Kafka stores basic metadata in ZooKeeper, such as information about brokers, topics, partitions, partition leader/followers, consumer offsets.
<img loading="lazy" src="/images/notes/kafka-2011/image-13.png"></li>
</ul>
<h3 id="zookeeper-as-the-central-coordinatormight-be-stale-info">ZooKeeper as the central coordinator(Might be Stale info)</h3>
<ul>
<li>Kafka brokers are stateless; they rely on ZooKeeper to maintain and coordinate brokers, such as notifying consumers and producers of the arrival of a new broker or failure of an existing broker, as well as routing all requests to partition leaders.</li>
<li>Stores all sorts of Metadata about the Kafka Cluster</li>
</ul>
<h3 id="how-do-producers-or-consumers-find-out-who-the-leader-of-a-partition-is">How do producers or consumers find out who the leader of a partition is?</h3>
<ul>
<li>
<p>In the older versions of Kafka, all clients (i.e., producers and consumers) used to <strong>directly talk to ZooKeeper</strong> to find the partition leader.</p>
</li>
<li>
<p>Kafka has moved away from this coupling, and in Kafka’s latest releases, <strong>clients fetch metadata information from Kafka brokers directly</strong>;
<img loading="lazy" src="/images/notes/kafka-2011/image-14.png"></p>
</li>
<li>
<p>All the critical information is stored in the ZooKeeper and ZooKeeper replicates this data across its cluster, therefore, failure of Kafka broker (or ZooKeeper itself) does not affect the state of the Kafka cluster.</p>
</li>
<li>
<p>Zookeeper is also responsible for <strong>coordinating the partition leader election</strong> between the Kafka brokers in case of leader failure.</p>
</li>
</ul>
<h3 id="controller-broker">Controller Broker</h3>
<h3 id="agenda-6">Agenda</h3>
<ul>
<li>What is a Controller Broker?</li>
<li>Split Brain.</li>
<li>Generation Clock.</li>
</ul>
<h3 id="what-is-a-controller-broker">What is a Controller Broker?</h3>
<ul>
<li>Within the Kafka cluster, one broker is elected as the Controller.</li>
<li>Controller broker is responsible for admin operations, such as creating/deleting a topic, adding partitions, assigning leaders to partitions, monitoring broker failures by doing health checks on other brokers.</li>
<li>Communicates the result of the partition leader election to other brokers in the system.</li>
</ul>
<h3 id="split-brain">Split Brain</h3>
<ul>
<li>When a controller node dies, kafka elects a new controller. One of the problems is that we cannot truly know if the leader has stopped for good(Crash Stop) or has experienced intermittent failures like Stop the World GC or process Pause, or a temporary network disruption.</li>
<li>Two split-brain controllers would be giving out conflicting commands in parallel. If something like this happens in a cluster, it can result in major inconsistencies. How do we handle this?</li>
</ul>
<h3 id="generation-clock">Generation Clock?</h3>
<ul>
<li>Split-brain is commonly solved with a generation clock, which is simply a monotonically increasing number to indicate a server’s generation.</li>
<li>In Kafka, the generation clock is implemented through an epoch number, Old leader = epoch 1, and new leader = epoch 2.</li>
<li>This epoch is included in every request that is sent from the Controller to other brokers.</li>
<li>Brokers can now easily differentiate the real Controller by simply trusting the Controller with the highest number.</li>
<li>This epoch number is stored in ZooKeeper.</li>
</ul>
<h3 id="kafka-delivery-semantics">Kafka Delivery Semantics?</h3>
<h3 id="agenda-7">Agenda</h3>
<ul>
<li>Producer Delivery Semantics</li>
<li>Consumer Delivery Semantics</li>
</ul>
<h3 id="producer-delivery-semantics">Producer Delivery Semantics</h3>
<ul>
<li>A producer writes only to the leader broker, and the followers asynchronously replicate the data.</li>
<li>How can a producer know that the data is successfully stored at the leader or that the followers are keeping up with the leader?</li>
<li>Kafka offers <strong>three options</strong> to denote the number of brokers that must receive the record before the producer considers the write as successful:</li>
</ul>
<h3 id="consumer-delivery-semantics">Consumer Delivery Semantics</h3>
<ul>
<li>A consumer can read only those messages that have been written to a set of in-sync replicas(<strong>High Water Mark</strong>).</li>
<li>There are three ways of providing consistency to the consumer:</li>
</ul>
<h3 id="kafka-characteristics">Kafka Characteristics</h3>
<h3 id="agenda-8">Agenda</h3>
<ul>
<li>Storing messages to disks</li>
<li>Record Retention in Kafka</li>
<li>Client Quota</li>
<li>Kafka Performance</li>
</ul>
<h3 id="storing-messages-to-disks">Storing messages to disks</h3>
<ul>
<li>Kafka writes its messages to the local disk and does not keep anything in RAM. Disk storage is important for durability so that the messages will not disappear if the system dies and restarts.</li>
<li>Even though disk access is generally considered to be slow, there is a huge performance difference b/w Random Block Access and Sequential Access.</li>
<li>Random block access is slower because of numerous disk seeks, whereas the sequential nature of writing or reading, enables disk operations to be thousands of times faster than random access.</li>
<li>Because all writes and reads happen sequentially, <strong>Kafka has a very high throughput</strong>.</li>
<li>Writing or reading sequentially from disks are <strong>heavily optimized</strong> by the OS, via <strong>read-ahead</strong> (prefetch large block multiples) and <strong>write-behind</strong> (group small logical writes into big physical writes) techniques.</li>
<li>Also, modern operating systems cache the disk in free RAM. This is called Pagecache.</li>
<li>Since Kafka stores messages in a standardized binary format unmodified throughout the whole flow (producer → broker → consumer), it can make use of the zero-copy optimization.</li>
<li>Kafka has a protocol that groups messages together. This allows network requests to group messages together and reduces network overhead.</li>
</ul>
<h3 id="record-retention-in-kafka">Record Retention in Kafka</h3>
<ul>
<li>By default, Kafka retains records until it runs out of disk space. We can set time-based limits (configurable retention period), size-based limits (configurable based on size), or compaction (keeps the latest version of record using the key).</li>
<li>For example, we can set a retention policy of three days, or two weeks, or a month, etc.</li>
<li>The records in the topic are available for consumption until discarded by time, size, or compaction.</li>
</ul>
<h3 id="client-quota">Client Quota</h3>
<ul>
<li>Heavy Hitters(Noisy Neighbours) can exhaust broker resources, or can cause network saturation to multi-tenant kafka clusters, which can deny service to other clients and broker themselves.</li>
<li>In Kafka, quotas are <strong>byte-rate</strong> thresholds defined per <strong>client-ID(application).</strong></li>
<li>The broker does not return an error when a client exceeds its quota but instead attempts to slow the client down by holding the client’s response for enough time to keep the client under the quota.</li>
<li>This also prevents clients from having to implement special back-off and retry behavior.</li>
</ul>
<h3 id="kafka-performance">Kafka Performance</h3>
<ul>
<li>Scalability</li>
<li>Fault Tolerance and Reliability</li>
<li>Throughput</li>
<li>Low Latency?</li>
</ul>
<h3 id="system-design-pattern">System Design Pattern:</h3>
<ul>
<li>
<p><strong>High Water Mark</strong> - To deal with Non-Repeatable reads and data consistency.</p>
</li>
<li>
<p><strong>Leader and Follower</strong> - Leader serves read/writes. Followers do replication.</p>
</li>
<li>
<p><strong>Split-Brain</strong> - Multiple Controller nodes active at a time(due to Zombie Controller). Generational Epoch number to resolve.</p>
</li>
<li>
<p><strong>Segmented Log</strong> - Log segmentation to implement storage for its partitions.
<strong>References:</strong></p>
</li>
<li>
<p>Confluent Docs</p>
</li>
<li>
<p>NYTimes usecase</p>
</li>
<li>
<p>Kafka Summit 2019</p>
</li>
<li>
<p>Kafka Acks explained(TODO)</p>
</li>
<li>
<p>Kafka as distributed log</p>
</li>
<li>
<p>Minimizing Kafka Latency(TODO)</p>
</li>
<li>
<p>Kafka Internal Storage(TODO)</p>
</li>
<li>
<p>Exactly once semantics(TODO)</p>
</li>
<li>
<p>Split Brain(TODO)
<strong>Open Questions:</strong></p>
</li>
<li>
<p>Kafka stores the current offset per consumer group per topic per partition? <strong>What? Initially we said Kafka is DUMB and that Consumer tracks the offset? [Research]</strong></p>
</li>
<li>
<p>In At-most-once consumer delivery semantics, Why can’t the consumer read from the previous offset? Why are messages said to be lost?[Research]</p>
</li>
<li>
<p>Exactly once semantics? How would transactions happen across 2 systems(consumer processing + Kafka Offset Commit). How are they suggesting the transaction would be rolled back?</p>
</li>
<li>
<p>Zero Copy Optimization</p>
</li>
<li>
<p>Page Cache optimization Kafka</p>
</li>
<li>
<p>How does replication internal work b/w leader follower?</p>
</li>
<li>
<p>Tombstoning in Kafka.</p>
</li>
</ul>
<h2 id="1-zero-copy-optimizations--page-cache-in-kafka-and-other-systems"><strong>1️⃣ Zero Copy Optimizations &amp; Page Cache in Kafka and Other Systems</strong></h2>
<h3 id="-what-is-zero-copy"><strong>📌 What is Zero Copy?</strong></h3>
<p>Zero Copy is a <strong>kernel-level optimization</strong> that allows data to be transferred between disk and network <strong>without passing through user-space memory</strong>, <strong>reducing CPU overhead and increasing throughput</strong>.</p>
<p>🚀 <strong>Why is Zero Copy important?</strong> ✔ <strong>Reduces CPU usage</strong> (since data isn’t copied multiple times).</p>
<p>✔ <strong>Minimizes context switches</strong> (between user and kernel space).</p>
<p>✔ <strong>Improves I/O throughput</strong> (as memory copying is avoided).</p>
<h3 id="-how-kafka-uses-zero-copy-sendfile-optimization"><strong>📌 How Kafka Uses Zero Copy (Sendfile Optimization)</strong></h3>
<p>Kafka uses <strong>Zero Copy via the sendfile system call</strong> in Linux.</p>
<p>🔹 <strong>Without Zero Copy (Traditional Path)</strong></p>
<ol>
<li>
<p>Kafka reads a log file from disk → <strong>(Disk → Kernel Space).</strong></p>
</li>
<li>
<p>The kernel copies data to Kafka’s user-space buffer → <strong>(Kernel Space → User Space).</strong></p>
</li>
<li>
<p>Kafka writes the buffer to a network socket → <strong>(User Space → Kernel Space → Network).</strong></p>
</li>
<li>
<p>The kernel sends data over the network.
🔹 <strong>With Zero Copy (Optimized Path)</strong></p>
</li>
<li>
<p>Kafka calls sendfile() → <strong>Kernel directly transfers a log file to the network socket</strong>.</p>
</li>
<li>
<p><strong>No user-space buffer required</strong> → Data goes <strong>directly from disk to network</strong>.
✔ <strong>Avoids unnecessary copies in user-space.</strong>✔ <strong>Greatly improves throughput</strong> (Kafka can achieve <strong>millions of messages per second</strong>).</p>
</li>
</ol>
<h3 id="-zero-copy-optimizations-in-other-systems"><strong>📌 Zero Copy Optimizations in Other Systems</strong></h3>
<p><em>[Table content - requires manual formatting]</em></p>
<h3 id="-what-is-page-cache-and-how-kafka-optimizes-it"><strong>📌 What is Page Cache and How Kafka Optimizes It?</strong></h3>
<p>Kafka <strong>doesn’t need a traditional database cache</strong>. Instead, it relies on the <strong>OS page cache</strong> for fast reads.</p>
<p>✔ <strong>Page Cache:</strong> The Linux kernel automatically caches recently read disk pages in memory.</p>
<p>✔ <strong>Kafka uses the Page Cache to serve reads directly from memory without hitting disk.</strong></p>
<p>🔹 <strong>How Page Cache Works in Kafka:</strong></p>
<ol>
<li>When a consumer reads a message, Kafka <strong>first checks the OS page cache</strong>.</li>
<li>If the data is cached, it is served <strong>directly from memory</strong> (zero disk I/O).</li>
<li>If the data isn’t in cache, Kafka reads it from disk, and the OS automatically caches it.
🚀 <strong>Optimizations in Kafka:</strong> ✔ <strong>Uses sendfile() to directly transfer from Page Cache to network.</strong>✔ <strong>Leverages sequential disk access (append-only logs) for high read efficiency.</strong>✔ <strong>Minimizes JVM heap memory usage by relying on OS caching.</strong></li>
</ol>
<h2 id="2-how-replication-works-between-leaders-and-followers-in-kafka"><strong>2️⃣ How Replication Works Between Leaders and Followers in Kafka</strong></h2>
<p>Kafka ensures <strong>fault tolerance</strong> and <strong>high availability</strong> using <strong>replication</strong>.</p>
<h3 id="-basics-of-kafka-replication"><strong>📌 Basics of Kafka Replication</strong></h3>
<p>✔ Each <strong>Kafka topic is partitioned</strong>, and each partition has:</p>
<ul>
<li><strong>One Leader</strong> (handles all reads &amp; writes).</li>
<li><strong>One or more Followers</strong> (replicas of the leader’s data).</li>
</ul>
<h3 id="-steps-in-kafka-replication"><strong>📌 Steps in Kafka Replication</strong></h3>
<p>1️⃣ <strong>Producer writes data to the Leader Partition</strong>.</p>
<p>2️⃣ <strong>Leader appends data to its local log segment</strong>.</p>
<p>3️⃣ <strong>Followers fetch new data from the leader</strong>.</p>
<p>4️⃣ <strong>Followers append data to their own log segment</strong>.</p>
<p>5️⃣ **Followers send an acknowledgment (ACK) once they persist the data.**6️⃣ <strong>If a majority of followers acknowledge, Kafka considers the message committed</strong>.</p>
<h3 id="-leader-and-follower-sync-mechanism"><strong>📌 Leader and Follower Sync Mechanism</strong></h3>
<p>✔ <strong>Kafka uses a pull-based replication model</strong> → Followers <strong>poll</strong> the leader to fetch new data.</p>
<p>✔ <strong>Offset tracking:</strong> Followers maintain an <strong>offset</strong> to track the latest committed message.</p>
<p>✔ <strong>ISR (In-Sync Replicas):</strong> Only replicas in sync with the leader are part of the ISR.</p>
<h3 id="-how-a-new-leader-is-elected"><strong>📌 How a New Leader is Elected?</strong></h3>
<p>✔ If the Leader fails, <strong>one of the ISR replicas is promoted</strong>.</p>
<p>✔ The new Leader <strong>starts serving read and write requests</strong>.</p>
<p>✔ If no ISR exists, the partition becomes <strong>temporarily unavailable</strong> until a new Leader is available.</p>
<h3 id="-replication-strategies"><strong>📌 Replication Strategies</strong></h3>
<p><em>[Table content - requires manual formatting]</em></p>
<p>🚀 <strong>Tuning Replication Settings for Performance</strong> ✔ <strong>min.insync.replicas = 2</strong> → Ensures durability (at least two replicas must ACK).</p>
<p>✔ <strong>unclean.leader.election = false</strong> → Prevents unsafe leader elections (data loss risk).</p>
<p>✔ <strong>replica.lag.time.max.ms = 10,000</strong> → Defines when a slow follower is removed from ISR.</p>
<h2 id="3-tombstoning-in-kafka"><strong>3️⃣ Tombstoning in Kafka</strong></h2>
<p>Kafka <strong>Tombstoning</strong> is used for <strong>deleting records in log-compacted topics</strong>.</p>
<h3 id="-why-is-tombstoning-needed"><strong>📌 Why is Tombstoning Needed?</strong></h3>
<p>✔ Kafka <strong>never deletes data immediately</strong>.</p>
<p>✔ Instead, Kafka <strong>marks the record as deleted (tombstone message)</strong>.</p>
<p>✔ The actual data is <strong>removed later during log compaction</strong>.</p>
<h3 id="-how-tombstoning-works"><strong>📌 How Tombstoning Works</strong></h3>
<ol>
<li>Producer sends a <strong>null value for a key</strong> (marks it as deleted).</li>
<li>Kafka appends this <strong>tombstone message</strong> to the log.</li>
<li>The <strong>consumer sees the tombstone event</strong> and removes the record from its own storage.</li>
<li>Kafka’s <strong>log compaction</strong> eventually purges the tombstone message and the original record.</li>
</ol>
<h3 id="-example-of-tombstone-message"><strong>📌 Example of Tombstone Message</strong></h3>
<p>{</p>
<p>&ldquo;key&rdquo;: &ldquo;user_123&rdquo;,</p>
<p>&ldquo;value&rdquo;: null,</p>
<p>&ldquo;timestamp&rdquo;: 1700000000</p>
<p>}</p>
<hr>
<p>✔ This <strong>soft deletes</strong> &ldquo;user_123&rdquo;.</p>
<p>✔ <strong>Log compaction</strong> later removes both the <strong>original record and the tombstone</strong>.</p>
<h3 id="-how-log-compaction-works"><strong>📌 How Log Compaction Works</strong></h3>
<ul>
<li><strong>Log compaction keeps only the latest value for each key.</strong></li>
<li><strong>Tombstones stay in the log until Kafka compacts the segment.</strong></li>
<li><strong>Kafka guarantees at least one copy of the latest record is retained</strong> (even after compaction).
🚀 <strong>Tuning Log Compaction</strong> ✔ <strong>log.cleanup.policy = compact</strong> → Enables log compaction.</li>
</ul>
<p>✔ <strong>delete.retention.ms = 86400000</strong> → Keeps tombstones for 24 hours before purging.</p>
<p>✔ <strong>log.segment.bytes</strong> → Defines when segments are compacted.</p>
<h2 id="-summary--key-takeaways"><strong>🔹 Summary &amp; Key Takeaways</strong></h2>
<h3 id="zero-copy--page-cache"><strong>Zero Copy &amp; Page Cache</strong></h3>
<p>✔ <strong>Kafka uses sendfile() for Zero Copy, avoiding unnecessary memory copies.</strong>✔ <strong>Page Cache stores recent messages, reducing disk I/O.</strong></p>
<h3 id="replication-between-leaders-and-followers"><strong>Replication Between Leaders and Followers</strong></h3>
<p>✔ <strong>Kafka uses asynchronous, pull-based replication for performance.</strong>✔ <strong>ISR (In-Sync Replicas) ensures durability.</strong>✔ <strong>New leaders are elected from ISR in case of failure.</strong></p>
<h3 id="tombstoning--log-compaction"><strong>Tombstoning &amp; Log Compaction</strong></h3>
<p>✔ <strong>Kafka uses tombstones (null values) for soft deletes.</strong>✔ <strong>Log compaction removes older records but keeps the latest one per key.</strong></p>
<hr>
<p><strong>Paper Link:</strong> <a href="https://notes.stephenholiday.com/Kafka.pdf">https://notes.stephenholiday.com/Kafka.pdf</a></p>
<hr>
<p><em>Last updated: March 15, 2026</em></p>
<p><em>Questions or discussion? <a href="mailto:sethi.hemant@gmail.com">Email me</a></em></p>
]]></content:encoded>
    </item>
  </channel>
</rss>
