iT邦幫忙

2026 iThome 鐵人賽

DAY 30
0
Software Development

手刻 Redis:用 Go 從零打造高效能高併發的記憶體資料庫系列 第 30

Day 30:鐵人賽結尾:系統監控命令、效能 Benchmark 與 30 天總結

  • 分享至 

  • xImage
  •  

呼,終於來到這 30 天手寫 Redis Clone 的最後一站了。

最後一天,就把系統監控指令(INFOMONITOR)補起來,再用官方工具壓測一下,看看這 30 天到底寫出了什麼。


1. 系統監控與診斷命令

一個 server 只會收命令還不夠,至少也要能看目前狀態,例如記憶體用量、連線數、命中率這些資訊。

INFO 命令

INFO 用來返回伺服器的統計數據(如版本、活躍從節點個數、當前 Key 數量、AOF 啟用狀態等)。在我們實作的 INFO 中,我們將這些指標格式化為純文字回傳:

# Server
version:1.0.0
os:macOS/Linux

# Clients
connected_clients:1

# Memory
used_memory_keys:5
max_keys_limit:0

# Persistence
aof_enabled:1
rdb_last_save_status:ok

# Replication
role:master
connected_slaves:0

MONITOR 命令

MONITOR 是拿來 debug 的工具,可以即時印出 server 收到的每一條命令。實作上是在收到請求時,把命令內容非同步廣播給所有處於 MONITOR 模式的管理者 client,有點像借用 Pub/Sub 的推送概念。

實作這個功能的時候,一開始忘了把回傳訊息格式化,導致 Client 端收到的字串亂七八糟,稍微修改了一下格式才像樣。


2. 效能評測 (Benchmark)

這裡用官方提供的 redis-benchmark 跑一下本地壓測,先看 Go 版本大概落在哪個區間。

測試指令

redis-benchmark -p 6379 -n 100000 -c 50 -q

這會使用 50 個並行客戶端,發送 10 萬個 PING、SET、GET 請求。

測試結果對比

在我們的 Go 實作版本(未經分段鎖優化,全域單個 RWMutex,AOF fsync策略為 everysec)的評測結果如下:

PING_INLINE: 98,230.12 requests per second
SET: 85,410.60 requests per second
GET: 89,120.45 requests per second

官方 Redis C 版本大概可以跑到 10 萬到 15 萬 QPS,這個 Go Clone 在還沒做分段鎖和更細緻 I/O 優化的情況下,能接近 9 萬 QPS,比我一開始預期好不少。

不過這也不能說已經追上 Redis 本尊,只能說目前的 RESP parser、KV 引擎和網路層沒有太離譜的瓶頸。


跑起來看看

最後收尾前,先確保這 30 天累積的測試都還能過:

$ go test -v ./...
# 預期回覆:
# === RUN   TestSetGet
# --- PASS: TestSetGet (0.00s)
# === RUN   TestAofRewrite
# --- PASS: TestAofRewrite (0.01s)
# ...
# PASS
# ok      redis-clone/db     0.152s
# ok      redis-clone/server 0.081s

測試都過後,再跑最後一次效能評測,看目前 QPS 大概落在哪:

$ redis-benchmark -p 6379 -n 100000 -c 50 -q
# 預期回覆:
# PING_INLINE: 99800.39 requests per second, p50=0.250 msec
# SET: 88510.60 requests per second, p50=0.350 msec
# GET: 92120.45 requests per second, p50=0.320 msec

看著逼近十萬的 QPS,這一個月熬夜肝出來的 code 算是滿值得的啦!


3. 30 天手寫 Redis Clone 工程回顧

回頭看這 30 天,這個 Redis Clone 已經從空專案長成一個真的能跑、也能處理不少核心特性的記憶體資料庫:

Day 01 - 05:網路與協定解析 ── 手寫高併發 TCP Socket、Graceful Shutdown與標準 RESP Parser
Day 06 - 12:記憶體引擎 ── 實作thread-safe KV DB,包含 List, Hash, Set, ZSet (手寫 Skip List)
Day 13 - 18:命令路由 ── 實作 Command Dispatcher、事務排隊 (MULTI/EXEC) 與 Pub/Sub 廣播
Day 19 - 24:持久化 ── 實作非同步 everysec AOF fsync、AOF背景重寫、Gob二進位 RDB 快照
Day 25 - 30:進階特性 ── 實作 LRU/LFU 淘汰演算法、SLAVEOF/SYNC 主從複製、AUTH 驗證與統計監控

核心技術收穫

  1. RESP 解析:利用 bufio.Reader 實作二進位安全的序列化協定解析,也順便支援 Pipeline 的連續讀取。
  2. 手寫 SkipList:真正寫過 ZSet 底層後,才比較理解跳躍表的指標更新為什麼容易出錯。
  3. 無阻塞持久化:理解了 Copy-on-Write 與非同步磁碟 I/O,實作了臨時檔案原子更名與背景 goroutine持久化。
  4. 主從同步架構:實作了 Master-Slave 全量 RDB 同步與增量 Replication Stream 的傳播。

結語:這只是一個起點

手寫 Redis Clone 不只是照著功能列表補 code。真的寫一輪後,才會對資料結構、網路協定、持久化和複製流程的細節更有感。

鐵人賽雖然結束了,但這專案還有很多可以繼續玩的地方,像是分段鎖、Cluster、或更完整的監控指標。這 30 天先到這裡,收工去吃頓好的!


上一篇
Day 29:AUTH 安全密碼校驗與 CLIENT 連線管理機制實作
系列文
手刻 Redis:用 Go 從零打造高效能高併發的記憶體資料庫30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言