一、樂觀鎖
先表明態度,樂觀鎖並不是乙個好的實現方式!
在mysql中,我們一般通過給資料表額外建乙個version欄位,讀的時候讀出verson,更新的時候 v2 = versin+1,語句為
update *** set ***=***, version = version + 1 where id = *** and version < v2;
只要有人在我前面更新了,我就會更新失敗。然後直接響應給客戶端錯誤嗎?顯然不能,在大併發的情況下,難道要客戶一次次的手動提交嗎?所以,我們只能替使用者去迴圈嘗試更新,讓使用者多等待一會,當然要設定迴圈次數或者時間。而且,雖然更新失敗了,但是依然操作了資料庫,而且是迴圈操作,更加使脆弱的mysql雪上加霜。那麼,樂觀鎖能保證資料安全嗎?可以的,因為在更新version的時候使用的是自增而不是賦值。
二、redis事務
雖然redis是單執行緒的,但是使用事務的時候,事務塊會被放入事務佇列中,直到呼叫exec命令,此時事務塊作為乙個原子插入到主執行佇列中,雖然在執行事務塊的時候是單執行緒的不存在併發,但是在構成事務塊的過程中主線程同時執行著其他命令,是並行的,所以總的來看,事務不能保證資料的安全性。另外,redis事務不具備一致性,沒有回滾機制。
示例1:
multi
set name rao
set age 12
set score 100
exec
示例2:
multi
set name rao
set age 13
incr name
exec
get age
報錯但沒有回滾處理!!!!
exec返回以個陣列,就是所有命令依次的結果。
當在構造事務的過程中想要取消事務,可使用discard命令
三、redis事務加樂觀鎖
既然存在並行的情況,那麼資料安全就沒法保障,所以,必須加個鎖來保證事務過程中key的值不被改變。
watch:監視乙個(或多個) key的版本變化 ,如果在事務執行之前這個(或這些) key 被其他命令所改動,那麼事務將被打斷。
在執行exec的時候,redis會去檢查你watch的key。如果版本發生變化,就不執行。
如果watch了乙個有過期時間的,且在exec之前剛好過期了,那麼事務依然會執行。
當執行exec後,就會unwatch這些key;當客戶端斷開,也會unwatch這些key。
示例1:
watch name age score
multi
set name rao
set age 12
set score 100
exec
注意,事務和樂觀鎖是一起存在的,當你想要用樂觀鎖的時候,也要使用事務。
四、存在的問題
redis事務沒有回滾機制是個硬傷,
Redis 事務(悲觀鎖 樂觀鎖)
1 定義 redis事務是乙個單獨的隔離操作 事務中所有的命令都會被序列化 按照順序執行 事務在執行過程中不會被其他客戶端傳送來的命令請求打斷 2 作用 串聯多個命令防止別的命令插隊 multi 輸入開始命令 exec 執行命令 discard 放棄組隊 刪除掉 3 注意事項 1 multi 命令不...
Redis 樂觀鎖控制事務
redis對事務的支援比較簡單。redis只能保證乙個客戶端發起的事務命令可以執行,中間不會插入其他事務。因為redis是單執行緒的,所以做到上面這點很容易。一般redis接受到客戶端的命令後會立即執行,但是如果客戶端發起multi命令,redis不會立即執行,而是讓當前連線進入事務上下文,把命令放...
Redis樂觀鎖控制事務
redis對事務的支援比較簡單。redis只能保證乙個客戶端發起的事務命令可以執行,中間不會插入其他事務。但 redis集群不支援事務。因為redis是單執行緒的,所以做到上面這點很容易。一般redis接受到客戶端的命令後會立即執行,但是如果客戶端發起multi命令,redis不會立即執行,而是讓當...