基於redis的樂觀鎖實踐

redis真是一個分佈式應用場景下的好東西,對於咱們的應用設計,功勞大大的!redis

 

今天要研究的是基於redis的事務機制以及watch指令(CAS)實現樂觀鎖的過程。ssh

所謂樂觀鎖,就是利用版本號比較機制,只是在讀數據的時候,將讀到的數據的版本號一塊兒讀出來,當對數據的操做結束後,準備寫數據的時候,再進行一次數據版本號的比較,若版本號沒有變化,即認爲數據是一致的,沒有更改,能夠直接寫入,若版本號有變化,則認爲數據被更新,不能寫入,防止髒寫。分佈式

 

下面,看看如何基於redis實現樂觀鎖。spa

 

首先,看看redis的事務,涉及到的指令,主要有multi,exec,discard。而實現樂觀鎖的指令,在事務基礎上,主要是watch指令,以及unwatch指令,unwatch一般能夠不用!設計

 

案例1:redis的純事務code

下面是ssh窗口1裏面的操做:blog

127.0.0.1:6379> set hello 1
OK
127.0.0.1:6379> get hello
"1"
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr hello
QUEUED
127.0.0.1:6379> incr hello                 #這一步執行完畢後,去另一個窗口(ssh窗口2),對hello這個key作incr操做,將hello對應的值變成2。完成後,繼續後面的exec指令
QUEUED
127.0.0.1:6379> exec
1) (integer) 3 #注意,這時hello的值是3了,前面執行get hello指令時,值是1喲,說明這個值在其餘地方被修改過,這裏的其餘地方,就是指前面提到的,在另一個鏈接窗口裏面執行的。 2) (integer) 4
127.0.0.1:6379>

這個情景下,multi和exec之間的指令,依然是能夠執行的。生命週期

 

下面的操做,就是在ssh窗口2裏面的操做:事務

127.0.0.1:6379> 
127.0.0.1:6379> get hello
"1"
127.0.0.1:6379> incr hello
(integer) 2
127.0.0.1:6379>

 

案例2: 利用watch指令,基於CAS機制,簡單的樂觀鎖get

下面是ssh窗口1裏面的操做:

127.0.0.1:6379> watch hello
OK
127.0.0.1:6379> get hello
"4"
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr hello
QUEUED
127.0.0.1:6379> incr hello                #這一步執行完畢後,去另一個窗口(ssh窗口2),對hello這個key作incr操做,將其值變成5。完成後,繼續後面的exec指令
QUEUED
127.0.0.1:6379> exec
(nil)                                     #注意,這是exec執行後返回的是nil,表示事務提交執行失敗 127.0.0.1:6379> 
127.0.0.1:6379> get hello                 #這個時候,查看hello對應的值,就是在另一個窗口(ssh窗口2)執行incr後的值 "5"

 

下面是ssh窗口2裏面的操做:

127.0.0.1:6379> incr hello
(integer) 5
127.0.0.1:6379> 

 

案例3:watch指令在一次事務執行完畢後,即結束其生命週期

下面是ssh窗口1裏面的操做:

127.0.0.1:6379> multi                     #接着上面案例2後,再也不輸入watch hello這個指令,直接啓動事務
OK
127.0.0.1:6379> incr hello
QUEUED
127.0.0.1:6379> incr hello                #這一步執行完畢後,就在另一個窗口(ssh窗口2),執行incr hello,將hello的值變成6。
QUEUED
127.0.0.1:6379> exec                      #另一個窗口(ssh窗口2)裏面的操做結束後,繼續來這個窗口執行該指令,依然完成了上面的兩個incr hello的操做。 1) (integer) 7
2) (integer) 8
127.0.0.1:6379>

 

下面是ssh窗口2裏面的操做:

127.0.0.1:6379> incr hello
(integer) 6
127.0.0.1:6379>

 

上述3個案例的操做,指令其實很是的少,兩個窗口的指令全集,截圖以下:

在另一個窗口(ssh窗口2)中的操做:

 

經過這個簡單的例子,基於redis的樂觀鎖,能夠得出一個結論:

1. 樂觀鎖的實現,必須基於WATCH,而後利用redis的事務。

2. WATCH生命週期,只是和事務關聯的,一個事務執行完畢,相應的watch的生命週期即結束。

相關文章
相關標籤/搜索