Redis數據類型及編碼

Redis數據類型及編碼

說到Redis的數據類型,我們大概會很快想到Redis的5種常見的數據類型:字符串(String)、列表(List)、散列(Hash)、集合(Set)、有序集合(Sorted Set),以及他們的特點和運用場景及常用命令。不過在講五大數據類型之前,我們有必要看一下redis中的全局操作命令,下面列出了一些常用的操作及其時間複雜度和使用場景。

在這裏插入圖片描述

全局命令中大多都是針對key的屬性設置和修改,除了全局操作以外,redis的五個常用數據類型也有自己的單獨對的操作命令,我們下面就來一個個看一下,順便把這些數據類型的內部原理也大概瞭解一下。

在這裏插入圖片描述

要講內部原理,首先我們得看看redis中有多少種編碼方式:

/* Objects encoding. Some kind of objects like Strings and Hashes can be
 * internally represented in multiple ways. The 'encoding' field of the object
 * is set to one of this fields for this object. */
#define OBJ_ENCODING_RAW 0     /* Raw representation */
#define OBJ_ENCODING_INT 1     /* Encoded as integer */
#define OBJ_ENCODING_HT 2      /* Encoded as hashtable */
#define OBJ_ENCODING_ZIPMAP 3  /* Encoded as zipmap */ // 已廢棄
#define OBJ_ENCODING_LINKEDLIST 4 /* Encoded as regular linked list */
#define OBJ_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
#define OBJ_ENCODING_INTSET 6  /* Encoded as intset */
#define OBJ_ENCODING_SKIPLIST 7  /* Encoded as skiplist */
#define OBJ_ENCODING_EMBSTR 8  /* Embedded sds string encoding */
#define OBJ_ENCODING_QUICKLIST 9 /* Encoded as linked list of ziplists */

不懂這些編碼方式不要緊,後面都會講到。下面我們就從五個數據類型出發,依次講解。

(一)String 字符串

string是redis最基本的數據類型,一個key對應一個value。string類型是二進制安全的,意思是redis的string可以包含任何數據,比如圖片或者序列化的對象 等等。string類型是redis最基本的數據類型,一個鍵最大能存儲512MB的數據。String 數據結構是簡單的 key-value 類型。

string類型一共有三種編碼方式,分別是int,raw, embstr。

1.int編碼

字符串對象保存的值是一個整數值,並且這個整數值在 long 的範圍內,那麼 redis 用整數值來保存這個信息,字符串編碼設置爲int。

2.raw編碼

字符串對象保存的是一個字符串,長度大於 32 個字節,就會使用SDS(簡單動態字符串)數據結構來保存這個字符串值,並且將字符串對象的編碼設置爲raw。

3.embstr編碼

字符串對象保存的是一個字符串,長度小於 32 個字節,會使用embstr來保存,embstr編碼是對SDS的一個優化,採用連續的空間保存,即將SDS的值和字符串對象的值放在一塊連續的內存空間上。主要用於爲使用較小的字符串對象時提高效率。另外,embstr編碼是隻讀的,只要發生修改操作,就會將編碼轉換成raw再進行操作。

PS:若字符串保存的爲浮點數,那麼浮點數將先被轉化爲字符串,再根據上面的三種情況來選擇編碼方式。浮點數在進行操作時時,需要從字符串轉換成浮點數進行計算,然後再轉換成字符串進行保存。

在這裏插入圖片描述

(二)Hash 哈希

hash類型很像一個關係型數據庫的數據表,hash的Key是一個唯一值,Value部分是一個 hashmap的結構。hash數據類型在存儲對象時具有比 string 類型更靈活、更快的優勢,具體的說,使用 string 類型存儲,必然需要轉換和解析 json 格式的字符串,即便不需要轉換,在內存開銷方面,還是 hash 更佔優勢。hash的模型基本上是這樣:

在這裏插入圖片描述
哈希對象的編碼有ziplist和hashtable。

1.ziplist編碼

鍵值對的鍵和值的長度都小於 64 字節,且鍵值對個數小於 512時,使用ziplist編碼,底層數據結構使用ziplist,用兩個連續的ziplist節點來表示哈希對象中的一個鍵值對。

2.hashtable編碼

鍵值對的鍵或值的長度大於 64 字節,或鍵值對個數大於512時使用hashtable編碼,底層數據結構使用hashtable。哈希在結構上和hashtable非常相似,因此哈希對象中的每一個鍵值對都是hashtable中的一個鍵值對。

在這裏插入圖片描述

(三)List 列表

redis中的列表是簡單的字符串列表,按照插入順序排序。你可以添加一個元素到列表的頭部(左邊)或者尾部(右邊),就像一個雙向隊列。

在這裏插入圖片描述

list類型經常會被用於消息隊列的服務,以完成多程序之間的消息交換。在較老版本中(好像是3.2以下),list一共使用了兩種數據結構:壓縮鏈表和雙向鏈表。當元素數量較少的時候,使用壓縮列表,當元素數量增多,就使用雙向鏈表。

但是在3.2之後,一個新的數據結構——快速列表(quicklist)出現了,這個數據結構現在已經成爲了所有列表的底層實現。

在這裏插入圖片描述

(四)Set 集合

set 就是一個集合,集合的概念就是一堆不重複值的組合。利用redis提供的set數據類型,可以存儲一些集合性的數據。redis的set是string類型的無序集合。集合最大的優勢在於可以進行交集並集差集操作。Set可包含的最大元素數量是4294967295。

在這裏插入圖片描述
集合對象的編碼有intset和hashtable。

1.intset編碼

集合中的所有元素都是整數,且數量不大於 512 個的時候,使用 intset 編碼。intset 編碼底層使用intset數據結構。

2.hashtable編碼

元素不符合全部爲整數值且元素個數小於 512時,集合對象使用的編碼方式爲 hashtable。hashtable的每一個鍵都是一個字符串對象,其中保存了集合裏的一個元素,hashtable的值全部被設置爲NULL。

在這裏插入圖片描述

(五)Sorted Set 有序集合

和set相比,sorted set是將set中的元素增加了一個權重參數score,使得集合中的元素能夠按 score進行有序排列。sorted set 和set一樣也是string類型元素的集合,且不允許重複的成員,不同的是每個元素都會關聯一個double類型的分數。redis正是通過分數來爲集合中的成員進行從小到大的排序。set的成員是唯一的,但分數(score)卻可以重複。sorted set是插入有序的,即自動排序。

有序集合對象的編碼有ziplist和skiplist。

1.ziplist編碼

當元素數量少於128且所有元素成員的長度小於64字節時使用ziplist編碼,有序集合對象的實現數據結構爲ziplist, 每個集合的元素 (key-value), 使用兩個緊挨着的ziplist的節點來表示,第一個節點保存集合元素的成員 (member), 第二個節點保存集合元素的分數(score)。在壓縮列表的內部,集合元素按照分值從小到大進行排序。

2.skiplist編碼

當元素數量大於128且所有元素成員的長度大於64字節時使用skiplist編碼,內部使用zset來實現數據的保存。

在這裏插入圖片描述

最後,我們總結一下五種數據類型和所用的編碼:

在這裏插入圖片描述
2020年4月28日

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章