<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    jinfeng_wang

    G-G-S,D-D-U!

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      400 Posts :: 0 Stories :: 296 Comments :: 0 Trackbacks
    http://blog.csdn.net/oyl822/article/details/44337119

    第一篇中介紹了Redis是一個強大的鍵-值倉儲,支持五種靈活的數據結構。事實上,Redis還支持其它的一些高級特性:事務、發布與訂閱、管道、腳本等,本篇我們來看一下事務。


    前一篇中我們提到,在Redis中每個命令都是原子性的,因為Redis內部的實現是單線程的。當然Redis也支持多個命令之間的事務,不過事務在Redis中相對來說很簡單,不像數據庫事務那樣涉及傳播級別、隔離級別等特性。
    使用multi命令開始一個新的事務,exec命令提交,discard命令回滾。如果把信用卡的可用額度存入balance,欠額存入debt,在消費的時候就必須在一個事務內同時更新這兩個鍵。
    [plain] view plain copy
    1. 127.0.0.1:6379> set balance 100  
    2. OK  
    3. 127.0.0.1:6379> set debt 0  
    4. OK  
    5. 127.0.0.1:6379> multi  
    6. OK  
    7. 127.0.0.1:6379> decrby balance 25  
    8. QUEUED  
    9. 127.0.0.1:6379> incrby debt 25  
    10. QUEUED  
    11. 127.0.0.1:6379> exec  
    12. 1) (integer) 75  
    13. 2) (integer) 25  
    14. 127.0.0.1:6379> get balance  
    15. "75"  
    16. 127.0.0.1:6379> get debt  
    17. "25"  

    在multi命令后的其它命令,返回結果都是"QUEUED“,這些命令不會立即執行,只是簡單的在Server端緩存起來了。在發出exec命令后,他們才會被一起執行;或者discard命令回滾事務。
    在Redis官方文檔有指出事務的兩個特點:
    1. 事務中的命令都是按著他們進入緩存隊列的順序依次執行的,在事務執行中,Redis不會受理其它客戶端的命令(隔離性)
    2. 事務中的命令,或者全部執行,或者全部不執行。(原子性)
    上面的例子是信用卡扣減,但實際中在做扣減時我們需要檢查余額是否足夠,所以一般會這么做:
    [plain] view plain copy
    1. redis.multi()  
    2. balance = redis.get('balance')  
    3. if (balance < amtToSubtract) {  
    4.     redis.discard()  
    5. } else {  
    6.     redis.decrby('balance', amtToSubtract)  
    7.     redis.incrby('debt', amtToSubtract)  
    8.     redis.exec()  
    9. }  
    對于普通數據庫事務,上面的代碼沒問題,但對于Redis事務來說行不通,因為在exec命令之前,所有的命令都被Redis緩存起來了,根本就拿不到balance的值。那類似這種需要基于已經存在的某個值的事務在Redis中如何實現呢?答案是Watch命令:
    [plain] view plain copy
    1. redis.watch('balance')  
    2. balance = redis.get('balance')  
    3. if (balance < amtToSubtract) {  
    4.     redis.unwatch()  
    5. } else {  
    6.     redis.multi()  
    7.     redis.decrby('balance', amtToSubtract)  
    8.     redis.incrby('debt', amtToSubtract)  
    9.     redis.exec()  
    10. }  

    通俗點講,watch命令就是標記一個鍵,如果標記了一個鍵,在提交事務前如果該鍵被別人修改過,那事務就會失敗,這種情況通常可以在程序中重新再嘗試一次。像上面的例子,首先標記了鍵balance,然后檢查余額是否足夠,不足就取消標記,并不做扣減;足夠的話,就啟動事務進行更新操作,如果在此期間鍵balance被其它人修改,那在提交事務(執行exec)時就會報錯,程序中通常可以捕獲這類錯誤再重新執行一次,直到成功。
    Redis事務失敗后不支持回滾
    與數據庫事務很重要的一個區別是Redis事務在執行過程中出錯后不會回滾。在exec命令后,Redis Server開始一個個的執行被緩存的命令,如果其中某個命令執行出錯了,那之前的命令并不會被回滾。
    [plain] view plain copy
    1. 127.0.0.1:6379> set value 1  
    2. OK  
    3. 127.0.0.1:6379> set value2 abc  
    4. OK  
    5. 127.0.0.1:6379> multi  
    6. OK  
    7. 127.0.0.1:6379> incr value  
    8. QUEUED  
    9. 127.0.0.1:6379> incr value2  
    10. QUEUED  
    11. 127.0.0.1:6379> exec  
    12. 1) (integer) 2  
    13. 2) (error) ERR value is not an integer or out of range  
    14. 127.0.0.1:6379> get value  
    15. "2"  
    16. 127.0.0.1:6379>   

    exec提交事務后,在執行到incr value2時錯誤了(數據類型不正確),但事務對value的操作卻是生效的,這點可以從后面的get value的返回值看到。
    posted on 2016-12-20 15:24 jinfeng_wang 閱讀(117) 評論(0)  編輯  收藏 所屬分類: 2016-REDIS
    主站蜘蛛池模板: 又大又硬又粗又黄的视频免费看| 美女羞羞喷液视频免费| 亚洲一本之道高清乱码| 美女黄色毛片免费看| 性感美女视频免费网站午夜| 亚洲色无码专区在线观看| 在线观看日本亚洲一区| 成人精品视频99在线观看免费| 亚洲一级免费毛片| 在线观看午夜亚洲一区| 亚洲欧美日韩一区二区三区在线| 热99RE久久精品这里都是精品免费 | 亚洲码在线中文在线观看| 美女免费视频一区二区三区| 国产一级淫片a免费播放口之| 亚洲区视频在线观看| 97人妻精品全国免费视频| 久久精品国产亚洲av麻豆| 免费无码午夜福利片 | 国产小视频在线观看免费| 亚洲国产高清在线精品一区| 任你躁在线精品免费| 亚洲熟妇av一区| 日本不卡免费新一二三区| 亚洲精品在线不卡| 午夜dj在线观看免费视频| 激情内射亚洲一区二区三区爱妻| 日韩激情无码免费毛片| 一级毛片视频免费观看| 免费人成在线观看视频播放| 亚洲另类无码一区二区三区| 亚洲片国产一区一级在线观看 | 久久亚洲精品成人AV| 在线观看免费播放av片| 亚洲毛片无码专区亚洲乱| 国产成人免费一区二区三区| 中文在线日本免费永久18近| 精品久久亚洲中文无码| 久99精品视频在线观看婷亚洲片国产一区一级在线 | 亚洲国产精品无码久久久秋霞2 | 亚洲噜噜噜噜噜影院在线播放|