1. 程式人生 > >redis入門指南一書總結下(redis進階)

redis入門指南一書總結下(redis進階)

redis事務

Redis中的事務是一組命令的集合,事務和命令一樣都是Redis的最小執行單位
事務的原理為:先發送MULTI命令告訴redis接下來將會開啟一個事務,然後傳送一系列命令,最後傳送執行命令EXEC告訴redis執行這一系列命令。如下就是一個簡單的事務處理:

這裡寫圖片描述

事務通常可以用來保證資料的安全,如果在傳送exec命令前客戶端斷線了,那麼redis將會清空事務佇列,事務中的所有命令都不會執行。而一旦客戶端傳送了exec命令,即使之後客戶端斷線了也不會影響事務的執行,因為redis已經記錄了所有要執行的命令
如果事務中的語句發生錯誤,那麼redis將會如何處理呢?
首先,我們需要知道是什麼原因導致的錯誤,主要有兩種情況:
1.語法錯誤:命令不存在或者引數的個數不對,只要在事務中存在一個語句出現了語法的錯誤,那麼所有的命令都不會執行,如下:

這裡寫圖片描述

2.執行錯誤:執行錯誤指在命令執行時出現的錯誤,比如使用雜湊型別的命令操作集合型別的鍵值時,在語法上是沒有錯誤的,然而在執行起來時就會出錯,看如下:

這裡寫圖片描述

這裡需要注意的一點是:redis的事務和大多數的事務不同,它沒有提供rollback回滾操作,想要復原到事務執行之前需要自己進行元素的設定操作來手動實現
有時候對於事務處於安全考慮,我們想要實現這樣一個情況:在事務執行之前如果某個鍵值發生了改變就不執行事務。要實現這樣一個情況就需要使用到另一個強大的命令watch
該命令可以監控一個或者多個鍵,一旦在接下來的事務執行之前有一個鍵值發生了改變,那麼事務就不會執行。這裡需要注意的是:這裡所指的事務是接下來的第一個,而不是所有的。看如下:

這裡寫圖片描述

我們發現,最終事務的執行結果為(nil),也就是redis中的null,因為在該事物執行之前進行了testkey的修改,所以接下來的事務將不會執行。如果想要取消監視,可以使用命令unwatch,不過該命令只能取消所有的監視,而不能取消指定鍵的監視

生存時間

在實際的開發中經常會遇到一些有時效的資料,比如設計一個限時活動的時候,資料庫中儲存的一些還未使用優惠券等過了優惠的時間就需要刪除這些資料。對於關係資料庫比如MySQL之類的一般需要手動刪除或者額外新增一個欄位儲存到期時間,然後定期檢測刪除過期資料。而對於redis來說, 這一操作就變得簡單了許多
在redis中,可以使用命令expire來設定一個鍵的生存時間,到指定時間後redis就會自動刪除它,它的命令格式為:redis> EXPIRE key seconds其中seconds表示鍵的生存時間,單位是秒

這裡寫圖片描述

如果想要設定更精確的生存時間可以通過expireat命令,它的命令格式和expire一樣,只是第二個引數的單位不是秒,而是unix時間戳
想要檢視指定鍵當前的剩餘生存時間,可以使用命令ttl

這裡寫圖片描述

在這裡使用命令expire設定鍵值的生存時間時需要注意:我們之前說到的watch命令監視鍵,如果正在被監視的鍵因為生存時間到期被自動刪除這一修改不會被watch命令認為該鍵被改變

排序

在前面一篇部落格提到redis資料型別時,有一個有序集合型別,它裡面的元素是有序的,而對於其餘的資料型別該如何進行排序呢?
我們可以藉助redis提供的sort命令來對資料進行排序,該命令可以對列表型別、集合型別和有序集合型別進行鍵值排序,其中對有序集合型別的鍵值排序的方式同樣是通過元素自身的值進行排序的,而不是有序集合型別自帶的分數排序

這裡寫圖片描述

sort命令預設只會對數值型別進行排序,如果元素值為非數值型別,結果就會報錯,因為redis無法自動將數值型別與字串型別進行比較,需要我們手動新增引數ALPHA來實現按照字典順序進行排列
redis> SORT key ALPHA
sort命令預設是按照升序進行排列的,我們可以新增DESC引數來實現按照降序進行排列輸出結果
redis> SORT key DESC
sort命令預設是按照元素自身的值進行排序的,如果想要根據其他對應的鍵值進行排序,可以新增by引數,如下圖

這裡寫圖片描述

由上圖可知,我們通過獲取集合set中的每一個元素值,並通過demo.*進行逐個元素值注入並根據demo.*對應的值進行比較然後升序輸出,最終輸出的結果依舊是原來的set集合的值,而不是demo對應的值
sort命令預設是返回集合中的元素的值,如果想要返回指定的鍵值,比如上面的demo對應的值,可以通過get引數來指定,其命令格式和by一樣

這裡寫圖片描述

對於get引數,如果想要返回元素本身的值可以使用#,當然大多數時候是沒有必要的
sort命令預設是直接將結果輸出,如果想要儲存結果到指定變數中,可以使用store引數,其後指定一個鍵名或者說欄位即可,不管是否存在都行
效能優化:SORT命令是redis最強大也是最複雜的命令之一,該命令的時間複雜度與集合本身元素數量和要返回的元素數量有關,當集合本身元素數量過多或者返回的數量過多時SORT的效能較低,並且redis在使用該命令進行排序前會先建立一個長度為n(集合本身元素數量)的容器來儲存待排序的元素,雖然是一個臨時過程,但是同時進行的話也會嚴重影響效能

訊息通知

前面我們提到過從列表中彈出元素使用的是命令LPOP/RPOP,該命令是非阻塞式命令,如果有元素則彈出並返回該元素的值,如果沒有則輸出(nil),而其實還有一個相對應的比較強大的阻塞時彈出命令:BRPOP
該命令和RPOP命令的唯一區別在於:如果列表中沒有元素則該命令會一直阻塞下去,知道有元素就彈出並返回該元素
我們可以使用該命令來模擬實現一些簡單的訊息通知行為,該命令的格式為:BRPOP key1 key2 key3,可以同時指定多個列表型別元素,其中如果都沒有元素則會阻塞,從而可以實現任務的優先順序:優先執行的任務可以放在前面

釋出/訂閱模式

redis提供了一組命令用於簡單實現redis客戶端之間的通訊,對應命令為:PUBLISH釋出和SUBSCRIBE訂閱,對應的命令格式如下:
//釋出客戶端釋出訊息
redis> PUBLISH channer info

//訂閱客戶端接收訂閱訊息
redis> SUBSCRIBE channer
其中channer表示訂閱的頻道,它可以看成是一個變數,使用示例看下圖

這裡寫圖片描述