絕命一問:秒殺Redis分段鎖,如何設計?

文章很長,且持續更新,建議收藏起來,慢慢讀!瘋狂創客圈總目錄 博客園版 爲您奉上珍貴的學習資源 :

免費贈送 :《尼恩Java面試寶典》 持續更新+ 史上最全 + 面試必備 2000頁+ 面試必備 + 大廠必備 +漲薪必備
免費贈送 :《尼恩技術聖經+高併發系列PDF》 ,幫你 實現技術自由,完成職業升級, 薪酬猛漲!加尼恩免費領
免費贈送 經典圖書:《Java高併發核心編程(卷1)加強版》 面試必備 + 大廠必備 +漲薪必備 加尼恩免費領
免費贈送 經典圖書:《Java高併發核心編程(卷2)加強版》 面試必備 + 大廠必備 +漲薪必備 加尼恩免費領
免費贈送 經典圖書:《Java高併發核心編程(卷3)加強版》 面試必備 + 大廠必備 +漲薪必備 加尼恩免費領

免費贈送 資源寶庫: Java 必備 百度網盤資源大合集 價值>10000元 加尼恩領取


絕命一問:秒殺Redis分段鎖,如何設計?

尼恩說在前面

秒殺,是一個非常常見的高併發面試題,很多面試官也非常熟悉,上來就讓面試者設計一個秒殺系統。

在40歲老架構師 尼恩的讀者交流羣(50+)中,最近有小夥伴拿到了一線互聯網企業如得物、阿里、滴滴、極兔、有贊、shein 希音、百度、網易的面試資格,遇到很多很重要的面試題:

分佈式鎖,如何實現高併發?

小夥伴 沒有回答好,導致面試掛了。

小夥伴面試完了之後,來求助尼恩:如何才能回答得很漂亮,才能 讓面試官刮目相看、口水直流。所以,尼恩給大家做一下系統化、體系化的梳理,使得大家內力猛增,可以充分展示一下大家雄厚的 “技術肌肉”,讓面試官愛到 “不能自已、口水直流”,然後實現 ”offer自由”

當然,這道面試題,以及參考答案,也會收入咱們的 《尼恩Java面試寶典》V173版本PDF集羣,供後面的小夥伴參考,提升大家的 3高 架構、設計、開發水平。

注:本文以 PDF 持續更新,最新尼恩 架構筆記、面試題 的PDF文件,請到公衆號【技術自由圈】獲取。

本文目錄

問題場景:熱點庫存扣減問題

秒殺場景,有一個難度的問題:熱點庫存扣減問題。

  • 既要保證不發生超賣

  • 又要保證高併發

如何解決這個高難度的問題呢? 答案就是使用redis 分段鎖。

首先說說什麼是分佈式鎖,普通分佈式鎖的不足

比如說在一個分佈式系統中,存在客戶端多個用戶,同時通過多個業務微服務,發起一個數據修改。

如果沒有分佈式鎖機制保證,在那多臺機器上的多個服務可能進行併發修改操作,導致數據修改的不一致,出現髒讀髒寫,這就會造成問題。

而分佈式鎖機制就是爲了解決類似這類問題,保證多個服務之間互斥的訪問共享資源,如果一個服務搶佔了分佈式鎖,其他服務沒獲取到鎖,就不進行後續操作。

上圖中,客戶端1的服務搶佔了分佈式鎖,可以去扣減庫存。

其他服務沒獲取到分佈式鎖,就不進行後續操作。

什麼是分佈式鎖?

  • 當在分佈式模型下,數據只有一份(或有限制),此時需要利用鎖的技術控制某一時刻修改數據的進程數。
  • 用一個狀態值表示鎖,對鎖的佔用和釋放通過狀態值來標識。

分佈式鎖的條件:

  • 互斥性。在任意時刻,只有一個客戶端能持有鎖。
  • 不會發生死鎖。即使有一個客戶端在持有鎖的期間崩潰而沒有主動解鎖,也能保證後續其他客戶端能加鎖。
  • 具有容錯性。只要大部分的 Redis 節點正常運行,客戶端就可以加鎖和解鎖。
  • 解鈴還須繫鈴人。加鎖和解鎖必須是同一個客戶端,客戶端自己不能把別人加的鎖給解了。

普通的分佈式鎖的如何實現?

分佈式鎖的實現由很多種,文件鎖、數據庫、redis等等,比較多;分佈式鎖常見的多種實現方式:

  1. 數據庫悲觀鎖、
  2. 數據庫樂觀鎖;
  3. 基於Redis的分佈式鎖;
  4. 基於ZooKeeper的分佈式鎖。

在實踐中,還是redis做分佈式鎖性能會高一些

尼恩提示:基於ZooKeeper的分佈式鎖,請參見尼恩面試寶典 專題15.

尼恩提示:基於redis 的分佈式鎖,請參見尼恩面試寶典 專題15.

普通分佈式鎖的性能問題

分佈式鎖一旦加了之後,對同一個商品的下單請求,會導致所有下單操作,都必須對同一個商品key加分佈式鎖。

假設某個場景,一個商品1分鐘6000訂單,每秒的 600個下單操作,

假設加鎖之後,釋放鎖之前,查庫存 -> 創建訂單 -> 扣減庫存,每個IO操作100ms,大概300毫秒。

具體如下圖:

可以再進行一下優化,將 創建訂單 + 扣減庫存 併發執行,將兩個100ms 減少爲一個100ms,這既是空間換時間的思想,大概200毫秒。

將 創建訂單 + 扣減庫存 批量執行,減少一次IO,也是大概200毫秒。也就是單個商品而言,只有 5 QPS.

假設一個商品sku的數量是10000,10秒內秒殺完,也就是單個商品而言,需要 單商品 100 QPS,如何應對一個商品的 100qps秒殺。

甚至,如果單商品需要 1000qps秒殺呢?

答案是,使用 分段加鎖。

分段加鎖的思想來源

分段加鎖的思想來源與基礎知識。在尼恩的 《Java 高併發核心編程 卷2》 介紹了 JUC的 LongAdder 和 ConcurrentHashMap的源碼和底層原理,他們提升性能的辦法是: 分段加鎖,空間換時間

尼恩經常在技術自由圈社羣裏邊,對小夥伴們強調 基礎知識的重要性,反覆強調, 《Java 高併發三部曲》 一定要多刷,最好刷三遍。

尤其是 LongAdder 的實現思想,可以用於 Redis分佈式鎖 作爲性能提升的參考設計方案,將 Redis分佈式鎖 優化爲 Redis分段鎖。

建議大家提前看看LongAdder ,有關LongAdder 的系統化學習,請參見 《Java 高併發核心編程 卷2》

優化之後:使用Redis分段鎖提升秒殺的併發性能

回到前面的場景:

假設一個商品1分鐘6000訂單,每秒的 600個下單操作,

假設加鎖之後,釋放鎖之前,查庫存 -> 創建訂單 -> 扣減庫存,經過優化,每個IO操作100ms,大概200毫秒,一秒鐘5個訂單。

如何提高性能呢? 空間換時間

爲了達到每秒600個訂單,可以將鎖分成 600 /5 =120 個段,反過來, 每個段1秒可以操作5次, 120個段,合起來,及時每秒操作600次。

進行搶奪鎖的,如果申請到一個具體的段呢?

  • 隨機路由法
  • hash取模法

如果是用隨機路由算法,可以將請求隨機到一個分段, 如果不行,就輪詢下一個分段,具體的流程,大致如下:

這個是一個理論的時間預估,沒有扣除 嘗試下一個分段的 時間, 另外,實際上的性能, 會比理論上差,從咱們實操案例的測試結果,也可以證明這點。

隨機路由法的問題:

不同分端之間,可能庫存消耗不均,導致部分用戶無法扣減庫存,反覆進行重試,拖慢系統性能。

如何進一步優化: hash取模法。

第二次優化之後:使用hash取模法,減少庫存消耗不均和無效重試

由於秒殺場景的分佈式鎖,實際上是爲了防止超賣, 和庫存是強相關的。

所以,可以結合庫存,把秒殺的分佈式鎖進行改進。

第一步: 把redis 的分段方式進行演進,額外增加一個總庫存分段鎖,用於分配存儲剩餘的總庫存。採用多批次少量分配的思路,通過定時任務,從總庫存向分段庫存中遷移庫存。

第二步:使用hash取模法,把用戶路由到某一個分段,如果分段裏邊的庫存耗光了,就去訪問剩餘的總庫存。

庫存動態遷移

爲了防止分段多庫存耗光,大家都去搶佔總庫存鎖。

採用多批次少量分配的思路,通過定時任務,從總庫存向分段庫存中遷移庫存。

至此, hash取模法的分段鎖設計方案,已經完美實現。

並且尼恩社羣中,已經有小夥伴在生產上完成落地。 以上方案,也是尼恩在給他一對一改簡歷的時候,分享給尼恩的。

當然,如果大家簡歷挖掘不出來亮點,也可以找尼恩挖掘, 保證簡歷金光閃閃、改天換地。

說在最後

秒殺相關的面試題,是非常常見的面試題。

以上的內容,如果大家能對答如流,如數家珍,基本上 面試官會被你 震驚到、吸引到。最終,讓面試官愛到 “不能自已、口水直流”。offer, 也就來了。

在面試之前,建議大家系統化的刷一波 5000頁《尼恩Java面試寶典》V173,在刷題過程中,如果有啥問題,大家可以來 找 40歲老架構師尼恩交流。

另外,如果沒有面試機會,可以找尼恩來幫扶、領路。

尼恩已經指導了大量的就業困難的小夥伴上岸,前段時間,幫助一個40歲+就業困難小夥伴拿到了一個年薪100W的offer,小夥伴實現了 逆天改命 。

技術自由的實現路徑:

實現你的 架構自由:

喫透8圖1模板,人人可以做架構

10Wqps評論中臺,如何架構?B站是這麼做的!!!

阿里二面:千萬級、億級數據,如何性能優化? 教科書級 答案來了

峯值21WQps、億級DAU,小遊戲《羊了個羊》是怎麼架構的?

100億級訂單怎麼調度,來一個大廠的極品方案

2個大廠 100億級 超大流量 紅包 架構方案

… 更多架構文章,正在添加中

實現你的 響應式 自由:

響應式聖經:10W字,實現Spring響應式編程自由

這是老版本 《Flux、Mono、Reactor 實戰(史上最全)

實現你的 spring cloud 自由:

Spring cloud Alibaba 學習聖經》 PDF

分庫分表 Sharding-JDBC 底層原理、核心實戰(史上最全)

一文搞定:SpringBoot、SLF4j、Log4j、Logback、Netty之間混亂關係(史上最全)

實現你的 linux 自由:

Linux命令大全:2W多字,一次實現Linux自由

實現你的 網絡 自由:

TCP協議詳解 (史上最全)

網絡三張表:ARP表, MAC表, 路由表,實現你的網絡自由!!

實現你的 分佈式鎖 自由:

Redis分佈式鎖(圖解 - 秒懂 - 史上最全)

Zookeeper 分佈式鎖 - 圖解 - 秒懂

實現你的 王者組件 自由:

隊列之王: Disruptor 原理、架構、源碼 一文穿透

緩存之王:Caffeine 源碼、架構、原理(史上最全,10W字 超級長文)

緩存之王:Caffeine 的使用(史上最全)

Java Agent 探針、字節碼增強 ByteBuddy(史上最全)

實現你的 面試題 自由:

4800頁《尼恩Java面試寶典 》 40個專題

免費獲取11個技術聖經PDF:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章