<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Posts on Umit Unal</title><link>https://umitunal.net/posts/</link><description>Recent content in Posts on Umit Unal</description><generator>Hugo</generator><language>en-us</language><copyright>© 2020 Umit Unal.</copyright><lastBuildDate>Tue, 03 Feb 2026 10:00:00 +0300</lastBuildDate><atom:link href="https://umitunal.net/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>PetraCache: Building a Memcached-Compatible Cache with RocksDB</title><link>https://umitunal.net/2026/02/petracache-building-a-memcached-compatible-cache-with-rocksdb/</link><pubDate>Tue, 03 Feb 2026 10:00:00 +0300</pubDate><guid>https://umitunal.net/2026/02/petracache-building-a-memcached-compatible-cache-with-rocksdb/</guid><description>&lt;h2 id="the-problem"&gt;The Problem&lt;/h2&gt;
&lt;p&gt;Memcached is fast. Really fast. But when it restarts, your cache is gone. Cold cache means every request hits your database until the cache warms up again. At scale, this can take down your entire system.&lt;/p&gt;
&lt;p&gt;I wanted to explore a different approach: &lt;strong&gt;what if we could add persistence to memcached without changing the protocol?&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="why-memcached-protocol"&gt;Why memcached Protocol?&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/facebook/mcrouter"&gt;mcrouter&lt;/a&gt; is Meta&amp;rsquo;s memcached router—5 billion requests per second in production. Consistent hashing, failover, replication, connection pooling. All battle-tested at massive scale.&lt;/p&gt;</description></item><item><title>Consistent Hashing Algorithms: Jump Hash vs Ring Hash vs Rendezvous Hash</title><link>https://umitunal.net/2025/09/consistent-hashing-algorithms-jump-hash-vs-ring-hash-vs-rendezvous-hash/</link><pubDate>Wed, 17 Sep 2025 14:30:00 +0300</pubDate><guid>https://umitunal.net/2025/09/consistent-hashing-algorithms-jump-hash-vs-ring-hash-vs-rendezvous-hash/</guid><description>&lt;p&gt;Whether you&amp;rsquo;re building a database, cache, load balancer, or content delivery network, you face the same fundamental challenge: distributing workload across multiple machines. Poor distribution leads to unreliable and slow systems. Optimal distribution enables scalability. The question is: how?&lt;/p&gt;
&lt;p&gt;Your e-commerce platform started with one database but now handles 100 million users across 50 database shards. Every user profile, order history, and product review must be stored in exactly the right shard for fast queries. When user &amp;ldquo;john_doe_12345&amp;rdquo; places an order, which of your 50 shards should store it? Route it wrong and you&amp;rsquo;ll query all shards (slow). Route it right and you get instant lookups. You add new shards monthly during planned maintenance, and replace failed ones immediately with identical replicas.&lt;/p&gt;</description></item><item><title>Distributed System Implementations: Building Key-Value Stores</title><link>https://umitunal.net/2025/04/distributed-system-implementations-building-key-value-stores/</link><pubDate>Fri, 25 Apr 2025 14:09:07 +0300</pubDate><guid>https://umitunal.net/2025/04/distributed-system-implementations-building-key-value-stores/</guid><description>&lt;p&gt;Many modern applications need to be fast, scalable, and always available. To achieve this, they often use &lt;strong&gt;distributed systems&lt;/strong&gt;. These systems run on many computers and work together to store and process data.&lt;/p&gt;
&lt;p&gt;One important type of distributed system is the &lt;strong&gt;key-value store&lt;/strong&gt;. It saves data as key-value pairs. This model is simple but very powerful. Many popular tools—like databases, caches, and service discovery systems—use this structure.&lt;/p&gt;
&lt;p&gt;However, building a key-value store that works across multiple machines is not easy. We need to think about problems like:&lt;/p&gt;</description></item><item><title>Using RoaringBitmap in Distributed Data Systems</title><link>https://umitunal.net/2024/12/using-roaringbitmap-in-distributed-data-systems/</link><pubDate>Sun, 22 Dec 2024 14:09:07 +0300</pubDate><guid>https://umitunal.net/2024/12/using-roaringbitmap-in-distributed-data-systems/</guid><description>&lt;p&gt;In modern high-traffic or data-intensive applications, &lt;strong&gt;distributed data systems&lt;/strong&gt; are crucial for handling large volumes of information. But when we deal with &lt;strong&gt;huge sets of integer IDs&lt;/strong&gt;—such as user IDs, IP addresses, or event indices—we need a data structure that is not only &lt;strong&gt;memory-efficient&lt;/strong&gt; but also supports &lt;strong&gt;fast set operations&lt;/strong&gt;. This is where &lt;strong&gt;RoaringBitmap&lt;/strong&gt; comes in.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://roaringbitmap.org/"&gt;&lt;strong&gt;RoaringBitmap&lt;/strong&gt;&lt;/a&gt; stores large sets of integer values in a compressed format and offers rapid operations like intersection, union, and difference. This blog will explore how RoaringBitmap can make distributed data systems more efficient and easier to manage.&lt;/p&gt;</description></item><item><title>eBPF Powers Next-Generation Observability: Maximum Insight, Minimal Impact</title><link>https://umitunal.net/2024/12/ebpf-powers-next-generation-observability-maximum-insight-minimal-impact/</link><pubDate>Sun, 01 Dec 2024 14:09:07 +0300</pubDate><guid>https://umitunal.net/2024/12/ebpf-powers-next-generation-observability-maximum-insight-minimal-impact/</guid><description>&lt;p&gt;In the era of modern software systems, observability has become a critical aspect of system management. It enables engineers to monitor, debug, and optimize their applications effectively. However, traditional observability tools often come with high resource costs, limited visibility, and performance overhead. This is where &lt;strong&gt;eBPF (extended Berkeley Packet Filter)&lt;/strong&gt; steps in to revolutionize observability solutions.&lt;/p&gt;
&lt;p&gt;eBPF is a cutting-edge technology that empowers developers to collect detailed insights about system behavior directly from the Linux kernel, all while keeping resource usage to a minimum. It offers a flexible, efficient, and secure way to understand what’s happening inside your systems, without significantly affecting performance.&lt;/p&gt;</description></item><item><title>Advanced Concepts in LSM Trees: Scaling Write-Optimized Storage</title><link>https://umitunal.net/2024/11/advanced-concepts-in-lsm-trees-scaling-write-optimized-storage/</link><pubDate>Fri, 01 Nov 2024 14:09:07 +0300</pubDate><guid>https://umitunal.net/2024/11/advanced-concepts-in-lsm-trees-scaling-write-optimized-storage/</guid><description>&lt;p&gt;Handling massive volumes of data writes in distributed environments requires data structures built to minimize I/O, balance loads, and retain data integrity. Log-Structured Merge Trees (LSM Trees) accomplish this by intelligently managing writes, compactions, and reads across hierarchical storage levels. This guide will dissect the internal mechanics of LSM Trees, from write batching and SSTable lifecycle management to advanced techniques in compaction and read amplification reduction, all essential for high-performance distributed storage solutions.&lt;/p&gt;</description></item><item><title>Implementing CountDownLatch Functionality in Go Inspired by Java</title><link>https://umitunal.net/2021/04/implementing-countdownlatch-functionality-in-go-inspired-by-java/</link><pubDate>Fri, 09 Apr 2021 12:42:59 +0300</pubDate><guid>https://umitunal.net/2021/04/implementing-countdownlatch-functionality-in-go-inspired-by-java/</guid><description>&lt;p&gt;When working with concurrent applications, synchronization primitives are essential tools. While Go provides &lt;code&gt;sync.WaitGroup&lt;/code&gt;, sometimes we need more sophisticated control like timeouts. Java&amp;rsquo;s &lt;code&gt;CountDownLatch&lt;/code&gt; offers this functionality, so let&amp;rsquo;s implement it in Go.&lt;/p&gt;
&lt;h2 id="the-implementation"&gt;The Implementation&lt;/h2&gt;
&lt;p&gt;Our CountDownLatch combines Go&amp;rsquo;s &lt;code&gt;sync.WaitGroup&lt;/code&gt; with atomic operations for thread-safe counting:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CountDownLatch&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;sync&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;WaitGroup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;counter&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;uint64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The struct embeds &lt;code&gt;sync.WaitGroup&lt;/code&gt; and adds a &lt;code&gt;counter&lt;/code&gt; field using &lt;code&gt;uint64&lt;/code&gt; to store two 32-bit counters in one atomic value.&lt;/p&gt;</description></item></channel></rss>