悲觀鎖 vs 樂觀鎖 vs Redis

2022-03-16 16:22:10 字數 1455 閱讀 4858

企業面對高併發場景採用的方案.

比如 產品搶購高併發時的超發現象.

1 悲觀鎖

悲觀鎖 需要資料庫本身提供支援(oracle和mysql都是支援的).

實現細節:

當前 資料庫事務 讀取到產品後, 就將目標資料直接鎖定(select ... for update), 不允許別的執行緒進行讀寫操作, 知道 當前資料庫事務完成自動釋放鎖.

悲觀鎖中, 資源只能被乙個事務鎖持有, 所以也被稱為 獨佔鎖 or 排它鎖.

悲觀鎖的優點是實現簡單好理解, 缺點是過多的等待和響應的事務切換導致效能問題.

為提高執行效率, 可以採用 樂觀鎖.

2 樂觀鎖

樂觀鎖 是一種 不使用資料庫鎖 和 不阻塞執行緒併發 的方案.

著名的 cas(compare and swap): 執行緒在修改目標資料時, 會將目標資料的當前狀態和舊狀態進行比較(compare), 如果狀態一直, 就可以認為 資料木有被修改過, 否則就認為資料已經不同步了, 當前計算作廢, 不做任何修改操作(回滾).

cas方案卻會引發 aba問題, 就是共享值回退導致資料的不一致問題, 有點像髒讀.

採用 帶版本號(version)的樂觀鎖方案, 再配合cas, 就可以解決 aba問題了.

實現細節:

給產品表新增 version欄位, 只要操作過程中有修改產品狀態(比如減少庫存), 無論是業務正常 回退 還是異常, 版本號只增不減. 即

update t_product set stock=stock-#, version=version+1

where id=# and version=#

樂觀鎖沒有獨佔資源和阻塞任何執行緒, 所以樂觀鎖也稱為 非獨佔鎖 or 無阻塞鎖.

在實際使用樂觀鎖時, 會發現執行緒的業務失敗率會很高, 針對這點可以對 樂觀鎖 引入重入機制. 也就是一旦業務失敗, 不是立即結束請求, 而是重新做一次樂觀鎖流程, 可限制重入時間or重入次數.

樂觀鎖優點是不獨佔不阻塞, 缺點是實現相對複雜.

3 redis

有些企業已經開始使用 nosql 來處理高併發問題, 代表就是 redis(記憶體資料庫).

首先, redis 是記憶體資料庫, 所以效能是沒的說的. 其次, redis lua 在 redis 的執行中是具備原子性的, 所以不會傳送超發現象.

兩步設計:

1) 使用 redis 響應高併發使用者請求

即用 redis 代替原來的磁碟資料庫 讀寫, 保證效能和資料一致性.

2) 定時持久化 redis 資料

記憶體資料儲存是不穩定的, 我們需要及時將儲存在記憶體中的資料持久化到磁碟資料庫中.

使用 redis 效率要比悲觀鎖和樂觀鎖機制快上數倍, 但是千萬記住 redis 的儲存基於記憶體, 如果操作不當容易引發資料的丟失, 所以使用 redis 時建議使用獨立的 redis 伺服器, 而且要做好備份和容災等手段.

參考:《深入淺出 spring boot 2.x>> 楊開振

悲觀鎖 VS 樂觀鎖

1 資料庫的隔離級別 1.read uncommited 未提交讀 沒有提交就可以讀取到資料 發出了insert,但沒有commit就可以讀取到 2.read commited 提交讀 只有提交後才可以讀 3.repeatable read 可重複讀 mysql預設級別,必須提交才能看到,讀取資料是...

樂觀鎖vs悲觀鎖

為什麼需要鎖 併發控制 在併發的環境中,會存在多個使用者同時更新同一條資料,這時就會產生衝突。衝突結果 因此為了解決上述問題,引入了併發控制機制。樂觀鎖 樂觀併發控制 和悲觀鎖 悲觀併發控制 是併發控制的主要手段,其實不僅關係型資料庫中有樂觀鎖和悲觀鎖的概念,像redis,memcached等都有類...

悲觀鎖樂觀鎖

1 悲觀鎖,正如其名,它指的是對資料被外界 包括本系統當前的其他事務,以及來自外部系統的事務處理 修改持保守態度,因此,在整個資料處理過程中,將資料處於鎖定狀態。悲觀鎖的實現,往往依靠資料庫提供的鎖機制 也只有資料庫層提供的鎖機制才能真正保證資料訪問的排他性,否則,即使在本系統中實現了加鎖機制,也無...