Skip to content

Commit de8778f

Browse files
committed
content(blog): dht
1 parent 75714ba commit de8778f

File tree

2 files changed

+176
-1
lines changed

2 files changed

+176
-1
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# The Chaos Coordinator: Mastering Distributed Hash Tables (DHT)
2+
3+
Imagine you're at the world's largest party. There are millions of people, and everyone is carrying exactly one piece of a giant, fragmented encyclopedia. You want to find the page about "How to make the perfect sourdough."
4+
5+
In a **centralized** world, you'd go to the host (the server). If the host is in the bathroom or fainted from the stress, you're out of luck.
6+
7+
In a **distributed** world—the world of **DHTs**—you ask the person next to you. They might not have the page, but they know someone who is "closer" to the topic. After a few hops, you're holding your sourdough recipe.
8+
9+
Welcome to the magic of Distributed Hash Tables. It's how BitTorrent works, how IPFS breathes, and why decentralized systems don't just collapse into a pile of "404 Not Found" errors.
10+
11+
---
12+
13+
## What is a DHT, really?
14+
15+
At its heart, a DHT is just a **Key-Value store**.
16+
- **Key:** The hash of the data (e.g., `SHA-1("sourdough-recipe")`).
17+
- **Value:** The data itself or the address of the node storing it.
18+
19+
The "Distributed" part means we slice this giant table into pieces and give a piece to every node in the network. But there's a catch: **How do we know who has what?**
20+
21+
We don't want to broadcast "WHO HAS THE SOURDOUGH?" to millions of people. That's a network storm. We need **Routing**.
22+
23+
## The Keyspace: The Circle of Life
24+
25+
Most DHTs (like **Chord** or **Kademlia**) imagine the entire universe of possible keys as a giant circle.
26+
27+
If your hash is 160 bits (like SHA-1), your keyspace is $2^{160}$. That's more addresses than there are atoms in... okay, maybe not atoms, but it's a LOT.
28+
29+
Each node in the network is also assigned a unique ID from this same keyspace. A node is responsible for keys that are "close" to its own ID.
30+
31+
## Distance: When Math Gets Emotional
32+
33+
How do we define "close"?
34+
- In **Chord**, it's the numerical distance clockwise.
35+
- In **Kademlia** (the gold standard), we use the **XOR metric**.
36+
37+
### Why XOR?
38+
XOR ($ \oplus $) is a genius choice for distance because it’s a **metric**:
39+
1. $d(A, B) = 0$ iff $A = B$
40+
2. $d(A, B) = d(B, A)$ (Symmetry!)
41+
3. $d(A, B) + d(B, C) \ge d(A, C)$ (Triangle inequality)
42+
43+
In Go, calculating this distance is trivial but powerful:
44+
45+
```go
46+
func Distance(id1, id2 []byte) []byte {
47+
result := make([]byte, len(id1))
48+
for i := 0; i < len(id1); i++ {
49+
result[i] = id1[i] ^ id2[i]
50+
}
51+
return result
52+
}
53+
```
54+
55+
## Kademlia: The "Buckets" Strategy
56+
57+
Kademlia doesn't just remember everyone. It's picky. It uses **k-buckets**.
58+
59+
A node keeps a list of other nodes. For every bit-distance $i$ (from 0 to 160), it keeps a bucket of $k$ nodes that share a prefix of length $i$ with it.
60+
61+
- Nodes that are "far" away: We only know a few.
62+
- Nodes that are "near" us: We know almost all of them.
63+
64+
This creates a **logarithmic routing table**. To find any key in a network of $N$ nodes, you only need $O(\log N)$ hops. In a network of 10 million nodes, that’s about 24 hops. **Twenty-four!**
65+
66+
## Let's Build a Minimal Node in Go
67+
68+
Here is how you might represent a Node and its Routing Table in a Kademlia-inspired DHT:
69+
70+
```go
71+
package dht
72+
73+
import (
74+
"crypto/sha1"
75+
"fmt"
76+
)
77+
78+
const IDLength = 20 // 160 bits for SHA-1
79+
80+
type NodeID [IDLength]byte
81+
82+
type Contact struct {
83+
ID NodeID
84+
Address string
85+
}
86+
87+
type RoutingTable struct {
88+
Self Contact
89+
Buckets [IDLength * 8][]Contact
90+
}
91+
92+
// NewNodeID generates a ID from a string (like an IP or Username)
93+
func NewNodeID(data string) NodeID {
94+
return sha1.Sum([]byte(data))
95+
}
96+
97+
// GetBucketIndex finds which bucket a target ID belongs to
98+
func (rt *RoutingTable) GetBucketIndex(target NodeID) int {
99+
distance := Distance(rt.Self.ID[:], target[:])
100+
// Find the first non-zero bit
101+
for i, b := range distance {
102+
if b != 0 {
103+
for j := 0; j < 8; j++ {
104+
if (b >> uint(7-j)) & 0x01 != 0 {
105+
return i*8 + j
106+
}
107+
}
108+
}
109+
}
110+
return len(rt.Buckets) - 1
111+
}
112+
```
113+
114+
## The Lifecycle of a Query
115+
116+
1. **The Search:** I want Key `K`. I look at my routing table and find the $k$ nodes I know that are closest to `K`.
117+
2. **The Request:** I ask them: "Do you have `K`? If not, give me the closest nodes you know."
118+
3. **The Iteration:** They send back closer nodes. I ask *those* nodes.
119+
4. **The Convergence:** Each step, the distance to `K` halves (logarithmic magic). Eventually, I find the node holding `K`.
120+
5. **Caching:** Once I find it, I might store a copy of `K` on the nodes I asked along the way so the next person finds it even faster.
121+
122+
## Why should you care?
123+
124+
DHTs are the antidote to censorship and central failure. They are the backbone of:
125+
- **BitTorrent:** Finding peers without a central tracker.
126+
- **Ethereum:** Node discovery in the p2p layer.
127+
- **IPFS:** The interplanetary file system.
128+
129+
## Summary
130+
131+
DHTs turn chaos into a structured, searchable universe. By using clever math like XOR and logarithmic buckets, we can build systems that scale to millions of users without a single server in sight.
132+
133+
Now go forth and distribute your hashes! Just... maybe don't XOR your house keys. That won't end well.
134+
135+
---
136+
137+
*Found this useful? Or did I just XOR your brain into a state of confusion?*

public/posts/posts.json

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,42 @@
11
[
2+
{
3+
"slug": "tag-file-systems-explained-go-implementation",
4+
"title": "Escape the Hierarchy Trap: How Tag File Systems Work",
5+
"date": "2026-02-18",
6+
"updated": "2026-02-18",
7+
"description": "Ditch the folders! A deep dive into Tag-based File Systems, why hierarchical organization is failing us, and how FUSE and databases make tagging possible. Includes a Go implementation!",
8+
"tags": [
9+
"filesystems",
10+
"go",
11+
"databases",
12+
"architecture",
13+
"productivity"
14+
],
15+
"category": "dev",
16+
"filename": "tag-file-systems-explained-go-implementation.txt",
17+
"authors": [
18+
"fezcode"
19+
]
20+
},
21+
{
22+
"slug": "dht-distributed-hash-tables-go-educational-guide",
23+
"title": "The Chaos Coordinator: Mastering Distributed Hash Tables (DHT)",
24+
"date": "2026-02-18",
25+
"updated": "2026-02-18",
26+
"description": "A deep dive into Distributed Hash Tables (DHTs), Kademlia, XOR metrics, and building decentralized routing in Go. Fun, fast, and very educational.",
27+
"tags": [
28+
"go",
29+
"distributed-systems",
30+
"p2p",
31+
"networking",
32+
"dht"
33+
],
34+
"category": "dev",
35+
"filename": "dht-distributed-hash-tables-go-educational-guide.txt",
36+
"authors": [
37+
"fezcode"
38+
]
39+
},
240
{
341
"slug": "gobake-go-build-orchestrator",
442
"title": "gobake: The Build Orchestrator Go Was Missing",
@@ -2067,4 +2105,4 @@
20672105
"fezcode"
20682106
]
20692107
}
2070-
]
2108+
]

0 commit comments

Comments
 (0)