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