標籤:
redis(二)進階用法
事務
redis的事務是一組命令的集合。事務同命令一樣都是redis的最小執行單元,一個事務中的命令要麼執行要麼都不執行。
首先需要multi命令來開始事務,用exec命令來執行事務。
127.0.0.1:6379> multiOK127.0.0.1:6379> hset user:1 name xiaomingQUEUED127.0.0.1:6379> hset user:1 name daxiongQUEUED127.0.0.1:6379> exec1) (integer) 02) (integer) 0127.0.0.1:6379> hgetall user:11) "name"2) "daxiong"3) "score"4) "61"
multi代表事務的開始,返回ok表示成功; exec代表事務的執行,返回各個命令的執行結果; 在multi和exec中間添加需要執行的命令。 在multi開始後,所有命令都不會執行,而是全部暫時儲存起來,在執行exec命令後會按照命令儲存的順序依次執行各個命令。 如果事務執行過程中存在失敗的情況下(某一個命令執行失敗後其他命令會繼續執行),需要開發人員自行處理後果。 注意:redis不支援復原操作,導致redis的錯誤異常需要開發人員處理。watchwatch命令可以監控一個或多個索引值的變化,一旦其中一個鍵被改變,之後的事務就不會執行,而且監控會一直持續到exec命令。
127.0.0.1:6379> set key 1OK127.0.0.1:6379> watch keyOK127.0.0.1:6379> set key 2OK127.0.0.1:6379> multiOK127.0.0.1:6379> set key 3QUEUED127.0.0.1:6379> exec(nil)127.0.0.1:6379> get key"2"
存留時間(1)設定key的逾時時間,逾時後redis會自動刪除給key值,類似於memcache中的逾時時間。
expire key seconds//設定成功返回1,失敗返回0
127.0.0.1:6379> set session:aabb uid1122OK127.0.0.1:6379> expire session:aabb 300(integer) 1127.0.0.1:6379> del session:aabb(integer) 1127.0.0.1:6379> expire session:aabb 300(integer) 0 127.0.0.1:6379> expire session:aabb 300(integer) 1127.0.0.1:6379> ttl session:aabb (integer) 290
(2)查詢剩餘逾時時間
ttl key
127.0.0.1:6379> expire session:aabb 300(integer) 1127.0.0.1:6379> ttl session:aabb (integer) 290
(3)取消逾時時間
127.0.0.1:6379> get session:aabb"300"127.0.0.1:6379> ttl session:aabb (integer) 280127.0.0.1:6379> persist session:aabb(integer) 1127.0.0.1:6379> ttl session:aabb(integer) -1
(4)如果使用設定相關的命令,會取消該鍵的逾時間
快取資料在某些情況下,需要緩衝一部分網站資料,而網站資料由需要持續的更新(假如需要兩個小時更新一次),那麼可以採用redis進行緩衝這部分資料,設定資料的逾時時間為2小時,每當有請求訪問的時候首先到redis中尋找該資料是否存在,如果存在直接讀取,如果不存在的話重新從資料庫中讀取該資料載入到redis中。 在快取資料的時候需要考慮到被快取資料的大小,如果快取資料較大,會佔用過多的記憶體資源,有必要在設定檔中限制記憶體的使用大小(maxmemory)。 當超過maxmemory的限制後,redis會根據maxmemory-policy參數指定的策略(包括LRU等演算法)來刪除不需要的鍵。
排序sort命令支援對集合類型、類表類型、有序集合類型進行排序。
127.0.0.1:6379> lpush list 1 2 6 3 4 9 8(integer) 7127.0.0.1:6379> sort list1) "1"2) "2"3) "3"4) "4"5) "6"6) "8"7) "9"
可以對有序集合的值進行排序:
127.0.0.1:6379> zadd set 50 2 40 3 20 1 60 5(integer) 4127.0.0.1:6379> sort set1) "1"2) "2"3) "3"4) "5"
sort命令可以添加desc來實現倒序排序
127.0.0.1:6379> sort set desc1) "5"2) "3"3) "2"4) "1"
BY參數很多時候我們需要根據ID對應的對象的某一個屬性進行排序,那麼如何才能把多個不同的資料進行關聯查詢呢?(1)首先,向userids中添加三個使用者id
127.0.0.1:6379> lpush userids 1 2 3(integer) 3
(2)其次,分別對三個使用者添加分數
127.0.0.1:6379> set user_score_1 50OK127.0.0.1:6379> set user_score_2 30OK127.0.0.1:6379> set user_score_3 70OK
(3)最後,使用sort、by命令來對對使用者按照預設情況以及分數的遞增和遞減進行排序。
127.0.0.1:6379> sort userids1) "1"2) "2"3) "3"127.0.0.1:6379> sort userids by user_score_*1) "2"2) "1"3) "3"127.0.0.1:6379> sort userids by user_score_* desc1) "3"2) "1"3) "2"
GET參數get參數並不影響排序,它的作用是使sort命令返回的結果不再是元素自身的值,而是get參數中指定的索引值,同by參數一樣,支援字串類型和散列類型的鍵。
127.0.0.1:6379> sort userids by user_score_* get user_name_*1) "xiaoming"2) "daxiong"3) "xiaohong"127.0.0.1:6379> sort userids by user_score_* desc get user_name_*1) "xiaohong"2) "daxiong"3) "xiaoming"
STORE參數store參數用於結果儲存。 sort命令是redis的複雜命令之一,使用不好會造成效能的瓶頸。 sort命令的時間複雜度是O(n+mlog(m)),其中n是排序列表(集合和有序集合)中元素的個數,m是返回元素的個數。Redis在排序前會建立一個長度為n的的容器來儲存待排序元素,雖然是一個臨時的過程,但是多個較大資料的排序操作則會嚴重影響系統的效能。 因此,在開發中需要注意:(1)儘可能減少排序鍵中的元素個數,降低n(2)使用Limit參數只擷取需要的資料,降低n(3)如果要排序的資料量較大,儘可能使用store名來緩衝結果。
任務隊列任務隊列一般適用於生產者和消費者之間通訊的,那麼在redis中很容易想到使用清單類型來實現任務隊列,具體方法是建立一個任務隊列,生產者主動lpush資料,而消費者去rpop資料,保持一個先進先出的循序。但是這樣存在一個問題,消費者需要主動去請求資料,周期性的請求會造成資源的浪費,因此,redis提供了一個brpop的命令來解決這個問題。
BRPOP key timeout
brpop命令接收兩個參數,第一個參數key為索引值,第二個參數timeout為逾時時間。BRPOP命令取資料時候,如果暫時不存在資料,該命令會一直阻塞直到達到逾時時間。如果timeout設定為0,那麼就會無限等待下去。
優先順序隊列基於任務隊列,如何?優先順序隊列呢? 那麼可以選擇多個任務隊列,而每個任務隊列的任務優先順序是不同的。 redis提供了下面的命令,會從左邊第一個key開始讀下去知道返回一個資料。
brpop key [key...] timetout
發布/訂閱模式redis提供了rabitmq類似的發布訂閱模式,通過生產者使用下面的命令來發布訊息,
PUBLISH CHANNEL MESSAGE
消費者通過下面的訊息來訂閱訊息,
SUBSCRIBE CHANNEL MESSAGE
生產者:
#向channel.test發布訊息127.0.0.1:6379> publish channel.test hello(integer) 0 #返回0表明訂閱者為0,沒有發布訊息127.0.0.1:6379> publish channel.test hello(integer) 1 #返回n表明訂閱者為n,成功發布給1個消費者
消費者:
#訂閱channel.test訊息127.0.0.1:6379> subscribe channel.test Reading messages... (press Ctrl-C to quit)1) "subscribe"2) "channel.test"3) (integer) 1
#接收到來自channel.test的訊息1) "message"2) "channel.test"3) "hello"
管道redis的底層通訊協定對管道提供了支援。通過管道可以一次性發送多條命令並在執行完後一次性將結果返回,當一組命令中每條命令都不依賴之前命令的執行結果時就可以將這組命令一起通過管道發出。管道通過減少用戶端與redis的通訊次數來實現降低往返實驗累計值的目的。
節省空間的(1)精簡鍵名和索引值(2)redis為每種資料類型提供了兩種內部編碼。例如散列類型的儲存是通過散列表來實現的,redis會根據資料的多少來選擇編碼類別型,當資料較少的時候會採用緊湊但效能稍差的內部編碼方式,而資料變多時會把編碼方式改為散列表。
redis(二)進階用法