Redis 不只是快取
大多數工程師第一次認識 Redis,是把它當作 Cache 層使用:把資料庫查詢結果放進去, 設個 TTL,讀取時先查 Redis 再查 DB。這當然沒問題,但 Redis 的能力遠不止於此。 它是一個多功能的記憶體資料結構伺服器,理解它的完整能力,能讓你少寫很多複雜的系統。
快取(Cache)
最常見的用法,SET/GET/TTL。把 DB 熱點資料放進 Redis,讀取速度從毫秒降到微秒。
Session Store
使用者登入狀態儲存。比存在 DB 快、比存在 Server 記憶體更能做水平擴展。
排行榜(Leaderboard)
Sorted Set 的天然應用場景。ZADD 更新分數,ZREVRANGE 取前N名,O(log N) 複雜度。
Pub/Sub 訊息系統
輕量的事件廣播機制。不需要 Kafka,小規模的即時通知用 Redis Pub/Sub 就夠了。
分散式鎖(Distributed Lock)
跨服務的互斥操作。多台 Server 同時搶同一個資源,用 Redis 加鎖防止 Race Condition。
計數與統計
HyperLogLog 統計 UV,Bloom Filter 判斷是否存在,以極小的記憶體換取巨大的效能。
在深入各個應用場景之前,先快速回顧 Redis 的五種核心資料結構, 因為後面所有的進階用法都建立在這些基礎之上:
Pub/Sub — 輕量事件廣播
Redis 的 Pub/Sub 提供了一個簡單的發布-訂閱模型:Publisher 把訊息發布到某個頻道(Channel), 所有訂閱該頻道的 Subscriber 都會即時收到。實作即時通知、廣播系統、 或服務間的輕量事件傳遞時,Redis Pub/Sub 是比引入 Kafka 更輕量的選擇。
Pub/Sub 的限制,以及 Redis Streams 如何解決
何時用 Pub/Sub,何時用 Streams?
如果你需要的是「廣播通知」(多個訂閱者同時收到),且可以接受訊息遺失,用 Pub/Sub 就好,簡單快速。 如果你需要「可靠的任務佇列」(每條訊息只被處理一次,且保證送達),用 Redis Streams。 Kafka 適合更大規模(每秒百萬級),Redis Streams 適合中小規模但要比 Pub/Sub 更可靠的場景。
分散式鎖(Distributed Lock)
單一程序內的 Race Condition 可以用 Mutex(互斥鎖)解決。但在多台 Server 的分散式環境中, 每台機器的記憶體是獨立的,傳統的鎖根本跨不了機器邊界。 這時候就需要用 Redis 實作分散式鎖。
分散式鎖的正確使用方式
鎖的 TTL 必須遠大於臨界區的執行時間,否則程式還在執行中鎖就過期了,另一個執行緒就會進來。 釋放鎖時一定要用 Lua Script 或 Redlock,確認 token 是自己的再刪除, 否則可能不小心釋放了別人的鎖。生產環境強烈建議使用成熟的 Redlock 函式庫而不是自己實作。
Lua Script — 原子操作的終極武器
Redis 是單執行緒的,這是它能保證原子性的基礎。但是,當你需要執行多個命令的組合操作時, 這些命令之間仍然可能被其他客戶端打斷。Lua Script 讓你把多個命令打包成一個原子操作, Redis 保證執行期間不會有任何其他命令插入。
Lua Script 的使用場景
任何需要「讀取 → 判斷 → 修改」三步驟的操作,都應該考慮用 Lua Script 包起來。 典型場景:扣庫存、限流器(Rate Limiter)、計數+判斷閾值、帶條件的快取更新。 注意:Lua Script 執行期間 Redis 是阻塞的,不要在 Script 中做複雜的計算或大量遍歷。
HyperLogLog 與 Bloom Filter
當資料量達到億級規模,精確計算「有多少個不重複的元素」或「某個元素是否存在」, 都會消耗大量記憶體。HyperLogLog 和 Bloom Filter 是兩種用「小誤差換巨大記憶體節省」的神奇資料結構。
HyperLogLog — 超省記憶體的基數統計
基數(Cardinality)指的是集合中不重複元素的數量,也就是「獨立訪客數(UV)」的概念。 HyperLogLog 是一種機率型資料結構,用大約 12KB 的固定記憶體,就能統計數億個不重複元素, 誤差率只有約 0.81%。
Bloom Filter — 「可能在」或「一定不在」
Bloom Filter 解決的問題是:「這個元素之前有沒有見過?」 它能在 O(1) 時間內判斷,且只用極少的記憶體,代價是有一定機率的「誤判為存在」(False Positive), 但絕對不會「誤判為不存在」(False Negative)。
Bloom Filter 的保證:
回傳 0(一定不存在):可以 100% 確定這個元素從未被加入過
回傳 1(可能存在):這個元素很可能存在,但有小機率是誤判(False Positive), 需要再查資料庫確認
Sorted Set 實作即時排行榜
排行榜是 Redis Sorted Set 最典型的應用場景。Sorted Set 中的每個成員都有一個關聯的浮點數分數, 成員按分數自動排序。無論是遊戲積分、電商銷售量、還是貼文熱度, Sorted Set 都能以 O(log N) 的複雜度高效更新和查詢排名。
為什麼不用資料庫來做排行榜?
用資料庫 ORDER BY score DESC 在資料量小時沒問題,但隨著玩家增加, 每次更新分數都需要 UPDATE,每次查排名都需要 ORDER BY 全表掃描(即使有索引,寫入時維護索引也有成本)。 Sorted Set 的 ZINCRBY 和 ZREVRANK 都是 O(log N),且 Redis 的記憶體操作遠快於磁碟 I/O。 每秒更新百萬次分數,Redis 輕鬆應對,資料庫早崩了。
Redis 部署與監控最佳實踐
Redis 跑起來很簡單,但在生產環境中要跑得穩,需要了解幾個常見的問題和對應的處理方式。 這裡列出工程師最常遇到的坑,以及對應的解法。
重要監控指標
used_memoryINFO memory
目前使用的記憶體量。應低於 maxmemory 的 80%,否則 GC 壓力大。
connected_clientsINFO clients
目前連線數。突然飆高表示連線池洩漏;建議用 PgBouncer 同理,Redis 也要控制連線數。
keyspace_hits / missesINFO stats
快取命中率 = hits / (hits + misses)。低於 80% 表示快取策略需要調整。
evicted_keysINFO stats
被淘汰的 Key 數量。長期非零表示記憶體不足,需要加記憶體或調整資料 TTL。
instantaneous_ops_per_secINFO stats
每秒操作數(OPS)。突然下降可能表示有大量慢查詢阻塞。
repl_backlog_sizeINFO replication
主從複製的 Backlog 大小。如果 Replica 斷線重連後 Backlog 不夠大,需要全量同步(很慢)。
Tags
上一篇
EP.05 Sharding 水平擴展
下一篇
EP.07(Coming Soon)