最近專案中需要使用到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...