Optimistic locking using check-and-set(樂觀鎖)
樂觀鎖介紹:
watch指令在redis事物中提供了CAS的行爲。爲了檢測被watch的keys在是否有多個clients同時改變引發衝突,這些keys將會被監控。若是至少有一個被監控的key在執行exec命令前被修改,整個事物將會回滾,不執行任何動做,從而保證原子性操做,而且執行exec會獲得null的回覆。redis
樂觀鎖工做機制:
watch 命令會監視給定的每個key,當exec時若是監視的任一個key自從調用watch後發生過變化,則整個事務會回滾,不執行任何動做。注意watch的key是對整個鏈接有效的,事務也同樣。若是鏈接斷開,監視和事務都會被自動清除。固然exec,discard,unwatch命令,及客戶端鏈接關閉都會清除鏈接中的全部監視。還有,若是watch一個不穩定(有生命週期)的key而且此key天然過時,exec仍然會執行事務隊列的指令。數據庫
客戶端1 | 客戶端2 | 說明 |
redis 127.0.0.1:6379> get age "10" redis 127.0.0.1:6379> get name "zhangsan" |
redis 127.0.0.1:6379> get age "10" redis 127.0.0.1:6379> get name "zhangsan" |
數據庫中兩客戶端登陸,及鍵初始值。 |
redis 127.0.0.1:6379> multi OK redis 127.0.0.1:6379> incr age QUEUED redis 127.0.0.1:6379> set name lisi QUEUED |
此時,客戶端1開啓事務,並提交隊列命令: 1.想要將當前age自增+1運算; 2.將name值改成lisi |
|
redis 127.0.0.1:6379> incr age (integer) 11 |
此時,客戶端2修改了age值 | |
redis 127.0.0.1:6379> exec 1) (integer) 12 2) OK redis 127.0.0.1:6379> get name "lisi" |
此時,客戶端1執行隊列命令,發現運算以後age不是理想中的11,而是12緣由是被其它客戶插足搶先給修改了。name值也修改了。這樣可能致使數據不一致性... 爲了解決這個問題引入「樂觀鎖」的機制: |
|
客戶端1-引入「樂觀鎖」機制 | 客戶端2 | 說明 |
redis 127.0.0.1:6379> get age "10" redis 127.0.0.1:6379> get name "zhangsan" |
redis 127.0.0.1:6379> get age "10" redis 127.0.0.1:6379> get name "zhangsan" |
數據庫中兩客戶端登陸,及鍵初始值。 |
redis 127.0.0.1:6379> watch age name OK redis 127.0.0.1:6379> multi OK redis 127.0.0.1:6379> incr age QUEUED redis 127.0.0.1:6379> set name lisi QUEUED |
此時,客戶端1用watch命令監視age和name,而後開啓事務,並提交隊列命令 | |
redis 127.0.0.1:6379> incr age (integer) 11 |
此時,客戶端2修改了age值 | |
redis 127.0.0.1:6379> exec (nil) redis 127.0.0.1:6379> get age "11" redis 127.0.0.1:6379> get name "zhangsan" |
此時,客戶端1執行隊列命令,由watch監控發現此期間age的值已經被修改過,則讓事整個務回滾,不作任何動做。watch能夠同時監控多個鍵,在監控期間只要有一個鍵被其它客戶端改變,則整個事務回滾。 |