亚洲AV日韩AⅤ综合手机在线观看,激情婷婷久久综合色,欧美色五月婷婷久久,久久国产精品99久久人人澡

  • <abbr id="uk6uq"><abbr id="uk6uq"></abbr></abbr>
  • <tbody id="uk6uq"></tbody>
  • Redis學(xué)習(xí)筆記:事務(wù)詳解

    時(shí)間:2020-09-21 12:41:22 讀書筆記 我要投稿

    Redis學(xué)習(xí)筆記:事務(wù)詳解

      一、概述:

    Redis學(xué)習(xí)筆記:事務(wù)詳解

      和眾多其它數(shù)據(jù)庫一樣,Redis作為NoSQL數(shù)據(jù)庫也同樣提供了事務(wù)機(jī)制。在Redis中,MULTI/EXEC/DISCARD/WATCH這四個(gè)命令是我們實(shí)現(xiàn)事務(wù)的基石。相信對(duì)有關(guān)系型數(shù)據(jù)庫開發(fā)經(jīng)驗(yàn)的開發(fā)者而言這一概念并不陌生,即便如此,我們還是會(huì)簡要的列出Redis中事務(wù)的實(shí)現(xiàn)特征:

      1). 在事務(wù)中的所有命令都將會(huì)被串行化的順序執(zhí)行,事務(wù)執(zhí)行期間,Redis不會(huì)再為其它客戶端的請(qǐng)求提供任何服務(wù),從而保證了事物中的所有命令被原子的執(zhí)行。

      2). 和關(guān)系型數(shù)據(jù)庫中的事務(wù)相比,在Redis事務(wù)中如果有某一條命令執(zhí)行失敗,其后的命令仍然會(huì)被繼續(xù)執(zhí)行。

      3). 我們可以通過MULTI命令開啟一個(gè)事務(wù),有關(guān)系型數(shù)據(jù)庫開發(fā)經(jīng)驗(yàn)的人可以將其理解為"BEGIN TRANSACTION"語句。在該語句之后執(zhí)行的命令都將被視為事務(wù)之內(nèi)的操作,最后我們可以通過執(zhí)行EXEC/DISCARD命令來提交/回滾該事務(wù)內(nèi)的所有操作。這兩個(gè)Redis命令可被視為等同于關(guān)系型數(shù)據(jù)庫中的COMMIT/ROLLBACK語句。

      4). 在事務(wù)開啟之前,如果客戶端與服務(wù)器之間出現(xiàn)通訊故障并導(dǎo)致網(wǎng)絡(luò)斷開,其后所有待執(zhí)行的語句都將不會(huì)被服務(wù)器執(zhí)行。然而如果網(wǎng)絡(luò)中斷事件是發(fā)生在客戶端執(zhí)行EXEC命令之后,那么該事務(wù)中的所有命令都會(huì)被服務(wù)器執(zhí)行。

      5). 當(dāng)使用Append-Only模式時(shí),Redis會(huì)通過調(diào)用系統(tǒng)函數(shù)write將該事務(wù)內(nèi)的所有寫操作在本次調(diào)用中全部寫入磁盤。然而如果在寫入的過程中出現(xiàn)系統(tǒng)崩潰,如電源故障導(dǎo)致的宕機(jī),那么此時(shí)也許只有部分?jǐn)?shù)據(jù)被寫入到磁盤,而另外一部分?jǐn)?shù)據(jù)卻已經(jīng)丟失。Redis服務(wù)器會(huì)在重新啟動(dòng)時(shí)執(zhí)行一系列必要的一致性檢測,一旦發(fā)現(xiàn)類似問題,就會(huì)立即退出并給出相應(yīng)的錯(cuò)誤提示。此時(shí),我們就要充分利用Redis工具包中提供的redis-check-aof工具,該工具可以幫助我們定位到數(shù)據(jù)不一致的錯(cuò)誤,并將已經(jīng)寫入的部分?jǐn)?shù)據(jù)進(jìn)行回滾。修復(fù)之后我們就可以再次重新啟動(dòng)Redis服務(wù)器了。

      二、相關(guān)命令列表:

      命令原型 時(shí)間復(fù)雜度 命令描述 返回值 MULTI 用于標(biāo)記事務(wù)的開始,其后執(zhí)行的命令都將被存入命令隊(duì)列,直到執(zhí)行EXEC時(shí),這些命令才會(huì)被原子的執(zhí)行。 始終返回OK EXEC 執(zhí)行在一個(gè)事務(wù)內(nèi)命令隊(duì)列中的所有命令,同時(shí)將當(dāng)前連接的狀態(tài)恢復(fù)為正常狀態(tài),即非事務(wù)狀態(tài)。如果在事務(wù)中執(zhí)行了WATCH命令,那么只有當(dāng)WATCH所監(jiān)控的Keys沒有被修改的前提下,EXEC命令才能執(zhí)行事務(wù)隊(duì)列中的所有命令,否則EXEC將放棄當(dāng)前事務(wù)中的所有命令。 原子性的返回事務(wù)中各條命令的返回結(jié)果。如果在事務(wù)中使用了WATCH,一旦事務(wù)被放棄,EXEC將返回NULL-multi-bulk回復(fù)。 DISCARD 回滾事務(wù)隊(duì)列中的所有命令,同時(shí)再將當(dāng)前連接的狀態(tài)恢復(fù)為正常狀態(tài),即非事務(wù)狀態(tài)。如果WATCH命令被使用,該命令將UNWATCH所有的Keys。 始終返回OK。 WATCHkey [key ...] O(1) 在MULTI命令執(zhí)行之前,可以指定待監(jiān)控的Keys,然而在執(zhí)行EXEC之前,如果被監(jiān)控的Keys發(fā)生修改,EXEC將放棄執(zhí)行該事務(wù)隊(duì)列中的所有命令。 始終返回OK。 UNWATCH O(1) 取消當(dāng)前事務(wù)中指定監(jiān)控的Keys,如果執(zhí)行了EXEC或DISCARD命令,則無需再手工執(zhí)行該命令了,因?yàn)樵诖酥螅聞?wù)中所有被監(jiān)控的Keys都將自動(dòng)取消。 始終返回OK。

      三、命令示例:

      1. 事務(wù)被正常執(zhí)行:

      復(fù)制代碼 代碼如下:

      #在Shell命令行下執(zhí)行Redis的客戶端工具。

      /> redis-cli

      #在當(dāng)前連接上啟動(dòng)一個(gè)新的事務(wù)。

      redis 127.0.0.1:6379> multi

      OK

      #執(zhí)行事務(wù)中的第一條命令,從該命令的返回結(jié)果可以看出,該命令并沒有立即執(zhí)行,而是存于事務(wù)的命令隊(duì)列。

      redis 127.0.0.1:6379> incr t1

      QUEUED

      #又執(zhí)行一個(gè)新的命令,從結(jié)果可以看出,該命令也被存于事務(wù)的命令隊(duì)列。

      redis 127.0.0.1:6379> incr t2

      QUEUED

      #執(zhí)行事務(wù)命令隊(duì)列中的所有命令,從結(jié)果可以看出,隊(duì)列中命令的結(jié)果得到返回。

      redis 127.0.0.1:6379> exec

      1) (integer) 1

      2) (integer) 1

      2. 事務(wù)中存在失敗的命令:

      復(fù)制代碼 代碼如下:

      #開啟一個(gè)新的事務(wù)。

      redis 127.0.0.1:6379> multi

      OK

      #設(shè)置鍵a的值為string類型的3。

      redis 127.0.0.1:6379> set a 3

      QUEUED

      #從鍵a所關(guān)聯(lián)的值的'頭部彈出元素,由于該值是字符串類型,而lpop命令僅能用于List類型,因此在執(zhí)行exec命令時(shí),該命令將會(huì)失敗。

      redis 127.0.0.1:6379> lpop a

      QUEUED

      #再次設(shè)置鍵a的值為字符串4。

      redis 127.0.0.1:6379> set a 4

      QUEUED

      #獲取鍵a的值,以便確認(rèn)該值是否被事務(wù)中的第二個(gè)set命令設(shè)置成功。

      redis 127.0.0.1:6379> get a

      QUEUED

      #從結(jié)果中可以看出,事務(wù)中的第二條命令lpop執(zhí)行失敗,而其后的set和get命令均執(zhí)行成功,這一點(diǎn)是Redis的事務(wù)與關(guān)系型數(shù)據(jù)庫中的事務(wù)之間最為重要的差別。

      redis 127.0.0.1:6379> exec

      1) OK

      2) (error) ERR Operation against a key holding the wrong kind of value

      3) OK

      4) "4"

      3. 回滾事務(wù):

      復(fù)制代碼 代碼如下:

      #為鍵t2設(shè)置一個(gè)事務(wù)執(zhí)行前的值。

      redis 127.0.0.1:6379> set t2 tt

      OK

      #開啟一個(gè)事務(wù)。

      redis 127.0.0.1:6379> multi

      OK

      #在事務(wù)內(nèi)為該鍵設(shè)置一個(gè)新值。

      redis 127.0.0.1:6379> set t2 ttnew

      QUEUED

      #放棄事務(wù)。

      redis 127.0.0.1:6379> discard

      OK

      #查看鍵t2的值,從結(jié)果中可以看出該鍵的值仍為事務(wù)開始之前的值。

      redis 127.0.0.1:6379> get t2

      "tt"

      四、WATCH命令和基于CAS的樂觀鎖:

      在Redis的事務(wù)中,WATCH命令可用于提供CAS(check-and-set)功能。假設(shè)我們通過WATCH命令在事務(wù)執(zhí)行之前監(jiān)控了多個(gè)Keys,倘若在WATCH之后有任何Key的值發(fā)生了變化,EXEC命令執(zhí)行的事務(wù)都將被放棄,同時(shí)返回Null multi-bulk應(yīng)答以通知調(diào)用者事務(wù)執(zhí)行失敗。例如,我們?cè)俅渭僭O(shè)Redis中并未提供incr命令來完成鍵值的原子性遞增,如果要實(shí)現(xiàn)該功能,我們只能自行編寫相應(yīng)的代碼。其偽碼如下:

      復(fù)制代碼 代碼如下:

      val = GET mykey

      val = val + 1

      SET mykey $val

      以上代碼只有在單連接的情況下才可以保證執(zhí)行結(jié)果是正確的,因?yàn)槿绻谕粫r(shí)刻有多個(gè)客戶端在同時(shí)執(zhí)行該段代碼,那么就會(huì)出現(xiàn)多線程程序中經(jīng)常出現(xiàn)的一種錯(cuò)誤場景--競態(tài)爭用(race condition)。比如,客戶端A和B都在同一時(shí)刻讀取了mykey的原有值,假設(shè)該值為10,此后兩個(gè)客戶端又均將該值加一后set回Redis服務(wù)器,這樣就會(huì)導(dǎo)致mykey的結(jié)果為11,而不是我們認(rèn)為的12。為了解決類似的問題,我們需要借助WATCH命令的幫助,見如下代碼:

      復(fù)制代碼 代碼如下:

      WATCH mykey

      val = GET mykey

      val = val + 1

      MULTI

      SET mykey $val

      EXEC

      和此前代碼不同的是,新代碼在獲取mykey的值之前先通過WATCH命令監(jiān)控了該鍵,此后又將set命令包圍在事務(wù)中,這樣就可以有效的保證每個(gè)連接在執(zhí)行EXEC之前,如果當(dāng)前連接獲取的mykey的值被其它連接的客戶端修改,那么當(dāng)前連接的EXEC命令將執(zhí)行失敗。這樣調(diào)用者在判斷返回值后就可以獲悉val是否被重新設(shè)置成功。

    【Redis學(xué)習(xí)筆記:事務(wù)詳解】相關(guān)文章:

    日語學(xué)習(xí)之全然詳解08-12

    英語學(xué)習(xí):感官動(dòng)詞詳解08-14

    教你利用PHP訪問帶有密碼的Redis11-24

    gre閱讀學(xué)習(xí)方法詳解09-27

    英語學(xué)習(xí):不定詞詳解08-14

    英語學(xué)習(xí):分詞構(gòu)句詳解08-14

    英語學(xué)習(xí):句子合成法詳解08-14

    JavaScript學(xué)習(xí)筆記11-13

    JAVA學(xué)習(xí)筆記08-29

    Java學(xué)習(xí)筆記08-13