Redis的事務基于四個命令:
Redis的事務從一個MULTI命令開始,MULTI總會命令返回"ok"。接著就可以開始輸入操作數(shù)據(jù),每一條操作命令都會進入隊列。最后執(zhí)行EXEC,在隊列中的命令得到執(zhí)行。
比如這樣:
> MULTIOK> INCR fooQUEUED> INCR barQUEUED> EXEC1) (integer) 12) (integer) 1如果事務中出現(xiàn)錯誤怎么辦?首先我們將事務中的錯誤分為兩類:
第一種很好理解,就像上面給出的例子中,成功進入隊列后會立馬返回"QUEUED"。如果沒能進入隊列,則整個事務都會失效,提示"Transaction discarded because of PRevious errors."關于EXEC執(zhí)行后出現(xiàn)的錯誤,凡是成功進入隊列的都會被執(zhí)行,即便同一事物中有執(zhí)行失敗的命令,其余的命令都會得到執(zhí)行。這讓那些用過關系型數(shù)據(jù)庫的人們感到詫異, 為什么Redis不支持roll back?對此官網(wǎng)的兩點說法:
Redis commands can fail only if called with a wrong syntax (and the problem is not detectable during the command queueing), or against keys holding the wrong data type: this means that in practical terms a failing command is the result of a programming errors, and a kind of error that is very likely to be detected during development, and not in production.
Redis is internally simplified and faster because it does not need the ability to roll back.
有人說不支持roll back會引發(fā)各種bug。但需要明白的是,roll back不是用來解決編程層面上的錯誤的。 而且,導致命令失敗只有兩種可能:
鑒于此,roll back幾乎沒有任何意義,Redis更傾向于不支持roll back而是保持簡潔和高效。
丟棄事務DISCARD可以用作丟棄當前事務,并將連接狀態(tài)恢復為正常狀態(tài)。使用方法如下:
> SET foo 1OK> MULTIOK> INCR fooQUEUED> DISCARDOK> GET foo"1"原子性check-and-set(CAS)之類的操作往往會出現(xiàn)竟態(tài)條件。Redis提供了WATCH用于觀察key的變化。當一個被觀察的key在EXEC執(zhí)行前變化時,整個事務會終止并返回Nil,對該key的觀察也會結束。剛接觸WATCH的時候,感覺這種處理方式很晦澀。不能加個顯示鎖什么的嗎? 好在官網(wǎng)給出了充分的說明,先假設Redis沒有提供INCR,我們現(xiàn)在要模擬一個遞增操作:
val = GET mykeyval = val + 1SET mykey $val一個client進行該操作時是沒有問題,但多個client一起進行該操作時會出現(xiàn)竟態(tài)條件。比如A和B兩個client同時進行了GET mykey,得到的都是10,因此兩次執(zhí)行的結果是11而不是12。 而加入WATCH后:
WATCH mykeyval = GET mykeyval = val + 1MULTISET mykey $valEXEC如果WATCH和EXEC之間有其他的什么東東改變了被觀察的key,該事務則會失敗。如果希望本次事務執(zhí)行成功則需要在循環(huán)中執(zhí)行,當然,這也是一種locking方式。事實上,多個client訪問同一key的沖突并不常見,看具體情況進行操作吧。
相應地,也有UNWATCH可以用于釋放所有被觀察的key。
比如下面的例子中,事務內(nèi)的INCR會成功執(zhí)行:
WATCH keyUNWATCH keyMULTIINCR keyEXEC關于WATCH,需要注意的一點是:設置了生存時間(EXPIRE)的key不會因為到期而被WATCH當作以改變。
新聞熱點
疑難解答