1511 字
8 分钟
手撸才是硬道理!2026 年最硬核的学习方式:Build Your Own X

手撸才是硬道理!2026 年最硬核的学习方式:Build Your Own X#

你有没有这样的经历——

看了一堆 Redis 的八股文,背熟了「跳表」「RDB 持久化」「主从复制」这些概念,面试官一问:「那如果让你设计一个 KV 存储,你会怎么做?」你瞬间大脑空白。

知其然不知其所以然,是大多数程序员学习过程中的通病。而治愈这个病的最好药方,就是 Build Your Own X——亲手重新实现那些你每天都在用的技术工具。

这个由 codecrafters-io/build-your-own-x 领衔的开源项目系列,在 GitHub 上一直保持超高热度。它的核心理念很简单:你只有亲手造过一个轮子,才能真正理解它为什么被设计成那样

为什么要自造轮子?#

有人可能会说:「Redis 已经写得那么好了,我干嘛还要自己实现一遍?」

这是个好问题。我的回答是:你学外语也不是为了取代母语者,而是为了理解他们的思维方式。

举个例子,当你自己实现一个 Git 的时候,你会深刻理解:

  • 为什么 Git 的存储是不可变的(immutable objects)
  • 为什么分支切换在 Git 里几乎是 O(1) 的操作
  • 为什么 Git 处理大文件那么痛苦(因为每次 commit 都是完整快照)

这些理解不是读文档能获得的,必须亲手踩过坑才知道。

手撸一个迷你 Redis#

光说不练假把式。我们来做一个最简单的 KV 存储 + TCP Server,感受一下 Redis 的核心设计思路:

#!/usr/bin/env python3
"""MiniRedis: 一个用 Python 实现的简易 KV 存储服务器"""
import asyncio
import time
from typing import Optional
class MiniRedis:
"""核心 KV 存储引擎"""
def __init__(self):
self._data: dict[str, tuple[str, Optional[float]]] = {}
# 结构:{ key: (value, expire_at) }
# expire_at 为 None 表示永不过期
def set(self, key: str, value: str, expire_seconds: int = None) -> str:
"""设置键值对,支持 TTL"""
expire_at = time.time() + expire_seconds if expire_seconds else None
self._data[key] = (value, expire_at)
return "OK"
def get(self, key: str) -> Optional[str]:
"""获取键值,自动处理过期"""
if key not in self._data:
return None
value, expire_at = self._data[key]
if expire_at and time.time() > expire_at:
del self._data[key] # 惰性删除
return None
return value
def delete(self, key: str) -> int:
"""删除键,返回删除数量(兼容 Redis 语义)"""
if key in self._data:
del self._data[key]
return 1
return 0
def exists(self, key: str) -> int:
"""检查键是否存在"""
return 1 if self.get(key) is not None else 0
# 协议解析器:解析 Redis 的 RESP 协议
class RESPProtocol:
"""RESP (Redis Serialization Protocol) 解析"""
@staticmethod
def encode_simple_string(s: str) -> bytes:
return f"+{s}\r\n".encode()
@staticmethod
def encode_bulk_string(s: Optional[str]) -> bytes:
if s is None:
return b"$-1\r\n"
return f"${len(s)}\r\n{s}\r\n".encode()
@staticmethod
def encode_integer(n: int) -> bytes:
return f":{n}\r\n".encode()
@staticmethod
def encode_error(msg: str) -> bytes:
return f"-ERR {msg}\r\n".encode()
# TCP Server:处理客户端连接
async def handle_client(reader: asyncio.StreamReader,
writer: asyncio.StreamWriter,
db: MiniRedis):
"""处理单个客户端连接"""
addr = writer.get_extra_info('peername')
print(f"新客户端连接: {addr}")
try:
while True:
data = await reader.readline()
if not data:
break
line = data.decode().strip()
parts = line.split()
if not parts:
continue
cmd = parts[0].upper()
if cmd == "SET" and len(parts) >= 3:
key, value = parts[1], parts[2]
expire = int(parts[4]) if len(parts) > 4 and parts[3].upper() == "EX" else None
result = db.set(key, value, expire)
writer.write(RESPProtocol.encode_simple_string(result))
elif cmd == "GET" and len(parts) == 2:
value = db.get(parts[1])
writer.write(RESPProtocol.encode_bulk_string(value))
elif cmd == "DEL" and len(parts) >= 2:
count = sum(db.delete(k) for k in parts[1:])
writer.write(RESPProtocol.encode_integer(count))
elif cmd == "PING":
writer.write(RESPProtocol.encode_simple_string("PONG"))
else:
writer.write(RESPProtocol.encode_error(f"unknown command: {cmd}"))
await writer.drain()
except ConnectionResetError:
pass
finally:
writer.close()
await writer.wait_closed()
print(f"客户端断开: {addr}")
async def main():
db = MiniRedis()
server = await asyncio.start_server(
lambda r, w: handle_client(r, w, db),
'127.0.0.1', 6379
)
addr = server.sockets[0].getsockname()
print(f"MiniRedis 启动在 {addr}")
print("你可以用标准 redis-cli 连接测试!")
async with server:
await server.serve_forever()
if __name__ == '__main__':
asyncio.run(main())

这个迷你 Redis 虽然只有不到 120 行,但它已经覆盖了几个核心概念:

  1. RESP 协议——理解了为什么 Redis 协议是文本 + 二进制的混合设计
  2. 惰性删除——Redis 的过期策略之一,在 get 的时候检查过期
  3. 事件循环——基于 asyncio 的单线程模型,跟 Redis 的 Reactor 模式异曲同工

Build Your Own X 的学习路线图#

如果你也想尝试这种硬核学习方式,这里有一份我梳理的路线图,按难度排序:

🌱 新手村(1-2 天可完成)
├── Build Your Own Calculator(理解解析器)
├── Build Your Own Todo List(理解 CRUD + 状态管理)
└── Build Your Own URL Shortener(理解 301/302 + 哈希)
🌿 进阶区(1-2 周)
├── Build Your Own Redis(理解 KV 存储 + 协议)
├── Build Your Own Git(理解快照存储 + DAG)
├── Build Your Own Docker(理解 Namespace + Cgroup)
└── Build Your Own Web Server(理解 HTTP + Socket)
🌳 高手区(2-4 周)
├── Build Your Own Database(理解 B-Tree + WAL)
├── Build Your Own Kubernetes(理解调度器 + Controller)
├── Build Your Own Compiler(理解 AST + 代码生成)
└── Build Your Own Blockchain(理解共识算法 + Merkle Tree)

Codecrafters 平台(也就是 codecrafters-io/build-your-own-x 的团队)甚至做了一个付费版本,提供交互动手环境。它会一步步引导你,每完成一个阶段都有测试验证,确保你的实现是正确的。

面试中的应用#

这个系列对面试的帮助真的太大了。我有个读者说,他在面字节跳动的时候,面试官问他「讲讲 Redis 的过期策略」,他直接说「我还原过 Redis 的 SETEX 命令实现」,然后当场在白板上画出了 mini Redis 的代码结构,面试官直接给了他 Strong Hire。

面试官问的是「你用过什么技术」,你说「我用过」,这是平均水平。面试官问「你用过什么技术」,你说「我还原过它的核心实现」——这就是碾压水平。

结语#

Build Your Own X 不仅仅是一个学习项目,更是一种工程师的思维方式。下次当你遇到一个「不理解为什么这样设计」的技术时,不要只读文档,试着亲手实现一个迷你版本。哪怕只有 100 行代码,它带给你的理解深度,远超 10 篇阅读量 10w+ 的技术文章。

代码仓库在这里:github.com/codecrafters-io/build-your-own-x

去给它点个 Star,然后开始你的第一个 Build Your Own X 项目吧。别忘了——轮子造过一次就好,理解才是永恒的

手撸才是硬道理!2026 年最硬核的学习方式:Build Your Own X
https://www.oferry.com/posts/a102/
作者
晨平安
发布于
2026-05-30
许可协议
CC BY-NC-SA 4.0
封面
示例歌曲
示例艺术家
封面
示例歌曲
示例艺术家
0:00 / 0:00