天天看點

Redis事務

一.使用Redis-Cli執行事務

  1.概念

和其它資料庫一樣,Redis作為NoSQL資料庫也同樣提供了事務機制。在Redis中,MULIT,EXEC,DISCARD,WATCH這個四個指令是實作事務的基石,Redis中事務的實作特征

    1.在事務中的所有指令都将被串行化的順序執行,事務執行期間,Redis不會再為其它用戶端的請求提供任何服務,進而保證了事務中的所有指令被原子的執行

    2.和關系型資料庫中事務相比,在Redis事務中如果由某一條指令執行失敗,其後的指令仍然會被繼續執行

    3.可以通過MULTI指令開啟一個事務,其可以了解為關系性資料庫中的“BEGIN TRANSACTION”語句。在該語句之後執行的指令都被視為事務之内的操作,最後我們可以通過執行EXEC或DISCARD指令來送出或復原事務内的所有操作。這兩個語句也可了解為關系型資料庫中的COMMIT和ROLLBACK語句

    4.在開啟事務之前,如果用戶端與服務端之間出現通訊故障并導緻網絡斷開,其後所有待執行的語句都将不會被伺服器執行,然而如果網絡中斷時間是發生在用戶端執行EXEC指令之後,那麼該事務中的所有指令都會被伺服器執行

    5.當時用Append-Only模式時,Redis會通過調用系統函數Write将該事務内的所有寫操作在本次調用中全部寫入磁盤,然而如果在寫入的過程中發生系統崩潰,那麼此時也許隻有部分資料被寫入磁盤,而另外一部分資料已經丢失,Redis伺服器在重新啟動時執行一系列必須的一緻性檢測,一旦發生類似問題,就會立即退出并給出相應的錯誤提示。此時隻要充分利用Redis工具包中提供的redis-check-aof工具,該工具客戶幫助定位到資料不一緻的錯誤,并将已經寫入的部分進行復原。修複後就可以再次重新啟動Redis伺服器了。

Redis事務是從2.6.5版本開始才有的。2.6.5版本之前是沒有事務

2.相關指令清單

指令原型 時間複雜度 指令描述 傳回值
MULTI 用于标記事務的開始,其後執行的指令都将被存入指令隊列,直到執行EXEC時,這些指令才會被原子的執行。 始終傳回OK
EXEC 執行在一個事務内指令隊列中的所有指令,同時将目前連接配接的狀态恢複為正常狀态,即非事務狀态。如果在事務中執行了WATCH指令,那麼隻有當WATCH所監控的Keys沒有被修改的前提下,EXEC指令才能執行事務隊列中的所有指令,否則EXEC将放棄目前事務中的所有指令。 原子性的傳回事務中各條指令的傳回結果。如果在事務中使用了WATCH,一旦事務被放棄,EXEC将傳回NULL-multi-bulk回複。
DISCARD 復原事務隊列中的所有指令,同時再将目前連接配接的狀态恢複為正常狀态,即非事務狀态。如果WATCH指令被使用,該指令将UNWATCH所有的Keys。 始終傳回OK。
WATCH key [key ...] O(1) 在MULTI指令執行之前,可以指定待監控的Keys,然而在執行EXEC之前,如果被監控的Keys發生修改,EXEC将放棄執行該事務隊列中的所有指令。
UNWATCH 取消目前事務中指定監控的Keys,如果執行了EXEC或DISCARD指令,則無需再手工執行該指令了,因為在此之後,事務中所有被監控的Keys都将自動取消。

 3.示例

   1.事務被正确執行

Redis事務

     從上面執行個體中可以看出multi指令是開啟了事務,在此指令之後向redis添加資料時都不會直接存儲,知道碰到exec指令。

   2.事務中出現失敗的指令

Redis事務

從上面代碼看出第二條指令失敗了,但是它并沒有影響其它指令的執行,這一點也是Redis的事務與關系資料庫中的事務最為重要的差别

3.復原事務

Redis事務

  上面代碼我們先将鍵"a"的值設為了“a",然後在事務中将“a”的值改為了,最後復原事務,我們發現值并沒有改變。

Watch指令

Watch指令-監聽一個(或多個)Key,如果在事務執行之前這個(或這些)被其它指令所改動,那麼事務将被打斷。

 例:

Redis事務

  從上面我們可以發現一開我們将鍵“a”的值設為“b”,然後去監聽鍵“a”,然後再将該“a“的值改為“b”,最後執行事務我們發現事務執行失敗,

Redis事務

這次代碼我們做出了相同的操作,隻不過再監聽之後到執行事務之前并沒有修改鍵”a“的值,我們發現值在事務中修改成功

 二。使用c#代碼處理事務

如果使用C#處理Redis就必須使用”servicestack.redis“得類庫包,這個類庫包4.0版本以上為收費版本,每天有讀取限制,是以在使用時使用4.0版本以下的版本。

下面我們就使用c#來處理Redis事務

首先建立RedisClient對象

RedisClient client = new RedisClient("127.0.0.1", 6379);  //Redis服務端的IP位址與端口号      
using (var tran = client.CreateTransaction())
            {
                try
                {
                    //執行事務指令(切記,每次指令隻能執行一條語句)
                    tran.QueueCommand(y =>
                    {
                          y.Set("a", "a");  

                     });
                    tran.QueueCommand(y =>
                    {
                        y.Set("b", "b");

                    });
//送出事務
                    tran.Commit();
                }
                catch (Exception ew)
                {
                    Console.WriteLine(ew.Message);
//復原事務
                    tran.Rollback();
                }
            }

        }      

然後使用RedisClient的CreateTransaction方法建立事務,然後使用QueueCommand執行指令,這個指令每次隻能執行一條語句,最後執行Commit方法送出,如果出現異常,則使用Rollback方法復原事務

上一篇: 靜态檔案