国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Redis 事務

2019-11-08 20:37:28
字體:
來源:轉載
供稿:網友
redis對事務的支持目前還比較簡單。redis只能保證一個client發起的事務中的命令可以連續的執行,而中間不會插入其他client的命令。由于redis是單線程來處理所有client的請求的所以做到這點是很容易的。一般情況下redis在接受到一個client發來的命令后會立即處理并 返回處理結果,但是當一個client在一個連接中發出multi命令有,這個連接會進入一個事務上下文,該連接后續的命令并不是立即執行,而是先放到一個隊列中。當從此連接受到exec命令后,redis會順序的執行隊列中的所有命令。并將所有命令的運行結果打包到一起返回給client.然后此連接就 結束事務上下文。  一、事務相關命令multi:標記一個事務塊的開始。事務塊內的多條命令會按照先后順序被放進一個隊列當中,最后由 EXEC 命令原子性(atomic)地執行。exec:執行所有事務塊內的命令。假如某個(或某些) key 正處于 WATCH 命令的監視之下,且事務塊中有和這個(或這些) key 相關的命令,那么 EXEC 命令只在這個(或這些) key沒有被其他命令所改動的情況下執行并生效,否則該事務被打斷(abort)。

discard:取消事務,放棄執行事務塊內的所有命令。如果正在使用 WATCH 命令監視某個(或某些) key,那么取消所有監視,等同于執行命令 UNWATCH 

watch:監視一個(或多個) key ,如果在事務執行之前這個(或這些) key 被其他命令所改動,那么事務將被打斷,watch不會開啟事務。

unwatch:取消 WATCH 命令對所有 key 的監視。如果在執行 WATCH 命令之后, EXEC 命令或 DISCARD 命令先被執行了的話,那么就不需要再執行 UNWATCH 了。因為 EXEC 命令會執行事務,因此 WATCH 命令的效果已經產生了;而 DISCARD 命令在取消事務的同時也會取消所有對 key 的監視,因此這兩個命令執行之后,就沒有必要執行 UNWATCH 了。

[plain] view plain copy PRint?在CODE上查看代碼片./bin/redis-cli -h 192.168.36.189 -p 6379  192.168.36.189:6379> watch a  OK  192.168.36.189:6379> get a  (nil)  192.168.36.189:6379> multi  OK  192.168.36.189:6379> set a 2  QUEUED  192.168.36.189:6379> incr a  QUEUED  192.168.36.189:6379> exec  1) OK  2) (integer) 3  192.168.36.189:6379>   

二、代碼實例

[java] view%20plain copy print?派生到我的代碼片package cn.slimsmart.redis.demo.transaction;    import java.util.List;    import redis.clients.jedis.Jedis;  import redis.clients.jedis.Transaction;    public class TransactionTest {        public static void main(String[] args) throws InterruptedException {          @SuppressWarnings("resource")          Jedis jedis = new Jedis("192.168.36.189", 6379);          Transaction t=jedis.multi();          t.set("key1", "aaa");          Thread.sleep(1000);          t.set("key2", "bbb");          List<Object> oList=t.exec();          System.out.println(oList);                    jedis.watch("key1");          t = jedis.multi();          t.set("key2", "ccc");          t.set("key3", "ddd");          t.get("key3");          oList = t.exec();          System.out.println(oList);      }    }  

1.當事務執行t.exec()的時候,事務內的命令才會連續執行,并且中間不會插入其它client的命令。2.一個Redis的jedis 只能開啟一個事務,開啟多個會拋異常。3.watch操作并不一定非要在事務內操作,也可以在事物外進行watch。redis只能保證事務的每個命令連續執行,但是如果事務中的一個命令失敗了,并不回滾其他命令,比如使用的命令類型不匹配。當事務的執行過程中,如果redis意外的掛了。很遺憾只有部分命令執行了,后面的也就被丟棄了。當然如果我們使用的append-only file方式持久化,redis會用單個write操作寫入整個事務內容。即是是這種方式還是有可能只部分寫入了事務到磁盤。發生部分寫入事務的情況下,redis重啟時會檢測到這種情況,然后失敗退出??梢允褂胷edis-check-aof工具進行修復,修復會刪除部分寫入的事務內容。修復完后就能夠重新啟動了。參考:http://blog.csdn.net/freebird_lb/article/details/7734008

三、總結

1.redis事物實現,multi開始,所有指令會被放入到隊列中。當調用exec后,隊列中所有指令會依次被執行。2.multi-exec中指令執行時,所有指令只要語法合理都會被寫入隊列中。隊列執行時,指令有可能會執行失敗,但不影響其它指令執行。3.redis事物提供了樂觀鎖,通過watch指令可以實現CAS操作。watch–multi–exec操作在給key加上樂觀鎖后,當在執行exec指令前,有其它client修改此key,此事物將執行失敗。從而保證原子操作。說明:對于redis事物的應用其實需要靈活使用,上面介紹的例子是從官網翻譯而來。其實在實際中可以通過watch一些標記位來保證多線程下緩存與數據庫數據庫的一致性。(我們的系統是分布式緩存與數據庫的結合使用,緩存需要跟據數據庫的一致性很重要,下面舉例我們應用中的一個場景:)如一個service方法,serviceA,執行DAO方法(1),然后更新緩存(2),兩個并發線程,線程一執行了方法1,此刻他需要把DAO相關的數據更新到緩存2中,多線程情況下,線程二在線程一執行1后,也同樣執行1,2相關的操作,并且比線程一優先完成,這樣將導致線程一在執行2時,將出現緩存數據與數據庫不一致的現象。(以上是針對單帳號的多并發操作,發生的概率還是存在),對于以上問題我們的解決方案是:1. 帳號為acc,為每個acc在緩存中增加一個tag標識.2. 當線程一執行方法1前,設置標記位tag.3. 當執行方法2時,將會watch tag,并且比較tag是否發生了修改,如果一旦發生修改,則此次緩存操作不將更新,并清空此acc緩存。4. 如果tag值達到預期,則提交緩存更新,在提交緩存這段時間,如果tag發生變換,則redisexec提交時,會返回null ,這樣,雖然緩存內容更新成功,但跟據返回結果,可以即時清除此acc的緩存,從而清空了緩存的臟數據。5. 通過以上事物保證了緩存數據與數據庫數據不一致性的時間很短,甚至可以忽略,因為基本上在MS級別上。6. 我們的應用在緩存數據不存在acc的情況下,會嘗試從數據庫讀取,而緩存的作用只是緩解我們系統數據庫的壓力,這樣實現,很好的達到了我們的預期效果.

參考

1.redis事務介紹與應用


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 合水县| 兴和县| 黎平县| 泰和县| 安康市| 桐柏县| 固阳县| 梧州市| 原阳县| 盐源县| 乐都县| 兴山县| 安化县| 从化市| 新密市| 栖霞市| 若尔盖县| 长沙县| 泽州县| 嘉义市| 沾化县| 陈巴尔虎旗| 东平县| 广河县| 抚宁县| 赫章县| 北票市| 溧阳市| 潢川县| 璧山县| 桑日县| 庄河市| 凉城县| 确山县| 葫芦岛市| 灵山县| 道真| 海安县| 杭锦后旗| 荣昌县| 荣昌县|