五,redis的事務,樂觀鎖和悲觀鎖
事務是什麼,我認為事務是不成功,便成仁;
事務是訪問並可能操作各種資料項的一個數據庫操作序列,這些操作要麼全部執行,要麼全部不執行,是一個不可分割的工作單位。事務由事務開始與事務結束之間執行的全部資料庫操作組成。
但是在redis中,事務中是不存在原子性的。
一,redis是一群命令的組合,每個命令在一條佇列中,順序執行;
一個事務中所有的命令都會被序列化,在執行任務的時候,順序執行。
二,redis事務沒有隔離級別的概念;
三,redis的三個階段
1)開始事務;
2)命令進入佇列;
3)執行命令。
四,redis的相關命令
1)multi 開啟事務;
2)watch key1 ..... keyn,監視一個或者多個key,如果在事務執行之前,被監視的key被其他命令改動,則事務被打斷。
3)exec:執行所有命令;
4)unwach:取消對所有key的監控;
5)discard:取消事務,放棄事務塊中的所有命令;
五,指令例項
1)事務的基本過程
開啟事務,命令進入序列中,執行命令;
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set name laoli
QUEUED
127.0.0.1:6379> set sex boy
QUEUED
127.0.0.1:6379> set age 30
QUEUED
127.0.0.1:6379> keys *
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) OK
4) 1) "score_ch"
2) "sex"
3) "name"
4) "age"
2)在事務中,入隊的命令中其中有一個命令有錯誤,事務中所有的命令是不執行的;
3)在事務中,入隊的命令是存在語法性的錯誤,在執行其他命令時候,其他的命令是可以正常執行的,錯誤的命令會丟擲異常;
六,悲觀鎖和樂觀鎖
在事務中,事務是有原子性的,事務是可以回滾的;
但是在redis中,事務是非原子性的,如何讓事務有回滾的能力,需要藉助wath命令去監控命令去實現。
1)樂觀鎖:開啟事務前,設定對資料的監聽,EXEC時,如果發生資料發生過修改,事務會自動取消(DISCARD)
認為什麼事情,都不會出現問題,都是樂觀的,不會上鎖;
監控money:正常執行;
127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 20
QUEUED
127.0.0.1:6379> incrby out 20
QUEUED
127.0.0.1:6379> exec
1) (integer) 80
2) (integer) 20
如果在監視的money中,發生了變化,則事務會自動取消
新開一個執行緒,新增讓money變成1000
127.0.0.1:6379> get money "80" 127.0.0.1:6379> set money 1000 OK 127.0.0.1:6379>
在開執行緒之前,首先watch money,然後開始事務,然後新開一個執行緒,讓money變成1000,就是執行上面的程式碼;然後money減去10元,out新增10元,exec後,出現nil
127.0.0.1:6379> get money "80" 127.0.0.1:6379> watch money OK 127.0.0.1:6379> multi OK 127.0.0.1:6379> decrby money 10 QUEUED 127.0.0.1:6379> incrby out 10 QUEUED 127.0.0.1:6379> exec (nil)
上面的案例可以看出,樂觀鎖在監控到元素髮生變化是,取消操作;
解決辦法是,放棄監視,重新執行;
127.0.0.1:6379> UNWATCH OK 127.0.0.1:6379> watch money OK 127.0.0.1:6379> multi OK 127.0.0.1:6379> decrby money 10 QUEUED 127.0.0.1:6379> incrby out 10 QUEUED 127.0.0.1:6379> exec 1) (integer) 990 2) (integer) 30
2)悲觀鎖:
認為任何事情,都會出現問題,都是悲觀的,很消耗效能;
我們在sql中使用的for update,應用程式的層面手工實現資料加鎖保護操作