業界普遍存在三大 Redis 認知誤區:(1) 認為 Redis 不可能比 Memcached 快,(2) 將其定位為「可持久化的 Memcached」,(3) 忽略其「資料結構伺服器」本質。本文從原始碼架構、事件循環、記憶體模型、CAS 開銷、資料型別語義、持久化權衡六大維度,深度解析 Redis 為何在單執行緒模型下超越 Memcached,並闡述正確定位與使用姿勢。
相同硬體 (雙路 Xeon、DDR4、10GbE) 下,redis-benchmark vs memcached-tool:
| 因素 | Memcached | Redis | 影響 |
|---|---|---|---|
| 事件循環庫 | libevent (通用、龐大、鎖爭用) | 自製 ae.c (epoll/kqueue/IOCP 精簡封裝,< 2000 行) | Redis 事件分派零鎖、零分配、極低延遲 |
| CAS/版本機制 | 每個 key 附帶 64-bit CAS token (CPU+記憶體開銷) | 無內建 CAS,樂觀鎖由應用層用 WATCH/MULTI 實現 | Memcached 額外 8 bytes/key + 原子增減開銷 |
| 記憶體分配器 | slab allocator (固定 size class,內部碎片高) | jemalloc (預設) / tcmalloc / glibc malloc,通用高效分配 | Redis 記憶體碎片率通常 < 1.1,Memcached 常 > 1.3 |
| 網路協議 | 純文本 + 二進制雙協議,解析分支多 | RESP (REdis Serialization Protocol) 純文本、極簡、流水線友善 | Redis 解析器更輕量,支援 Pipeline 批次提交 |
| I/O 模型 | 多執行緒 (worker threads),鎖保護共享資料結構 | 單執行緒事件循環,無鎖、無上下文切換 | Redis 避免鎖競爭、Cache line bouncing,單核效能極致 |
單執行緒 ≠ 慢。Redis 將所有命令序列化在單一事件循環,消除鎖、上下文切換、Cache 一致性流量,配合非阻塞 I/O、Pipeline、Lua 腳本原子性,單核吞吐可達 100M ops/sec。多核擴展採用「多實例 + 叢集分片」而非多執行緒。
| 維度 | Memcached | Redis |
|---|---|---|
| 核心抽象 | Key → Blob (不透明二進制) | Key → Rich Data Structure (String/Hash/List/Set/ZSet/Stream...) |
| 伺服端運算 | 無 (僅 Get/Set/Incr/Decr/CAS) | 豐富:Lua 腳本、Lua 函數、伺服端 LUA、Bitwise、Geo、HyperLogLog |
| 資料模型 | 扁平 KV | 多模型:快取、佇列、排行榜、速率限制、地理位置、串流日誌 |
| 持久化角色 | 無 (純快取) | 可選:RDB/AOF 讓 Redis 兼具資料庫特性 |
| 一致性保證 | 最終一致 (叢集) | 單執行緒強一致、WAIT 指令可達同步複寫 |
Redis 是 Remote Dictionary Server (資料結構伺服器),而非單純快取。其設計目標是「在記憶體速度下提供豐富資料結構與原子操作」,持久化是輔助手段而非核心賣點。
| 反模式 (String) | 問題 | 正確結構 | 優勢 |
|---|---|---|---|
| JSON 序列化整個物件 | 部分更新需全量讀寫、無法原子操作欄位 | Hash (HSET/HGET/HINCRBY) | 欄位級原子、記憶體更省 (ziplist) |
| List 用逗號分隔字串 | 插入/刪除/查詢 O(N)、無原子 | List (LPUSH/RPOP/LTRIM) | O(1) 雙端隊列、阻塞式 BLPOP 實現佇列 |
| Set 用 JSON 陣列 | 去重/交集/差集需應用層計算 | Set (SADD/SREM/SINTER/SUNION/SDIFF) | 原子集合運算、伺服端完成 |
| Sorted Set 用 JSON + 排序 | 排序、分頁、範圍查詢極慢 | ZSet (ZADD/ZRANGE/ZRANK/ZSCORE) | O(log N) 插入/排名/分數範圍查詢 |
| Stream 用 List 模擬 | 無消費者群組、無確認機制、無封存 | Stream (XADD/XREADGROUP/XACK) | 原生消費者群組、 exactamente-once、封存 |
誤區:以為開啟持久化就「萬無一失」。
建議:關鍵業務啟用混合持久化,非關鍵快取可僅用 RDB 或純記憶體。
Redis Cluster 採用 Hash Slot (16384 slots) 分片,每個 Master 負責部分 slots,支援:
{user:100}:profile 強制)MEMORY PURGE、關閉 THP