Memcached 定位
- **分散式**記憶體物件快取,基於網路 (TCP/UDP) 服務,非本地共享記憶體 (區別於 APC/Shm)。
- 適用場景:DB 前端快取、跨服務 Session/Token 共享、熱點資料緩衝。
- **不適用**:單機本地快取 (網路開銷大於收益)、持久化儲存 (重啟資料丟失)。
啟動流程 (memcached.c main)
- `settings_init()` 初始化預設參數。
- 解析命令列參數覆蓋設定。
- 設定 `RLIMIT_NOFILE` (最大檔案描述符)。
- 建立 TCP/UDP/Unix Socket 監聽。
- 檢查非 root 身份 (安全)。
- Daemon 化 (`-d` 參數) → `daemon()` fork + `setsid` + 重導向標準流到 `/dev/null`。
- 初始化核心子系統:`item`、`event` (libevent)、`stats`、`hash` (一致性雜湊)、`conn`、 `slab` 分配器。
- 訊號處理、刪除佇列、PID 檔寫入。
- 進入 `drive_machine` 事件迴圈 (libevent `event_base_loop`)。
記憶體管理:Slab Allocator (核心亮點)
設計動機
避免頻繁 `malloc/free` 造成碎片與鎖爭用,預先向 OS 申請大塊 (預設 1MB) Slab,切分為固定大小 Chunk。
關鍵資料結構
- `slabclass[0..MAX_NUMBER_OF_SLAB_CLASSES-1]` (1.2 版預設 200 類)。
- 每 class 固定 `chunk_size`,遞增因子 `factor=1.25` (可調 `-f`)。
- `chunk_size[0] = 96 bytes` (含 `item` 結構體),之後 `chunk_size[n] = ceil(chunk_size[n-1] * factor)` 對齊 8 位元組。
分配流程
- 客戶端 `set` → 計算 `key+value+flags+expire` 總長 → 找到最小滿足的 `slabclass`。
- 該 class `slots` 鏈表有空閒 chunk → 直接取用。
- 無空閒 → 向 OS 申請新 1MB Slab → 切分掛入 `slots` → 取用。
- LRU 淘汰:同 class 內按 `time` 排序,尾部淘汰 (非全域 LRU)。
優缺點
| 優點 | 缺點 |
| O(1) 分配/釋放,無碎片 (內部碎片僅 < factor) | 內部碎片浪費:小值存大 chunk (如 100B 存 136B chunk) |
| 鎖粒度細 (每 class 一把鎖),高併發擴展性好 | 無法跨 class 借用記憶體,導致部分 class OOM 而其他 class 閒置 |
網路模型:libevent + 狀態機
- 單執行緒 (預設) + 非阻塞 I/O,`drive_machine` 根據 `conn->state` 處理讀/寫/關閉。
- 支援多執行緒 (`-t`):主執行緒 `accept` → 分派到 worker 執行緒佇列,各自獨立 event_base。
- 協議:簡單文本行協議 (`set key flags exptime bytes\r\nvalue\r\n`),二進制協議 (1.3+) 減少解析開銷。
分散式:Client 端一致性雜湊
**伺服器端無叢集感知**,分散邏輯完全在 Client Library:
- 將 Key 雜湊 (Ketama 演算法) 映射到 0~2^32-1 環。
- 每台實體伺服器對應 100-200 個虛擬節點 (權重可調)。
- 順時針找最近虛擬節點 → 該實體伺服器。
- 增減節點僅影響少數 Key 重新映射 (單調性)。
BSM_Memcache (PHP 擴展) 關鍵實現
- C 層封裝 `libmemcached`,提供 `Memcache` 類相容介面 + 新增 `getMulti`、`setMulti` 批次操作。
- 連線池管理:`persistent_id` 區分進程間共享連線,避免 PHP-FPM 重複建連。
- 序列化策略:`igbinary` > `msgpack` > `php` (可配置 `memcache.serializer`)。
- 壓縮:`MEMCACHE_COMPRESSED` 旗標觸發 `zlib` 壓縮,閾值 `memcache.compress_threshold` (預設 20KB)。
調優檢查清單
- `-m` 記憶體上限 (預設 64MB,生產建議 2-4GB/進程)。
- `-f` 增長因子 (1.1-1.25,資料長度分佈均勻可調小)。
- `-t` 執行緒數 (CPU 核心數,超執行緒不建議超過物理核心)。
- 監控 `stats`:`get_hits/get_misses`、 `evictions`、 `bytes_used/limit_maxbytes`、 `curr_connections`。
- Client 端:連線池復用、批次 `getMulti`、`setMulti` 減少 RTT、關閉 `no_delay` (Nagle) 降低延遲。
- 上一篇文章: file_get_contents 失效替代方案:cURL 兜底通用函數 (支援超時、HTTPS、錯誤處理)
- 下一篇文章: Zend Studio 開啟 PHP 5.2.x 遠程除錯:輕量級 Zend Debugger 替代 Zend Platform
Copyright ©
程式碼之家 All Rights Reserved