一、是二進制安全的,也就是說,你可使用任何形式的二進制序列來做爲key,好比一個string,或者一個jpg圖片的數據,須要說明的是,空字符串也是一個有效的key。node
二、不建議使用過長的key,影響內存佔用及數據查性能,對於過長的key,能夠經過hash(例如SHA1)處理轉換。redis
三、建議使用有意義及統一格式的key。json
四、最大容許key大小爲512M。緩存
一、做爲原子計數器:incr、decr、incrby安全
二、結合append命令,做爲基於時間的增量序列。數據結構
三、隨機訪問及獲取值區域,getrange、setrange。app
附:須要注意的是append及range操做容易引發內存浪費和碎片化問題。性能
一、單個hash最多支持232 - 1個鍵值對。優化
二、關於hash類型的內部編碼:ziplist(壓縮列表) & hashtable(哈希表)編碼
配置:hash-max-ziplist-entries(hash類型最大kv數據,默認512)、hash-max-ziplist-value(單個v值最大值, 默認64)
redis 採用何種結構取決於hash中元素數及元素值得大小,當同時知足小於配置時,redis使用ziplist編碼存儲,不然會轉化爲hashtable。
ziplist編碼使用更加緊湊的結構實現多個元素的連續存儲,所以佔用的內存更小。
當數據類型沒法知足配置條件,此時使用ziplist編碼存儲讀寫效率會降低,因此轉換使用hashtable編碼存儲(O(1)時間複雜度)。
示例:添加 testuser hash類型key,前後設置元素name、desc不一樣長度元素值,分別查看內部編碼類型
redis 對象內部存儲形態。
一、type:數據類型、例如sting、hash、list、set、zset等,值類型查看命令【type】。
二、encoding:值存儲內部實現的數據結構,具體能夠參考第七部分。
三、lru:最後一次被訪問時間,輔助回收,能夠經過 object idletime {key} 在不更新lru屬性狀況下查看key的空閒時間。
四、refcount:當前對象被引用次數,輔助回收,能夠經過 object refcount {key} 查看引用數,當對象爲整數且值在範圍在[0-9999]時,redis能夠經過共享對象的方式來節省內存。
目前共享對象池只對整數設置了0~9999個共享對象,一方面整數對象池複用率最大,同時等值判斷上時間複雜度爲O(1)。
五、*ptr:數據存儲或指向,數據自己或者指向數據的指針,redis3.0以後,長度在39之內的字符串數據,內部編碼爲embstr,內存建立時,字符串和redisObject一塊兒分配,減小一次內存分配。
simple dynamic string:redis內部自定義簡單動態字符串結構。
一、字符串屬性的O(1)時間複雜度獲取。
二、空間與分配、減小內存再分配。
三、惰性刪除機制,字符串縮減後空間不釋放,做爲預分配空間保留。
6、關於對象屬性存儲:json or hash
對象屬性存儲能夠經過總體json存儲或者hash kv存儲。具體應用選擇,能夠結合總體對象大小及屬性操做需求來決定。
對於頻繁總體操做,且對象數據量較小的通常採用json字符串類型存儲。
對於多對象屬性層級操做情景,可能hash會比較合適。
如上圖,同一種數據類型,能夠有多種不一樣內部編碼存儲形式。具體redis採用那種編碼形式與實際應用的數據值類型相關,如上述第三部分論述hash類型的編碼轉換。
數據的編碼類型在數據寫入的時候肯定,不可變換,且只能向大內存編碼行使轉換。
以下,從新設置 testuser desc值,testuser對象的編碼形式保持不變:
編碼轉換時機:
經過第七節,咱們能夠看到hash、list、zset底層都有應用這種存儲結構。
基本特色:
一、連續性內存存儲。
二、能夠模擬雙向鏈表,O(1)時間複雜度內出入隊操做。
三、讀寫性能跟數據的元素個數及值長度相關,適合存儲小對象和長度有限的數據。
四、數據增刪涉及複雜的內存操做。
ziplist基本結構:
一、zlbytes:int32類型、4字節,ziplist總體字節長度。
二、zltail:int32類型、4字節,記錄距離尾節點偏移量,用於尾節點彈出。
三、zllen:int16類型,2字節,ziplist節點數量。
四、entry:數據節點,長度不定。
entry 即鏈表node,內部結構包含:
prev_entry_bytes_length:前一個節點所佔用的空間,用戶快速定位。
encoding:當前數據節點編碼類型及長度,前兩位標識編碼類型,其他標識數據長度。
contents:節點數據值。
五、zlend:1字節,記錄列表結尾。
redis內存消耗包括自身內存,鍵值對象佔用、緩衝區內存佔用及內存碎片佔用。
一、緩衝區內存:包括客戶端緩存、複製及壓緩衝區及AOF緩衝區。
二、內存碎片:固定範圍內存塊兒分配。
redis默認使用jemalloc內存分配器,其它包括glibc、tcmalloc。
內存分配器會首先將可管理的內存分配爲規定不一樣大小的內存塊以備不一樣的數據存儲需求,可是,咱們知道實際應用中須要存儲的數據大小不一,規範不一,內存分配器只能選擇最接近數據需求大小的內存塊兒進行分配,這樣就伴隨着「佔不滿」空間的碎片浪費。
jemalloc針對內存碎片有相應的優化策略,正常碎片率爲mem_fragmentation_ratio在1.03左右。
第二部分咱們說過,對string值得頻繁append及range操做會會致使內存碎片問題,另外,第七部分,SDS惰性內存回收也會致使內存碎片,同時過時鍵內存回收也伴隨着所釋放空間的沒法充分利用,致使內存碎片率上升的問題。
碎片處理:
應用層面:儘可能避免差別化的鍵值使用,作好數據對齊。
redis服務層面:能夠經過重啓服務,進行碎片整理。
三、maxmemory及maxmemory-policy控制redis最大可用內存及內存回收。須要注意的是內存回收執行影響redis的性能,避免頻繁的內存回收開銷。