前言
Memcached 是分散式快取系統標準選擇,Java 客戶端庫主要有 spymemcached (Couchbase 維護) 和 xmemcached (國產開源)。兩者架構不同:spymemcached 採非同步單執行緒 IO;xmemcached 採同步多執行緒並支援批次操作。本文實測兩者在不同併發度下的讀寫效能。
測試環境與方法
- 測試方式:啟動 N 個執行緒,每執行緒執行 10,000 次 set/get/delete (簡單類型) 或 100 次 (複雜物件)
- 指標:TPS (Transactions Per Second),數值越高越好
- 環境:相同硬體、網路、Memcached 伺服器版本
測試一:簡單類型讀寫 (String/Integer)
結果表 (TPS)
| 執行緒數 | spymemcached | xmemcached |
| set | get | delete | set | get | delete |
| 1 | 2,870 | 2,922 | 3,018 | 2,237 | 2,352 | 2,500 |
| 10 | 11,015 | 11,227 | 11,449 | 8,579 | 10,440 | 8,354 |
| 50 | 19,838 | 20,685 | 22,727 | 13,239 | 24,113 | 14,382 |
| 100 | 25,427 | 22,646 | 26,700 | 18,068 | 29,046 | 18,259 |
分析結論
- spymemcached 全面領先:在 set/delete 操作上穩定領先 30-50%
- xmemcached 唯一亮點:高併發 (50-100 執行緒) 下 get 效能略勝一籌
- 原因推測:xmemcached 將連續 get 操作合併為批次
get_multi 指令,減少網路往返,提升吞吐
測試二:複雜物件讀寫 (100 元素 Map,Value 為自訂類別)
結果表 (TPS)
| 執行緒數 | spymemcached | xmemcached |
| set | get | set | get |
| 1 | 492 | 492 | 427 | 492 |
| 10 | 159 | 680 | 1,103 | 1,122 |
| 50 | 57 | 1,103 | 1,561 | 1,226 |
| 100 | 71 | 1,308 | 1,530 | 1,223 |
驚人逆轉:xmemcached 全面碾壓
- set 效能差距巨大:100 執行緒下 xmemcached (1,530) 是 spymemcached (71) 的 21 倍!
- get 效能:xmemcached 穩定領先 1.2-1.5 倍
- CPU/記憶體佔用:兩者肉眼觀察差異不大
深度原因分析
- 序列化機制差異:spymemcached 預設使用 Java 原生序列化,對大型物件效能極差;xmemcached 支援多種編碼器 (如 Kryo, Protostuff),預設可能更高效
- 非同步 vs 同步架構:spymemcached 單執行緒 IO 處理大物件序列化時易阻塞事件迴路;xmemcached 多執行緒可並行處理序列化
- 批次操作優勢:複雜物件 get 同樣受益於 xmemcached 的批次合併機制
選型建議
| 場景 | 推薦客戶端 | 理由 |
| 簡單鍵值快取 (String, 數值, 小物件) | spymemcached | 單執行緒非同步模型延遲低、吞吐高、成熟穩定 |
| 複雜物件/大型物件快取 | xmemcached | 序列化效能強、支援批次 get、多執行緒架構適合重負載 |
| 需要高可用/自動故障轉移 | spymemcached | 內建 Ketama 一致性雜湊、動態節點發現、Couchbase 企業級支援 |
| 國產化/原始碼可控需求 | xmemcached | 國人開發、文檔中文友好、原始碼易閱讀修改 |
優化提示
- 避免 Java 原生序列化:改用 Kryo, Protostuff, Hessian 或 JSON (Jackson/Gson)
- 調整序列化策略:spymemcached 可設定
Transcoder;xmemcached 可設定 Serializer
- 連接池大小:根據 CPU 核心數與併發度調整 (通常 2x CPU 核心)
- 啟用壓縮:大物件開啟壓縮 (gzip/snappy) 減少網路傳輸
結語
「沒有最好的工具,只有最適合的工具」。簡單快取選 spymemcached,複雜物件選 xmemcached。實際專案務必依真實資料模型與存取模式進行基準測試,數據才是決策依據。