redis13---事務處理。

Jedis事務
咱們使用JDBC鏈接Mysql的時候,每次執行sql語句以前,都須要開啓事務;在MyBatis中,
也須要使用openSession()來獲取session事務對象,來進行sql執行、查詢等操做。當咱們
對數據庫的操做結束的時候,是事務對象負責關閉數據庫鏈接。

事務對象用於管理、執行各類數據庫操做的動做。它可以開啓和關閉數據庫鏈接,執行sql
語句,回滾錯誤的操做。

咱們的Redis也有事務管理對象,其位於redis.clients.jedis.Transaction下。

Jedis事務的相關代碼:java

[java]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. package cn.com.redis;  
  2.   
  3. import redis.clients.jedis.Jedis;  
  4. import redis.clients.jedis.Transaction;  
  5.   
  6. public class Test7 {  
  7.     public static void main(String[] args) {  
  8.         Jedis jedis = new Jedis("192.168.248.129",6379);  
  9.           
  10.         Transaction transaction=jedis.multi();//返回一個事務控制對象  
  11.           
  12.         //預先在事務對象中裝入要執行的操做  
  13.         transaction.set("k4", "v4");  
  14.         transaction.set("k5", "v5");  
  15.           
  16.         transaction.exec();//執行  
  17.     }  
  18. }  

咱們查看一下redis:

發現數據已經加入進去

咱們把k4的value和k5的value改成「v44」和「v55」,
而後在transaction.exec()語句後加入transaction.discard()語句:redis

[java]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. package cn.com.redis;  
  2.   
  3. import redis.clients.jedis.Jedis;  
  4. import redis.clients.jedis.Transaction;  
  5.   
  6. public class Test7 {  
  7.     public static void main(String[] args) {  
  8.         Jedis jedis = new Jedis("192.168.248.129",6379);  
  9.           
  10.         Transaction transaction=jedis.multi();//返回一個事務控制對象  
  11.           
  12.         //預先在事務對象中裝入要執行的操做  
  13.         transaction.set("k4", "v44");  
  14.         transaction.set("k5", "v55");  
  15.   
  16.         transaction.discard();//回滾  
  17.     }  
  18. }  

會發現數據插入操做被回滾,redis中那兩個值未被改變:


咱們模擬一個刷一次信用卡的交易,使用redis的事務來處理一些邏輯:sql

[java]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. package cn.com.redis;  
  2.   
  3. import redis.clients.jedis.Jedis;  
  4. import redis.clients.jedis.Transaction;  
  5.   
  6. public class TestTransaction {  
  7.     //模擬信用卡消費和還款  
  8.     public static void main(String[] args) {  
  9.         TestTransaction t = new TestTransaction();  
  10.         boolean retValue = t.transMethod(100);  
  11.         if(retValue){  
  12.             System.out.println("使用信用卡消費成功!");  
  13.         }else{  
  14.             System.out.println("使用信用卡消費失敗!");  
  15.         }  
  16.           
  17.     }  
  18.   
  19.     /** 
  20.      * 通俗點講,watch命令就是標記一個鍵,若是標記了一個鍵, 
  21.      * 在提交事務前若是該鍵被別人修改過,那事務就會失敗,這種狀況一般能夠在程序中 
  22.      * 從新再嘗試一次。 
  23.      * 
  24.      * 首先標記了balance,而後檢查餘額是否足夠,不足就取消標記,並不作扣減; 
  25.      * 足夠的話,就啓動事務進行更新操做。 
  26.      * 若是在此期間鍵balance被其餘人修改,拿在提交事務(執行exec)時就會報錯, 
  27.      * 程序中一般能夠捕獲這類錯誤再從新執行一次,直到成功。 
  28.      * */  
  29.     private boolean transMethod(int amount) {  
  30.           
  31.         System.out.println("您使用信用卡預付款"+amount+"元");  
  32.           
  33.         Jedis jedis = new Jedis("192.168.248.129",6379);  
  34.           
  35.         int balance = 1000;//可用餘額  
  36.         int debt;//欠額  
  37.         int amtToSubtract = amount;//實刷額度  
  38.           
  39.         jedis.set("balance", String.valueOf(balance));  
  40.         jedis.watch("balance");  
  41.         //jedis.set("balance", "1100");//此句不應出現,爲了模擬其餘程序已經修改了該條目  
  42.         balance = Integer.parseInt(jedis.get("balance"));  
  43.         if(balance < amtToSubtract){//可用餘額小於實刷金額,拒絕交易  
  44.             jedis.unwatch();  
  45.             System.out.println("可用餘額不足!");  
  46.             return false;  
  47.         }else{//可用餘額夠用的時候再去執行扣費操做  
  48.             System.out.println("扣費transaction事務開始執行...");  
  49.             Transaction transaction = jedis.multi();  
  50.             transaction.decrBy("balance",amtToSubtract);//餘額減去amtToSubtract的錢數  
  51.             transaction.incrBy("debt", amtToSubtract);//信用卡欠款增長amtToSubtract的錢數  
  52.             transaction.exec();//執行事務  
  53.             balance = Integer.parseInt(jedis.get("balance"));  
  54.             debt = Integer.parseInt(jedis.get("debt"));  
  55.             System.out.println("扣費transaction事務執行結束...");  
  56.               
  57.             System.out.println("您的可用餘額:"+balance);  
  58.             System.out.println("您目前欠款:"+debt);  
  59.             return true;  
  60.         }  
  61.     }  
  62.       
  63. }  


此代碼就是模擬用戶使用信用卡刷了100元的東西,此時應該減去信用卡的可用餘額100元,
增長100元的欠款。

運行結果:


redis的結果:

證實咱們的操做是成功的。

加watch命令是爲了在事務執行的過程當中,防止其它的操做打斷事務,或者是影響事務的計算結果,
致使「幻讀」、「髒數據」等異常狀況的發生。watch命令創建了一個鍵,一旦發現執行過程當中該
鍵被別人修改過,那事務就會失敗,程序中一般能夠捕獲這類錯誤再從新執行一次,直到成功。
因此watch命令能夠保證數據的同步安全。

爲了證實watch命令的用途,咱們把上面代碼裏面的jedis.set("balance", "1100");註釋釋放,
而後transMethod方法拋出打斷異常:throws InterruptedException,main方法捕獲打斷異常,
而後彈出相應警告框。數據庫

[java]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. package cn.com.redis;  
  2.   
  3. import java.util.List;  
  4.   
  5. import redis.clients.jedis.Jedis;  
  6. import redis.clients.jedis.Transaction;  
  7.   
  8. public class TestTransaction {  
  9.     //模擬信用卡消費和還款  
  10.     public static void main(String[] args) {  
  11.         TestTransaction t = new TestTransaction();  
  12.         boolean retValue=false;  
  13.         boolean Interrupted = false;  
  14.           
  15.         try {  
  16.             retValue = t.transMethod(100);  
  17.         } catch (InterruptedException e) {  
  18.             Interrupted = true;  
  19.             System.out.println("事務被打斷,請從新執行!");  
  20.         }finally{  
  21.             if(retValue){  
  22.                 System.out.println("使用信用卡消費成功!");  
  23.             }else{  
  24.                 if(!Interrupted){  
  25.                     System.out.println("使用信用卡消費失敗!餘額不足!");  
  26.                 }  
  27.             }  
  28.         }  
  29.     }  
  30.   
  31.     /** 
  32.      * 通俗點講,watch命令就是標記一個鍵,若是標記了一個鍵, 
  33.      * 在提交事務前若是該鍵被別人修改過,那事務就會失敗,這種狀況一般能夠在程序中 
  34.      * 從新再嘗試一次。 
  35.      * 
  36.      * 首先標記了balance,而後檢查餘額是否足夠,不足就取消標記,並不作扣減; 
  37.      * 足夠的話,就啓動事務進行更新操做。 
  38.      * 若是在此期間鍵balance被其餘人修改,拿在提交事務(執行exec)時就會報錯, 
  39.      * 程序中一般能夠捕獲這類錯誤再從新執行一次,直到成功。 
  40.      * */  
  41.     private boolean transMethod(int amount) throws InterruptedException{  
  42.           
  43.         System.out.println("您使用信用卡預付款"+amount+"元");  
  44.           
  45.         Jedis jedis = new Jedis("192.168.248.129",6379);  
  46.           
  47.         int balance = 1000;//可用餘額  
  48.         int debt;//欠額  
  49.         int amtToSubtract = amount;//實刷額度  
  50.           
  51.         jedis.set("balance", String.valueOf(balance));  
  52.         jedis.watch("balance");  
  53.         jedis.set("balance", "1100");//此句不應出現,爲了模擬其餘程序已經修改了該條目  
  54.         balance = Integer.parseInt(jedis.get("balance"));  
  55.         if(balance < amtToSubtract){//可用餘額小於實刷金額,拒絕交易  
  56.             jedis.unwatch();  
  57.             System.out.println("可用餘額不足!");  
  58.             return false;  
  59.         }else{//可用餘額夠用的時候再去執行扣費操做  
  60.             System.out.println("扣費transaction事務開始執行...");  
  61.             Transaction transaction = jedis.multi();  
  62.             transaction.decrBy("balance",amtToSubtract);//餘額減去amtToSubtract的錢數  
  63.             transaction.incrBy("debt", amtToSubtract);//信用卡欠款增長amtToSubtract的錢數  
  64.             List<Object> result = transaction.exec();//執行事務  
  65.               
  66.             if(result==null){//事務提交失敗,說明在執行期間數據被修改過  
  67.                   
  68.                 System.out.println("扣費transaction事務執行中斷...");  
  69.                 throw new InterruptedException();  
  70.                   
  71.             }else{//事務提交成功  
  72.                 balance = Integer.parseInt(jedis.get("balance"));  
  73.                 debt = Integer.parseInt(jedis.get("debt"));  
  74.                 System.out.println("扣費transaction事務執行結束...");  
  75.                   
  76.                 System.out.println("您的可用餘額:"+balance);  
  77.                 System.out.println("您目前欠款:"+debt);  
  78.                   
  79.                 return true;  
  80.             }  
  81.         }  
  82.     }  
  83.       
  84. }  

再運行一下,看一下效果:


這就說明了,若是在watch命令執行後和事務提交以前,若是數據發生了修改操做,事務執行就不會成功,安全

相關文章
相關標籤/搜索