基於redis的樂觀鎖實踐


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

 

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

所謂樂觀鎖,就是利用版本號比較機制,只是在讀數據的時候,將讀到的數據的版本號一起讀出來,當對數據的操作結束后,准備寫數據的時候,再進行一次數據版本號的比較,若版本號沒有變化,即認為數據是一致的,沒有更改,可以直接寫入,若版本號有變化,則認為數據被更新,不能寫入,防止臟寫。

 

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

 

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

 

案例1:redis的純事務

下面是ssh窗口1里面的操作:

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機制,簡單的樂觀鎖

下面是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的生命周期即結束。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM