别人用Redis只會cache,我用Redis做了六件你絕對想不到的事

2026-05-16 4 0

我干后端这些年,见过太多人把Redis当高级memcache用。set一个key,get一个key,完事。最离谱的是,有人问我:Redis和Memcache有什么区别?我说:大概就是兰博基尼和五菱宏光的区别吧,你非拿超跑拉货也不是不行,就是有点暴殄天物。

今天我就给你们看看,这辆兰博基尼到底能跑多快。


第一件事:Sorted Set 實現即時排行榜

游戏服务器最怕什么?排行榜。每天几百万人同時查榜,傳統方案是寫進數據庫,order by score desc limit 10,數據庫表示我去年買了個錶。

Redis的Sorted Set帮你搞定:

// 玩家積分更新
ZADD leaderboard:2026 8500 "player:9527"

// 前十名排行榜
ZREVRANGE leaderboard:2026 0 9 WITHSCORES

// 查詢某個玩家的排名
ZREVRANK leaderboard:2026 "player:9527"

// 計算某個分數區間有多少人
ZCOUNT leaderboard:2026 8000 9000

原理很簡單:內部是跳躍表(Skip List),查詢複雜度O(log N),無論數據多少,查詢時間都穩定。你沒看錯,是穩定。不是數據量越大越慢的那種垃圾實現。

之前做遊戲的時候,1200萬玩家的即時排行榜,查詢時間穩定在2毫秒以內。MySQL?對不起,1秒往上走。


第二件事:GEO 命令做「附近的人」

外賣、交友、房產APP,幾乎都有「附近的人」功能。傳統方案:經緯度存數據庫,計算兩點距離,SELECT周圍多少公里,數據庫又開始罵娘了。

Redis給你安排得明明白白:

// 添加商戶位置 (經緯度)
GEOADD shops:location 116.397128 39.916527 "shop:001"
GEOADD shops:location 116.397228 39.916627 "shop:002"
GEOADD shops:location 116.398128 39.917527 "shop:003"

// 查詢方圓3公里內的商戶
GEORADIUS shops:location 116.397128 39.916527 3 km WITHDIST ASC COUNT 10

// 查詢某商戶方圓5公里內有多少個商戶
GEODIST shops:location "shop:001" "shop:002" km

背後是GeoHash算法,把二維的經緯度編碼成一維字符串,附近的位置有相同前綴。查詢方圓5公里,響應時間不到1毫秒。

有人問我:為什麼不用PostGIS?我說你高興就好,PostGIS查一個方圓5公里要多少資源你不清楚嗎?


第三件事:Bitmap 做精確簽到統計

用戶簽到、活躍統計,常見方案:每天一張表,幾千萬用戶,COUNT(*)跑半天。Redis Bitmap讓你用一個字節存8天的簽到信息:

// 用戶2026年5月1日簽到
SETBIT user:sign:2026:05:01 95270000 1

// 查詢某用戶連續簽到天數
// 需要程序配合,遍歷每天的BITCOUNT

// 統計某天簽到人數
BITCOUNT user:sign:2026:05:01

假設你有5000萬用戶,一天的簽到數據只需要6.25MB內存。6.25MB!同等數據存MySQL起碼要幾百MB還不帶索引。

有人說這不是內存換時間嗎?我說你這個認知有問題,這叫用極低成本換極高收益,懂不懂?


第四件事:HyperLogLog 做 UV 統計

UV(獨立訪客)統計,每個運営同學都要看。但精確UV需要存每個用戶ID,內存開銷巨大。HyperLogLog用概率演算法,0.81%誤差的代價,換取極小的記憶體開銷:

// 記錄一次訪問
PFADD page:uv:2026:05:16 "user:session:9527"
PFADD page:uv:2026:05:16 "user:session:8866"

// 獲取UV估值
PFCOUNT page:uv:2026:05:16

// 合併多個頁面的UV(假設你要算全站UV)
PFMERGE page:uv:month:2026:05 page:uv:2026:05:01 page:uv:2026:05:02 page:uv:2026:05:03

HyperLogLog每個key只需要12KB記憶體,就能統計2的64次方那麼多用戶。12KB!這是什么概念,你用任何資料庫統計同等數量的UV,沒有幾百MB下不來。

有人問誤差不會有問題嗎?我說你一個月UV有12億6884萬,用HyperLogLog算出來12億6900萬,誤差12萬,你運營同學看得出來?看不出來是吧,那就用。


第五件事:Stream 做輕量級消息隊列

RabbitMQ、Kafka,你們是挺好,但部署維護一套消息隊列要多少精力?Redis Stream讓你在已有Redis的情況下,擁有一個堪用的消息隊列:

// 生產消息
XADD mystream:orders * order_id "ORD-20260516-001" amount 299 status "pending"

// 消費消息(阻塞方式)
XREADGROUP group1 consumer1 BLOCK 3000 STREAMS mystream:orders ">"

// 創建消費者組
XGROUP CREATE mystream:orders consumer-group 0

// 確認消息已處理
XACK mystream:orders consumer-group 1654214400000-0

有人說Stream功能不如Kafka。我說你說得對,但問題是你有沒有那麼大的量級?日均百萬消息以下,Kafka能做的Stream都能做,還不用折騰那套JVM參數調優。

之前有個小項目,日均訂單十幾萬,用Kafka浪費,用Redis Stream剛好。老闆問你消息隊列用的什麼,你說Redis,他以為你在開玩笑,其實你是認真的。


第六件事:Pipeline 批量操作省網路開銷

這個嚴格來說不算是「神奇用法」,但我發現90%的Redis用戶都不知道或者從來不用Pipeline,導致明明可以並行的操作變成了串行:

// 錯誤示範:十次網路來回
for i in range(10):
    r.get(f"key:{i}")  # 10次網路RTT

// 正確姿勢:一次網路來回
pipe = r.pipeline()
for i in range(10):
    pipe.get(f"key:{i}")
results = pipe.execute()  # 1次網路RTT

很多人不知道這個差異有多大。在本機延遲1ms的環境下,10個key的查詢,無Pipeline要10ms,有Pipeline只需要1ms。如果網路延遲更高,這個差距會更誇張。

有人說現在網路延遲很低影響不大。我說你去看看你們的監控,有多少介面耗時就耗在Redis網路來回上,你就知道Pipeline有多香了。


總結:Redis不是cache,是數據結構服務器

寫到這裡,我發現這篇文章其實就在講一句話:Redis不是cache,至少不僅僅是cache。它的五種基本數據結構(String、Hash、List、Set、Sorted Set),加上GEO、Bitmap、HyperLogLog、Stream這些高級功能,讓它成為了瑞士軍刀一樣的存在。

你用它做cache,它不會說什麼,它就是脾氣好。但如果你有點追求,試試上面的用法,你會發現:

同樣的機器、同樣的資源,有些人的系統能扛住十倍流量,有些人的系統一碰就崩。差距不在於你用了什麼框架,而在於你有沒有把工具用到極致。

蘭博基尼用來飆車是本分,用來拉貨是暴殄天物。但問題是——你連飆車都不會,怪誰?

下次有人問你Redis能用來做什麼,別再只回答「做緩存」了。建議你反問他:你想要即時排行榜、附近的人、精確UV統計、還是輕量級消息隊列?

看他一臉懵的样子,你不覺得很快樂嗎?

相关文章

为什么你的 API 总被前端骂?一线工程师的血泪经验
AI探险笔记:最近挖到了什么宝藏,也踩了什么坑
AI探险笔记:最近挖到了什么宝藏,也踩了什么坑
🦞 一键部署AI工具?别装了,你需要的只是「代部署服务」
🦞 一键部署AI工具?别装了,你需要的只是「代部署服务」
SQL优化避坑指南:我以为会索引其实不会那种

发布评论