Redis入門(3) - 事務和緩存

  • 事務的使用方式
  • 事務的錯誤處理
  • WATCH命令
  • 生存時間
  • 緩存策略

Redis中的事務(transaction)是一組命令的集合。事務同命令同樣都是Redis的最小執行單位,一個事務中的命令要麼都執行,要麼都不執行。redis

事務的原理是先將屬於一個事務的命令發送給Redis,而後再讓Redis依次執行這些命令。算法

事務的使用方式

> MULTI
OK
> SADD key1 1
QUEUED
> SADD key2 2
QUEUED
> EXEC
1) (integer) 1
2) (integer) 1

首先用MULTI開啓事務,redis會返回"OK"。
接下來輸入的命令都會被加入到等待執行的事務隊列中,而不是像一般同樣當即執行,redis會返回"QUEUED"表示成功加入到隊列中了。數據庫

最終須要執行時,使用EXEC命令告訴Redis將等待執行的事務隊列中的全部命令按照發送的順序依次執行。EXEC命令的返回值就是這些命令的返回值組成的列表,返回值順序和命令的順序相同。緩存

經過這種方式,Redis能夠保證一個事務中的全部命令要麼都執行,要麼都不執行。若是在發送EXEC命令前客戶端斷線了,則Redis會清空事務隊列,事務中的全部命令都不會執行。而一旦客戶端發送了EXEC命令,全部的命令就都會被執行,即便此後客戶端斷線也不要緊,由於Redis中已經記錄了全部要執行的命令。服務器

除此以外,Redis的事務還能保證一個事務內的命令依次執行而不被其餘命令插入。好比在客戶端A執行多條命令的時候,客戶端B也剛好發送了一條命令,若是不使用事務,則客戶端B的命令可能會插入到客戶端A的命令中執行。而使用事務也能夠避免這種狀況的發生。dom

事務的錯誤處理

若是事務中的某個命令執行錯誤,Redis怎麼處理呢?分兩種狀況:spa

  1. 語法錯誤。命令的使用方式不對,或輸入了不存在的命令,這類狀況在加入事務隊列前就會被識別出來,發送EXEC後Redis會直接返回錯誤提示,事務中的命令都不會被執行。
> MULTI
 OK
 > SET key value
 QUEUED
 > SET key
 (error)ERR wrong number of arguments for 'set' command
 > ERRORCOMMAND key
 (error)ERR unknown command 'ERRORCOMMAND
 > EXEC
 (error) EXECABORT Transaction discarded because
 of previous errors.

這裏一共三條命令,第一條被加入到事務隊列中,但後面兩條都報錯,最終事務會被取消執行。unix

  1. 運行錯誤。運行錯誤是指在命令執行時出現的錯誤,好比使用散列類型的命令操做集合類型的鍵,運行錯誤在實際執行以前是沒法被Redis識別的,因此在事務裏這樣的命令是會被Redis接受並執行的。若是事務裏的一條命令出現了運行錯誤,事務裏其餘的命令依然會繼續執行,包括出錯命令以後的命令!例如:
> MULTI
 OK
 > SET key 1
 QUEUED
 > SADD key 2
 QUEUED
 > SET key 3
 QUEUED
 > EXEC
 1)OK
 2) (error) ERR Operation against a key holding
 the wrong kind of value
 3)OK
 > GET key
 "3"

雖然SADD那一步執行錯誤,但接下來的SET key 3仍然執行了,key的最終結果爲3。
遇到這種狀況怎麼辦呢?可能第一反應是如何回滾,但Redis並無提供事務的回滾功能,一旦出現這類運行錯誤,須要使用者自行處理,手動將數據庫修復爲事務執行前的狀態。code

但換個角度,正是因爲Redis捨棄了事務的回滾功能,使得Redis在的事務簡潔、快速。這裏的第一種錯誤能夠被Redis識別,第二種錯誤也是能夠提早避免的。隊列

WATCH命令

在一個事務中只有當全部命令都依次執行完後才能獲得每一個結果的返回值,但是有些狀況下須要先得到一條命令的返回值,而後再根據這個值執行下一條命令。若是直接獲取,可能以後這個值已經被別的客戶端更改過了,那麼後面都是基於過期的值在作計算了。
爲了不這種狀況,就可使用WATCH。

WATCH命令能夠監控一個或多個鍵,一旦其中有一個鍵被修改(或刪除),以後的事務就不會執行。監控一直持續到EXEC命令(事務中的命令是在EXEC以後才執行的,因此在MULTI命令後能夠修改WATCH監控的鍵值),如:

> SET key 1
 OK
 > WATCH key
 OK
 > SET key 2
 OK
 > MULTI
 OK
 > SET key 3
 QUEUED
 > EXEC
 (nil)
 > GET key
 "2"

這個例子中,在執行WATCH命令後、事務執行前修改了key的值(即SET key 2),因此最後事務中的命令SET key 3沒有執行,EXEC命令返回空結果。

執行EXEC命令後會取消對全部鍵的監控,若是不想執行事務中的命令也可使用UNWATCH命令來取消監控。

生存時間

Redis中能夠爲鍵設置生存時間,能夠利用這一特性,實現緩存、驗證碼等功能。

EXPIRE key seconds
 PEXPIRE key milliseconds

其中seconds/milliseconds參數表示鍵的生存時間,單位是秒/毫秒。返回1表示設置成功,返回0則表示鍵不存在或設置失敗。
再次執行EXPIRE/PEXPIRE會重置鍵的生存時間。

還能夠經過設置截至時間的方式讓鍵失效:

EXPIREAT key unixtimespan
 PEXPIREAT key unixtimespan

一樣的,PEXPIREAT的單位是毫秒。

若是想取消鍵的生存時間設置,即將鍵恢復成永久有效,可使用PERSIST命令:

PERSIST key

若是生存時間被成功清除則返回1,若是鍵不存在或鍵原本就是永久的則返回0。
除了這種方法,用SET命令爲鍵複製也會清除鍵的生存時間。

查看一個鍵剩餘的生存時間:

TTL key
 PTTL key

TTL和PTTL返回值的單位分別是秒和毫秒。
但若是鍵不存在,會返回-2。若是鍵沒有設置生存時間,或生存時間設置被清除,會返回-1。

基於生存時間能夠將Redis用做緩存。
當服務器內存有限時,若是大量地使用緩存鍵且生存時間設置得過長就會致使Redis佔滿內存;另外一方面若是爲了防止Redis佔用內存過大而將緩存鍵的生存時間設得過短,就可能致使緩存命中率太低而且大量內存白白地閒置。實際開發中會發現很難爲緩存鍵設置合理的生存時間,爲此能夠限制Redis可以使用的最大內存,並讓Redis按照必定的規則淘汰不須要的緩存鍵,這種方式在只將Redis用做緩存系統時很是實用。

修改配置文件的maxmemory參數能夠限制Redis最大可用內存大小,當超出了這個限制時Redis會依據maxmemory-policy參數指定的策略來刪除不須要的鍵,直到Redis佔用的內存小於指定內存。

maxmemory-policy可選的規則以下:

規則 說明
volatile-lru 使用LRU算法刪除一個鍵(只對設置了生存時間的鍵)
allkeys-lru 使用LRU算法刪除一個鍵
volatile-random 隨機刪除一個鍵(只對設置了生存時間的鍵)
allkeys-random 隨機刪除一個鍵
volatile-ttl 刪除生存時間最近的一個鍵
noeviction 不刪除鍵,只返回錯誤

LRU(LeastRecently Used)算法即「最近最少使用算法」,認爲最近最少使用的鍵在將來一段時間內也不會被用到,因此當須要空間時這些鍵會首先被刪除。

相關文章
相關標籤/搜索