【Redis緩衝機制】13.Java串連Redis_Jedis_事務

來源:互聯網
上載者:User

標籤:ack   port   net   src   out   提交   object   拒絕   就會   

Jedis事務
我們使用JDBC串連Mysql的時候,每次執行sql語句之前,都需要開啟事務;在MyBatis中,
也需要使用openSession()來擷取session事務對象,來進行sql執行、查詢等操作。當我們
對資料庫的操作結束的時候,是事務對象負責關閉資料庫連接。

事務對象用於管理、執行各種資料庫操作的動作。它能夠開啟和關閉資料庫連接,執行sql
語句,復原錯誤的操作。

我們的Redis也有交易管理對象,其位於redis.clients.jedis.Transaction下。

Jedis事務的相關代碼:
package cn.com.redis;import redis.clients.jedis.Jedis;import redis.clients.jedis.Transaction;public class Test7 {    public static void main(String[] args) {        Jedis jedis = new Jedis("192.168.248.129",6379);                Transaction transaction=jedis.multi();//返回一個事務控制對象                //預先在事務對象中裝入要執行的操作        transaction.set("k4", "v4");        transaction.set("k5", "v5");                transaction.exec();//執行    }}
我們查看一下redis:

探索資料已經加入進去

我們把k4的value和k5的value改為“v44”和“v55”,
然後在transaction.exec()語句後加入transaction.discard()語句:
package cn.com.redis;import redis.clients.jedis.Jedis;import redis.clients.jedis.Transaction;public class Test7 {    public static void main(String[] args) {        Jedis jedis = new Jedis("192.168.248.129",6379);                Transaction transaction=jedis.multi();//返回一個事務控制對象                //預先在事務對象中裝入要執行的操作        transaction.set("k4", "v44");        transaction.set("k5", "v55");        transaction.discard();//復原    }}
會探索資料插入操作被復原,redis中那兩個值未被改變:


我們類比一個刷一次信用卡的交易,使用redis的事務來處理一些邏輯:
package cn.com.redis;import redis.clients.jedis.Jedis;import redis.clients.jedis.Transaction;public class TestTransaction {    //類比信用卡消費和還款    public static void main(String[] args) {        TestTransaction t = new TestTransaction();        boolean retValue = t.transMethod(100);        if(retValue){            System.out.println("使用信用卡消費成功!");        }else{            System.out.println("使用信用卡消費失敗!");        }            }    /**     * 通俗點講,watch命令就是標記一個鍵,如果標記了一個鍵,     * 在提交事務前如果該鍵被別人修改過,那事務就會失敗,這種情況通常可以在程式中     * 重新再嘗試一次。     *     * 首先標記了balance,然後檢查餘額是否足夠,不足就取消標幟,並不做扣減;     * 足夠的話,就啟動事務進行更新操作。     * 如果在此期間鍵balance被其他人修改,拿在提交事務(執行exec)時就會報錯,     * 程式中通常可以捕獲這類錯誤再重新執行一次,直到成功。     * */    private boolean transMethod(int amount) {                System.out.println("您使用信用卡預付款"+amount+"元");                Jedis jedis = new Jedis("192.168.248.129",6379);                int balance = 1000;//可用餘額        int debt;//欠額        int amtToSubtract = amount;//實刷額度                jedis.set("balance", String.valueOf(balance));        jedis.watch("balance");        //jedis.set("balance", "1100");//此句不該出現,為了類比其他程式已經修改了該條目        balance = Integer.parseInt(jedis.get("balance"));        if(balance < amtToSubtract){//可用餘額小於實刷金額,拒絕交易            jedis.unwatch();            System.out.println("可用餘額不足!");            return false;        }else{//可用餘額夠用的時候再去執行計費操作            System.out.println("計費transaction事務開始執行...");            Transaction transaction = jedis.multi();            transaction.decrBy("balance",amtToSubtract);//餘額減去amtToSubtract的錢數            transaction.incrBy("debt", amtToSubtract);//信用卡欠款增加amtToSubtract的錢數            transaction.exec();//執行事務            balance = Integer.parseInt(jedis.get("balance"));            debt = Integer.parseInt(jedis.get("debt"));            System.out.println("計費transaction事務執行結束...");                        System.out.println("您的可用餘額:"+balance);            System.out.println("您目前欠款:"+debt);            return true;        }    }    }

此代碼就是類比使用者使用信用卡刷了100元的東西,此時應該減去信用卡的可用餘額100元,
增加100元的欠款。

運行結果:


redis的結果:

證明我們的操作是成功的。

加watch命令是為了在事務執行的過程中,防止其它的操作打斷事務,或者是影響事務的計算結果,
導致“幻讀”、“髒資料”等異常情況的發生。watch命令建立了一個鍵,一旦發現執行過程中該
鍵被別人修改過,那事務就會失敗,程式中通常可以捕獲這類錯誤再重新執行一次,直到成功。
所以watch命令可以保證資料的同步安全。

為了證明watch命令的用途,我們把上面代碼裡面的jedis.set("balance", "1100");注釋釋放,
然後transMethod方法拋出打斷異常:throws InterruptedException,main方法捕獲打斷異常,
然後彈出相應警告框。
package cn.com.redis;import java.util.List;import redis.clients.jedis.Jedis;import redis.clients.jedis.Transaction;public class TestTransaction {    //類比信用卡消費和還款    public static void main(String[] args) {        TestTransaction t = new TestTransaction();        boolean retValue=false;        boolean Interrupted = false;                try {            retValue = t.transMethod(100);        } catch (InterruptedException e) {            Interrupted = true;            System.out.println("事務被打斷,請重新執行!");        }finally{            if(retValue){                System.out.println("使用信用卡消費成功!");            }else{                if(!Interrupted){                    System.out.println("使用信用卡消費失敗!餘額不足!");                }            }        }    }    /**     * 通俗點講,watch命令就是標記一個鍵,如果標記了一個鍵,     * 在提交事務前如果該鍵被別人修改過,那事務就會失敗,這種情況通常可以在程式中     * 重新再嘗試一次。     *     * 首先標記了balance,然後檢查餘額是否足夠,不足就取消標幟,並不做扣減;     * 足夠的話,就啟動事務進行更新操作。     * 如果在此期間鍵balance被其他人修改,拿在提交事務(執行exec)時就會報錯,     * 程式中通常可以捕獲這類錯誤再重新執行一次,直到成功。     * */    private boolean transMethod(int amount) throws InterruptedException{                System.out.println("您使用信用卡預付款"+amount+"元");                Jedis jedis = new Jedis("192.168.248.129",6379);                int balance = 1000;//可用餘額        int debt;//欠額        int amtToSubtract = amount;//實刷額度                jedis.set("balance", String.valueOf(balance));        jedis.watch("balance");        jedis.set("balance", "1100");//此句不該出現,為了類比其他程式已經修改了該條目        balance = Integer.parseInt(jedis.get("balance"));        if(balance < amtToSubtract){//可用餘額小於實刷金額,拒絕交易            jedis.unwatch();            System.out.println("可用餘額不足!");            return false;        }else{//可用餘額夠用的時候再去執行計費操作            System.out.println("計費transaction事務開始執行...");            Transaction transaction = jedis.multi();            transaction.decrBy("balance",amtToSubtract);//餘額減去amtToSubtract的錢數            transaction.incrBy("debt", amtToSubtract);//信用卡欠款增加amtToSubtract的錢數            List<Object> result = transaction.exec();//執行事務                        if(result==null){//事務提交失敗,說明在執行期間資料被修改過                                System.out.println("計費transaction事務執行中斷...");                throw new InterruptedException();                            }else{//事務提交成功                balance = Integer.parseInt(jedis.get("balance"));                debt = Integer.parseInt(jedis.get("debt"));                System.out.println("計費transaction事務執行結束...");                                System.out.println("您的可用餘額:"+balance);                System.out.println("您目前欠款:"+debt);                                return true;            }        }    }    }
再運行一下,看一下效果:


這就說明了,如果在watch命令執行後和事務提交之前,如果資料發生了修改操作,事務執行就不會成功,

此舉保證了資料的安全性。

轉載請註明出處:http://blog.csdn.net/acmman/article/details/53579378

【Redis緩衝機制】13.Java串連Redis_Jedis_事務

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.