https://redis.io/topics/memory-optimization 官方文檔redis
1、特殊編碼:
自從Redis 2.2以後,不少數據類型均可以經過特殊編碼的方式來進行存儲空間的優化。其中,Hash、List和由Integer組成的Sets均可以經過該方式來優化存儲結構,以便佔用更少的空間,在有些狀況下,能夠省去9/10的空間。
這些特殊編碼對於Redis的使用而言是徹底透明的,事實上,它只是CPU和內存之間的一個交易而言。若是內存使用率方面高一些,那麼在操做數據時消耗的CPU天然要多一些,反之亦然。在Redis中提供了一組配置參數用於設置與特殊編碼相關的各類閾值,如:數組
#若是Hash中字段的數量小於參數值,Redis將對該Key的Hash Value採用特殊編碼。 hash-max-zipmap-entries 64 #若是Hash中各個字段的最大長度不超過512字節,Redis也將對該Key的Hash Value採用特殊編碼方式。 hash-max-zipmap-value 512 #下面兩個參數的含義基本等同於上面兩個和Hash相關的參數,只是做用的對象類型爲List。 list-max-ziplist-entries 512 list-max-ziplist-value 64 #若是set中整型元素的數量不超過512時,Redis將會採用該特殊編碼。 set-max-intset-entries 512
假若某個已經被編碼的值再通過修改以後超過了配置信息中的最大限制,那麼Redis會自動將其轉換爲正常編碼格式,這一操做是很是快速的,可是若是反過來操做,將一個正常編碼的較大值轉換爲特殊編碼,Redis的建議是,在正式作以前最好先簡單測試一下轉換效率,由於這樣的轉換每每是很是低效的。
2、BIT和Byte級別的操做:
從Redis 2.2開始,Redis提供了GETRANGE/SETRANGE/GETBIT/SETBIT四個用於字符串類型Key/Value的命令。經過這些命令,咱們即可以像操做數組那樣來訪問String類型的值數據了。好比惟一標識用戶身份的ID,可能僅僅是String值的其中一段子字符串。這樣就能夠經過GETRANGE/SETRANGE命令來方便的提取。再有就是可使用BITMAP來表示用戶的性別信息,如1表示male,0表示female。用這種方式來表示100,000,000個用戶的性別信息時,也僅僅佔用12MB的存儲空間,與此同時,在經過SETBIT/GETBIT命令進行數據遍歷也是很是高效的。
3、儘量使用Hash:
因爲小的Hash類型數據佔用的空間相對較少,所以咱們在實際應用時應該儘量的考慮使用Hash類型,好比用戶的註冊信息,這其中包括姓名、性別、email、年齡和口令等字段。咱們固然能夠將這些信息以Key的形式進行存儲,而用戶填寫的信息則以String Value的形式存儲。然而Redis則更爲推薦以Hash的形式存儲,以上信息則以Field/Value的形式表示。
如今咱們就經過學習Redis的存儲機制來進一步證實這一說法。在該篇博客的開始處已經提到了特殊編碼機制,其中有兩個和Hash類型相關的配置參數:hash-max-zipmap-entries和hash-max-zipmap-value。至於它們的做用範圍前面已經給出,這裏就再也不過多的贅述了。如今咱們先假設存儲在Hash Value中的字段數量小於hash-max-zipmap-entries,而每一個元素的長度又同時小於hash-max-zipmap-value。這樣每當有新的Hash類型的Key/Value存儲時,Redis都會爲Hash Value建立定長的空間,最大可預分配的字節數爲:
total_bytes = hash-max-zipmap-entries * hash-max-zipmap-value
這樣一來,Hash中全部字段的位置已經預留,而且能夠像訪問數組那樣隨機的訪問Field/Value,他們之間的步長間隔爲hash-max-zipmap-value。只有當Hash Value中的字段數量或某一新元素的長度分別超過以上兩個參數值時,Redis纔會考慮將他們以Hash Table的方式進行從新存儲,不然將始終保持這種高效的存儲和訪問方式。不只如此,因爲每一個Key都要存儲一些關聯的系統信息,如過時時間、LRU等,所以和String類型的Key/Value相比,Hash類型極大的減小了Key的數量(大部分的Key都以Hash字段的形式表示並存儲了),從而進一步優化了存儲空間的使用效率。學習