解決並發問題的一般思路及使用redis實現秒殺


解決思路
  從讀到寫這段時間的數據不一致問題,根源在於用戶並行(個人認為並發是時間概念,並行是空間概念),
要解決這個問題,需要讓用戶串行,單個用戶原子性。鎖 說它可以做到。
  鎖只有一個目的,就是把並行變為串行,但是上鎖的方式 五花八門。
  1. Java應用內存鎖
    Java中自帶很多內存鎖,synchronize,各種Lock,但是優惠券服務多機部署,內存鎖無法滿足需求;
  2. Mysql數據庫鎖
    優惠券服務使用MySql(一個寫節點),innodb存儲引擎,innodb 支持 行鎖。
    利用innodb的行鎖機制,可以使用兩種方式實現用戶領券的原子性:
    第一種,讀取之前上鎖, 更新之后解鎖
      select  ... from table where ... for update;
      update table set ....
      優點: 簡單明了; 缺點: select 和 update 之間處理 出異常或應用異常終止 會產生死鎖。
    第二中,利用update 鎖行機制,加上where 條件 判斷數據,也是讀取前上鎖,更新后解鎖。
      update table set .... where ....
      優點:簡單明了; 缺點: 效率不高
    另外更新操作直接命中數據庫會對數據庫產生很大的壓力,所以數據庫鎖無法滿足搶券業務;
  3. Redis分布式內存鎖
    優惠券服務使用單節點Redis,Redis 支持setnx命令。
    利用setnx命令,可以在應用中自建鎖及維護鎖的生命周期。
    基本思路是領券前將優惠券的key通過 setnx 命令寫進 redis,成功則之后便執行后續的三次讀取 比較 和更新,
  最后 del 命令刪除優惠券的key。
    優點:邏輯簡單,實現簡單,total_got,user_got,user_today_got 三個值 存哪里不受任何限制。
    缺點:不太可靠,setnx 成功后,應用出現異常,沒有執行最后的del , 會產生死鎖;也可以在 setnx 后再
  設置一個過期時間,是的,這是一個辦法,只需要保證過期時間大於 接口的最大執行時間。
    另外,也可以使用 官方推薦的 分布式Redis鎖 開源實現 Redisson。

以redis為例:

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM