標籤:store 檔案 unsigned written ali 散列 發行者 ash 結合
redis使用基礎(四)
——Redis排序與訊息通知
(轉載請附上本文連結——linhxx)
一、排序
1、命令
SORT key [ALPHA] [DESC] [LIMIT start end],對列表、集合和有序集合進行排序,當加上alpha參數後,則可以按照字典順序排序,加上desc則倒序排序,加上limit則支援分頁。
2、關鍵參數
by參數:by key:*->val,可以指定排序的標準,可以自己傳入一個list,也可以指定某個列進行排序。
get參數:get key:*->val,可以指定sort排序的返回結果,而不是將整個集合進行返回,要多個參數時採用多個get,另外get#會返回元素本身的索引值。
store參數:store key2,可以將前面排序的結果儲存在另外一個key裡面。
3、效能問題
sort的時間複雜度O(n+mlog m),n是待排序的基數,m是排序後的值。另外redis會在排序前用一個空間為n的容器進行儲存排序期間的臨時資料。
因此,需要注意幾個問題:
1)儘可能減少待排序的集合數量,以減少n
2)如果不需要全部結果,則用limit,以減少m
3)如果要排序的結果大,則用store進行儲存。
二、訊息佇列
redis訊息佇列可以分為兩類,生產者和消費者,當生產者產生的資料會放入訊息佇列中,消費者監測到訊息佇列內有資料的時候,可以進行後續的處理。
1、命令
redis提供一個命令叫BRPOP,與RPOP的區別在於,當使用命令對key進行操作時,如果key沒有值,則會阻塞等待,直到等到有值後取出進行操作。另外,和brpop相似的,也有BLPOP命令。
2、優先順序
由於brpop命令可以支援多個鍵,並且當每個鍵都有未處理的資料時,會從最左邊的鍵開始處理。例如有兩個寄件提醒業務,一個是開通帳號的驗證,一個是新訊息提醒。則如果太多的不採用優先順序,新訊息提醒的業務會讓開通帳號的業務阻塞。因為開通帳號的時效性要求更高,因此需要將其放在左邊。
3、發布訂閱模式
發布訂閱模式有特殊的命令,發布的命令是PUBLISH channel message,訂閱的命令是SUBSCRIBE channel message,不過由於redis的發布命令不會對訊息進行持久化,即後面訂閱的無法查看到發行者之前發布的訊息。
subscribe命令後,會讓用戶端進入訂閱狀態,此後只能輸入四種命令:subscribe、unsubscribe、psubscribe、punsubscribe,其他命令會報錯。
處於訂閱狀態後,用戶端會收到3種類型的回複,每個回複有三個值,第一個值是回複的類型,根據類型不同,二三兩個值也不同。訊息類型如下:
1)subscribe 表示訂閱成功的反饋,此時第二個傳回值是訂閱的頻道名稱,第三個值是當前客訂閱的頻道數量。
2)message 表示收到的訂閱訊息,也是此模式的核心,其第二個值是頻道的名稱,第三個值是訊息的內容。
3)unsubscribe 表示成功取消訂閱某個頻道,第二個值是取消的頻道名稱,第三個是剩餘的訂閱頻道數量,如果是0,則此時會取消訂閱模式,後面就可以繼續輸入其他非訂閱的命令。
4、批量訂閱模式
命令psubscribe,支援blob模式,即類似正則的模式,如psubscribe channel.*,則訂閱所有channel開頭的頻道。
與此相應的,punsubscribe命令支援批量取消訂閱。
三、管道
redis和用戶端是用tcp進行的串連,因此來回傳送訊息都要經過網路,來回的總耗時稱為訊息時延。當執行多個命令時,每條命令需要執行完畢有返回的時候,下一條才會執行。
當需要一起執行時,redis底層的通訊對管道提供了支援,當一組命令中每條命令都不依賴於前一條時,可以一起發送請求,一起返回,以減少網路通訊的次數。
四、空間消耗
1、複雜度
redis為每種資料類型都提供兩種編碼方式,例如hash,當元素很多的時候會使用散列表的方式進行儲存,時間複雜度僅O(1);但是當元素很少時,O(n)和O(1)差距不大,為了節約記憶體,redis會採用內部編碼方法,用時間換空間。
redis可以使用OBJECT ENCODING key的方式,查看每個鍵的內部編碼類別型。
2、編碼
redis在內部編碼採用結構體類型,如下:
typedef struct redisObject{
unsigned type:4;
unsigned notuse:2;
unsigned encoding:4;
unsigned lru:22;
int refcount;
void *ptr;
}
type代表類型,用數字0-4表示五種類型;notuse是預留空間,未使用;ptr指標指向具體儲存的資料;encoding有9種,0-8,包括原生編碼、整型、雜湊表、zipmap、雙向鏈表、ziplist、skiplist、字串。針對redis的五種資料類型,分別有不同的encoding方式,如所示:(來自網路)
3、字串最佳化
字串儲存在一個結構體,包括字串長度、具體內容、剩餘空間。當執行set命令,要佔用30位元組,而當索引值是64位的整數,則ptr指標會直接指向值,而不是指向結構體,可以節約到16位元組。
當儲存的是0-9999時,redis由於會預設儲存這些數字,則ptr指標直接指向引用,佔用0位元組的空間。
4、散列最佳化
在設定檔中設定hash-max-ziplist-entries和hash-max-ziplist-value,當散列的鍵的個數少於entiries值,且每個索引值都小於value值,則會使用ziplist的方式編碼,否則用雜湊表來編碼。ziplist犧牲時間換空間,雜湊表犧牲空間換時間,因此資料少用ziplist,多的時候用雜湊表。
因此,兩個參數不宜設定的太大。
5、列表最佳化
列表和散列相似,有list-max-ziplist-entries和list-max-ziplist-value來配置。編碼方式包括ziplist、雙向鏈表、quicklist,quicklist結合ziplist和雙向鏈表的有點,達到減少空間的同時適當減少時間。
6、集合最佳化
設定檔配置set-max-intset-entries,小於時採用intset編碼,否則用雜湊表。intset使得集合內部有序排列,便於用二分法進行尋找,但是添加和刪除則需要進行排序,元素多的時候速度慢。
7、有序集合最佳化
設定檔配置zset-max-ziplist-entries和zset-max-ziplist-value。包括ziplist和skiplist編碼方式,skiplist是使用雜湊表和跳躍列表兩種結構來儲存,雜湊表用來儲存分數的映射,跳躍列表用來儲存分數和元素值的映射。
——written by linhxx
更多最新文章,歡迎關注公眾號“決勝機器學習”,或掃描右邊二維碼。
redis使用基礎(四) ——Redis排序與訊息通知