關注我,能夠獲取最新知識、經典面試題以及微服務技術分享面試
在Redis中會涉及不少數據結構,好比SDS,雙向鏈表、字典、壓縮列表、整數集合等等。Redis會基於這些數據結構自定義一個對象系統,並且自定義的對象系統有不少好處。redis
經過對如下的Redis對象系統的學習,能夠了解Redis設計原理以及初衷,爲了咱們在使用Redis的時候,更加可以理解到其原理和定位問題。數據庫
Redis基於上述的數據結構自定義一個Object 系統,Object結構:數據結構
redisObject結構: typedef struct redisObject{ //類型 unsigned type:4; //編碼 unsigned encoding:4; //指向底層實現數據結構的指針 void *ptr; ….. }
Object 系統包含五種Object:app
Redis使用對象來表示數據庫中的鍵和值,即每新建一個鍵值對,至少建立有兩個對象,並且使用對象的具備如下好處:微服務
1. redis能夠在執行命令前會根據對象的類型判斷一個對象是否能夠執行給定的命令 2. 針對不一樣的使用場景,爲對象設置不一樣的數據結構實現,從而優化對象的不一樣場景夏的使用效率 3. 對象系統還能夠基於引用計數計數的內存回收機制,自動釋放對象所佔用的內存,或者還可讓多個數據庫鍵共享同一個對象來節約內存。 4. redis對象帶有訪問時間記錄信息,使用該信息能夠進行優化空轉時長較大的key,進行刪除!
對象的ptr指針指向對象的底層現實數據結構,而這些數據結構由對象的encoding屬性決定,對應關係:學習
編碼常量 | 編碼對應的底層數據結構 |
---|---|
REDIS_ENCODING_INT | long類型的整數 |
REDIS_ENCODING_EMBSTR | embstr編碼的簡單動態字符串 |
REDIS_ENCODING_RAW | 簡單動態字符串 |
REDIS_ENCODING_HT | 字典 |
REDIS_ENCODING_LINKEDLIST | 雙向鏈表 |
REDIS_ENCODING_ZIPLIST | 壓縮列表 |
REDIS_ENCODING_INTSET | 整數集合 |
REDIS_ENCODING_SKIPLIST | 跳躍表和字典 |
每種Object對象至少有兩種不一樣的編碼,對應關係:優化
類型 | 編碼 | 對象 |
---|---|---|
String | int | 整數值實現 |
String | embstr | sds實現 <=39 字節 |
String | raw | sds實現 > 39字節 |
List | ziplist | 壓縮列表實現 |
List | linkedlist | 雙端鏈表實現 |
Set | intset | 整數集合使用 |
Set | hashtable | 字典實現 |
Hash | ziplist | 壓縮列表實現 |
Hash | hashtable | 字典使用 |
Sorted set | ziplist | 壓縮列表實現 |
Sorted set | skiplist | 跳躍表和字典 |
字符串對象編碼能夠int 、raw或者embstr,若是保存的值爲整數值且這個值能夠用long類型表示,使用int編碼,其餘編碼相似。ui
好比:int編碼的String Object編碼
redis> set number 520 ok redis> OBJECT ENCODING number "int"
String Object結構:
### String 對象之間的編碼轉換
int編碼的字符串對象和embstr編碼的字符串對象在條件知足的狀況下,會被轉換爲raw編碼的字符串對象。
好比:對int編碼的字符串對象進行append命令時,就會使得原來是int變爲raw編碼字符串
list對象能夠爲ziplist或者爲linkedlist,對應底層實現ziplist爲壓縮列表,linkedlist爲雙向列表。
Redis>RPUSH numbers 「Ccww」 520 1
用ziplist編碼的List對象結構:
用linkedlist編碼的List對象結構:
當list對象能夠同時知足如下兩個條件時,list對象使用的是ziplist編碼:
1. list對象保存的全部字符串元素的長度都小於64字節 2. list對象保存的元素數量小於512個,
不能知足這兩個條件的list對象須要使用linkedlist編碼。
Hash對象的編碼能夠是ziplist或者hashtable
其中,ziplist底層使用壓縮列表實現:
hashtable底層使用字典實現,Hash對象種的每一個鍵值對都使用一個字典鍵值對保存:
好比:HSET命令
redis>HSET author name "Ccww" (integer) redis>HSET author age 18 (integer) redis>HSET author sex "male" (integer)
ziplist的底層結構:
hashtable底層結構:
當list對象能夠同時知足如下兩個條件時,list對象使用的是ziplist編碼:
1. list對象保存的全部字符串元素的長度都小於64字節 2. list對象保存的元素數量小於512個,
不能知足這兩個條件的hash對象須要使用hashtable編碼
Note:這兩個條件的上限值是能夠修改的,可查看配置文件hash-max-zaiplist-value和hash-max-ziplist-entries
Set對象的編碼能夠爲intset或者hashtable
inset編碼Set對象結構:
redis> SAD number 1 3 5
hashtable編碼Set對象結構:
redis> SAD Dfruits 「apple」 "banana" " cherry"
使用intset編碼:
1. set對象保存的全部元素都是整數值 2. set對象保存的元素數量不超過512個
不能知足這兩個條件的Set對象使用hashtable編碼
ZSet對象的編碼 能夠爲ziplist或者skiplist
ziplist編碼,每一個集合元素使用相鄰的兩個壓縮列表節點保存,一個保存元素成員,一個保存元素的分值,而後根據分數進行從小到大排序。
ziplist編碼的ZSet對象結構:
Redis>ZADD price 8.5 apple 5.0 banana 6.0 cherry
skiplist編碼的ZSet對象使用了zset結構,包含一個字典和一個跳躍表
Type struct zset{ Zskiplist *zsl; dict *dict; ... } skiplist編碼的ZSet對象結構
當ZSet對象同時知足如下兩個條件時,對象使用ziplist編碼
1. 有序集合保存的元素數量小於128個 2. 有序集合保存的全部元素的長度都小於64字節
不能知足以上兩個條件的有序集合對象將使用skiplist編碼。
Note:能夠經過配置文件中zset-max-ziplist-entries和zset-max-ziplist-vaule