redis應該中如何解決多寫的競爭問題

2021-07-28 04:07:18 字數 1270 閱讀 2805

最近專案中需要使用到redis進行資料快取及讀寫操作。遇到了一些問題並總結到這裡。

考慮到redis沒有像db中的sql語句,update val = val + 10 where ...,無法使用這種方式進行對資料的更新。

假如有某個key = "price",  value值為10,現在想把value值進行+10操作。正常邏輯下,就是先把資料key為price的值讀回來,加上10,再把值給設定回去。如果只有乙個連線的情況下,這種方式沒有問題,可以工作得很好,但如果有兩個連線時,兩個連線同時想對還price進行+10操作,就可能會出現問題了。

例如:兩個連線同時對price進行寫操作,同時加10,最終結果我們知道,應該為30才是正確。

考慮到一種情況:

t1時刻,連線1將price讀出,目標設定的資料為10+10 = 20。

t2時刻,連線2也將資料讀出,也是為10,目標設定為20。

t3時刻,連線1將price設定為20。

t4時刻,連線2也將price設定為20,則最終結果是乙個錯誤值20。

如何解決?

方案一:可以使用獨佔鎖的方式,類似作業系統的mutex機制。(網上有例子, 不過實現相對複雜,成本較高)

方案二:使用樂觀鎖的方式進行解決(成本較低,非阻塞,效能較高)

如何用樂觀鎖方式進行解決?

本質上是假設不會進行衝突,使用redis的命令watch進行構造條件。偽**如下:

watch price

get price $price

$price = $price + 10

multi

set price $price

exec

解釋一下:

watch這裡表示監控該key值,後面的事務是有條件的執行,如果從watch的exec語句執行時,watch的key對應的value值被修改了,則事務不會執行。

同樣考慮剛剛的場景,

t1時刻,連線1對price進行watch,讀出price值為10,目標計算為20;

t2時刻,連線2對price進行watch,讀出price值為10,目標計算為20;

t3時刻,連線2將目標值為20寫到redis中,執行事務,事務返回成功。

t4時刻,連線1也對price進行寫操作,執行事務時,由於之前已經watch了price,price在t1至t4之間已經被修改過了,所以事務執行失敗。

綜上,該樂觀鎖機制可以簡單明瞭的解決了寫衝突的問題。

又問:如果多個寫操作同時過來,100個寫操作同時watch,則最終只會有乙個成功,99個執行失敗,何解?表急,請聽下回分解。

如何解決Redis中的key過期問題

最近我們在redis集群中發現了乙個有趣的問題。在花費大量時間進行除錯和測試後,通過更改key過期,我們可以將某些集群中的redis記憶體使用量減少25 twitter內部執行著多個快取服務。其中乙個是由redis實現的。我們的redis集群中儲存了一些twitter重要的用例資料,例如展示和參與度...

SQL Server的「警報」問題應該如何解決

問 sql server的警報問題應該如何解決?檢查你是否使用了最新的sql server service pack。因為在最新的sql server service pack中已經修補了很多sql server使用警告 alerts 的漏洞。應該確保在你的系統中已經安裝了最新的sql server...

jQuery中如何解決多庫衝突問題

方法一 使用noconflict 捨棄 用jquery代替 jquery.noconflict 方法二 自定義變數 捨棄 新定義乙個 y變數來代替 var y jquery.noconflict 方法三 使用語句塊 在區域性裡面使用 jquery.noconflict jquery document...