Redis的併發競爭問題,主要是發生在併發寫競爭。考慮到redis沒有像db中的sql語句,update val = val + 10 where ...,沒法使用這種方式進行對數據的更新。html
假若有某個key(mileage), value(10),如今想把value值進行+10操做。正常邏輯下,就是先把數據key爲mileage的值讀回來,加上10,再把值給設置回去。java
若是隻有一個鏈接的狀況下,這種方式沒有問題,能夠工做得很好,但若是有兩個鏈接時,兩個鏈接同時想對還mileage進行+10操做,就可能會出現問題了。redis
例如:兩個鏈接同時對mileage進行寫操做,同時加10,最終結果咱們知道,應該爲30纔是正確。sql
考慮到一種狀況:併發
T1時刻,鏈接1將mileage讀出,目標設置的數據爲10+10 = 20。post
T2時刻,鏈接2也將數據讀出,也是爲10,目標設置爲20。性能
T3時刻,鏈接1將mileage設置爲20。url
T4時刻,鏈接2也將mileage設置爲20,則最終結果是一個錯誤值20。spa
另外假設有個A線程正在寫mileage,B線程正在讀寫mileage,當A,B同時執行的時候也可能發生併發競爭問題:操作系統
即B將mileage值讀出來的時候,A正好更新了mileage值,而後B又更新回mileage值,此時照成A的更新無效。
利用redis自帶的incr命令,具體用法看這裏http://doc.redisfans.com/string/incr.html。
利用redis的setnx實現內置的鎖。
使用樂觀鎖的方式進行解決(成本較低,非阻塞,性能較高)。如何用樂觀鎖方式進行解決?本質上是假設不會進行衝突,使用redis的命令watch進行構造條件。僞代碼以下:
watch mileage get mileage $mileage $mileage = $mileage + 10 multi set mileage $mileage exec
解釋一下:
watch這裏表示監控該key值,後面的事務是有條件的執行,若是從watch的exec語句執行時,watch的key對應的value值被修改了,則事務不會執行。
具體看Redis的事務功能詳解這篇文章裏的watch命令介紹。
這個是針對同一個服務的客戶端來的,在代碼裏要對redis操做的時候,針對同一key的資源,就先進行加鎖(java裏的synchronized或lock)。
能夠使用獨佔鎖的方式,相似操做系統的mutex機制。(網上有例子,http://blog.csdn.net/black_ox/article/details/48972085 不過實現相對複雜,成本較高)