Redis 秒殺入門|從搶票轉圈圈開始
你一定經歷過這個瞬間:倒數三秒、頁面狂閃、按下去之後畫面轉圈圈——然後彈出「已售完」。
你心裡罵的是黃牛,但其實有一半機率,是資料庫在那零點幾秒裡,正忙著排隊「鎖」一筆庫存,鎖到你前面那個人先搶走了。
今天要介紹的 Redis,就是打算讓那個轉圈圈,變成不會轉的東西。
「已售完」其實有兩種
畫面上寫的都是同一句話,背後卻可能是完全不同的故事。
第一種:票真的沒了。
庫存數字已經歸零,你晚了一步,系統老實告訴你沒貨。這時候罵黃牛(或罵手速)說得過去。
第二種:系統還在排隊算帳。
票可能還在,但資料庫正鎖著那一列「剩餘數量」,你的請求卡在人潮後面。等輪到你,前面的人已經扣完——於是你看到的仍是「已售完」。你怪的是黃牛,受傷的其實是鎖與排隊。
兩種結果長一樣,原因不一樣。
Redis 上場要對付的,主要是第二種:讓「查庫存、改庫存」這一步快到幾乎不用排隊,也盡量別在混亂中算錯數字。
把「排隊算帳」攤開來看
你按下「搶購」之後,請求大概會走這一條路:
①② 通常很快;真正塞車的是 ③ 鎖庫存 → ④ 改數字。
成千上萬人同時要改同一格「還剩幾張」,資料庫只好排成一列——你的轉圈圈,常常就是卡在這段單車道收費站。
為什麼傳統帳本特別容易在這裡塞車
傳統關聯式資料庫很擅長「把帳記清楚、關連查得漂亮」。但秒殺要的不是漂亮報表,是同一毫秒內,成千上萬人改同一個數字。
可以想成收費站只開一條車道:
塞車通常疊了兩件事:
- 同一格熱點 — 全部請求都要動「商品 A 還剩幾件」這一格;系統為了不讓兩個人同時改到亂掉,常會讓請求排隊(鎖)。
- 帳本在較慢的地方 — 很多傳統設計把權威數字放在磁碟導向的資料庫;人潮一湧,鎖排隊再加上讀寫開銷,③→④ 就變成整條路最窄的口。
所以問題常常不是「資料庫壞了」,而是:秒殺這種極端熱點,跟「大家共享一本謹慎的倉庫帳本」本來就不合拍。
Redis 是什麼?
一句話:Redis 是把資料放在記憶體裡的 key-value 引擎。
- 記憶體:讀寫路徑短,適合應付瞬間湧進來的請求。
- key-value:你給一個名字(key),它記一筆內容(value)。例如 key 是
product:A:stock,value 是50。
它常被拿來當快取(把熱門資料暫放近一點),但在秒殺裡,我們更在意另一種用法:讓它當第一線的庫存記帳本——先在很快的地方改數字,別讓人潮全擠進那本謹慎的倉庫帳。
記住這張對比就夠了:秒殺當下,我們要的是櫃檯那疊便利貼,不是跑進倉庫翻厚帳本。
又快,還有一件事:不能算錯
便利貼解決的是「轉圈圈」——讓 ③→④ 變快。
但秒殺還有第二條底線:剩 1 件,不能賣出 2 件。
想像兩個人幾乎同時走到櫃檯:
快,只代表排隊變短;正確,代表改數字這一步不能拆成「我看過了」和「我改了」中間還能被人插隊。
Redis 站在熱路徑的哪裡?
回到稍早那條五步路——這次把第一線標清楚:
瀏覽器與 API 負責「說話」;改那格庫存數字的工作,交給 Redis。
完整訂單、排行榜、後台列表——可以再往後做。第一篇只要建立這個畫面就夠。
本篇小结
📝 TL;DR:搶票轉圈圈,常常是系統在排隊改同一格庫存。Redis 是記憶體裡的 key-value,適合當秒殺第一線記帳本;但快之外還要防超賣——「先讀再減」會出事。
你帶走三件事:
- 兩種「已售完」 — 真的沒了,或還在排隊算帳。
- Redis 心智模型 — 櫃檯便利貼(記憶體 key-value),不是要取代整間倉庫。
- 兩個目標 — 又快,又不能算錯;正確性的做法下一篇再拆。
下一篇會接著講:怎樣讓「查+扣」變成不能插隊的一次動作,以及為什麼還需要一條「削峰」的水路,把瞬間寫入壓力攤平。
實作可對照:lucashsu95/redis-seckill。