溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Redis五大數(shù)據(jù)類型分別是什么

發(fā)布時間:2021-06-23 10:14:05 來源:億速云 閱讀:139 作者:chen 欄目:大數(shù)據(jù)

本篇內(nèi)容主要講解“Redis五大數(shù)據(jù)類型分別是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“Redis五大數(shù)據(jù)類型分別是什么”吧!

上一篇文章有提到,Redis中使用最頻繁的有5種數(shù)據(jù)類型:String、List、Hash、Set、SortSet。上一篇文章只是單純介紹了下這5種數(shù)據(jù)類型使用到的指令以及常用場景,本篇文章會談?wù)?種數(shù)據(jù)類型的底層數(shù)據(jù)結(jié)構(gòu)以及各自常用的操作命令來分別進行解析。Redis作為目前最流行的Key-Value型內(nèi)存數(shù)據(jù)庫,不僅數(shù)據(jù)庫操作在內(nèi)存中進行,并且可定期的將數(shù)據(jù)持久化到磁盤中,所以性能相對普通數(shù)據(jù)庫高很多,而在Redis中,每個Value實際上都是以一個redisObject結(jié)構(gòu)來表示: typedef struct redisObject{ unsigned type:4; unsigned encoding:4; void *ptr; int refCount; unsigned lru: } 我們可以看看這幾個參數(shù)分別的含義:

  • type:對象的數(shù)據(jù)類型,一般情況就是5大數(shù)據(jù)類型。

  • encode:redisObject對象底層編碼實現(xiàn),主要編碼類型有簡單動態(tài)字符串,鏈表,字典,跳躍表,整數(shù)集合及壓縮列表。

  • *ptr:指向底層實現(xiàn)數(shù)據(jù)結(jié)構(gòu)的指針。

  • refCount:計數(shù)器,當(dāng)引用計數(shù)值為0將會釋放對象。

  • lru:最后一次訪問本對象的時間。

String數(shù)據(jù)類型

String 數(shù)據(jù)結(jié)構(gòu)是簡單的 Key-Value 類型,是Redis中最常用的一種數(shù)據(jù)類型,Value 可以是string或者數(shù)字。String數(shù)據(jù)類型實際上可以存儲字符串、整數(shù)、浮點數(shù)三種不同類型的值,Redis是如何做到自動識別字符串、整數(shù)、浮點數(shù)三種不同類型的值。Redis是使用C實現(xiàn)的,但是并未使用C中的字符串,實際上Redis自己實現(xiàn)了一個結(jié)構(gòu)體SDS來替代String類型: struct sdshdr{ //記錄buf數(shù)組中已使用字節(jié)的長度 int len; //記錄buf數(shù)組中剩余空間的長度 int free; //字節(jié)數(shù)組,用于存儲字符串 char buf[]; };

我們可以看到free參數(shù)是用來判斷剩余可使用空間的長度,len表示字符串的長度,buf存儲字符串的每一個字符以及結(jié)尾的'\0'。為什么Redis要自己實現(xiàn)SDS結(jié)構(gòu)體呢?因為SDS結(jié)構(gòu)體有幾個優(yōu)點:

  • 由于len保存了當(dāng)前字符串的實際長度,所以獲取長度時間復(fù)雜度為O(1)。


  • SDS在拼接之前會對當(dāng)前字符串的空間進行自動調(diào)整和擴展,防止當(dāng)前字符串?dāng)?shù)據(jù)溢出。


  • 減少內(nèi)存分配次數(shù),SDS拼接字符串發(fā)生時,如果此時的字符串長度len小于1M,則SDS會分配和len大小相同的未使用空間給free,如果此時的字符串長度len大于1M,則SDS會分配和1M的未使用空間給free,當(dāng)字符串縮短時,縮短的空間會疊加到free中,用于后續(xù)的拼接使用。


String數(shù)據(jù)類型常用命令:

  • 常用命令:set、get、decr、incr、mget 等。

String數(shù)據(jù)類型適用場景:

  • 分布式鎖

  • 分布式session:將分布式應(yīng)用session存儲到Redis中

  • 商品秒殺

  • 常規(guī)計數(shù):博客數(shù),閱讀數(shù)

List數(shù)據(jù)類型 List數(shù)據(jù)結(jié)構(gòu)是用來存儲多個有序的字符串,List中的每個字符串成為元素,List提供了節(jié)點重排和節(jié)點順序訪問的能力,在Redis中,List可以在兩端push和pop元素,還可以獲取指定范圍的元素列表,獲取指定索引下標的元素等,List數(shù)據(jù)結(jié)構(gòu)主要有zipList(壓縮鏈表)和LinkedList(雙向鏈表)兩種實現(xiàn)方式。首先我們可以先看看LinkedList的結(jié)構(gòu): type struct list{ //表頭節(jié)點 listNode *head; //表尾節(jié)點 listNode *tail; //包含的節(jié)點總數(shù) unsigned long len; };

可以看到每個LinkedList中都會包含一個表頭節(jié)點head和一個表尾結(jié)點tail,在LinkedList中每個節(jié)點都會有一個prev指向前一個元素,同時還有一個next指向后一個元素,每個節(jié)點的value就是節(jié)點的值。從而實現(xiàn)雙向鏈表,理解起來實際上和C中的雙向鏈表有很大程度的相似性。而另一種實現(xiàn)方式zipList是基于連續(xù)內(nèi)存實現(xiàn),有點類似于數(shù)組方式,但是和數(shù)組有點不一致的是zipList的每一個entry的大小可能不一致,需要特殊方法去控制解決,但是在執(zhí)行push,pop操作時會有數(shù)據(jù)的遷移,時間復(fù)雜度為O(n), 所以一般只有在元素較少時才會使用zipList,我們可以看看zipList的結(jié)構(gòu):

type struct ziplist{ //整個壓縮列表的字節(jié)數(shù) uint32_t zlbytes; //記錄壓縮列表尾節(jié)點到頭結(jié)點的字節(jié)數(shù),直接可以求節(jié)點的地址 uint32_t zltail_offset; //記錄了節(jié)點數(shù),有多種類型,默認如下 uint16_t zllength; //節(jié)點 List entryX; }

zipList中每個節(jié)點都會有以下幾個參數(shù)信息:

  • previous_entry_length:記錄前一個節(jié)點的字節(jié)長度

  • content:節(jié)點所存儲的內(nèi)容,可以是一個字節(jié)數(shù)組或者整數(shù)

  • encoding:記錄content屬性中所保存的數(shù)據(jù)類型以及長度

*** List數(shù)據(jù)類型適用場景**

在渲染文章列表時可以使用List數(shù)據(jù)類型,一般情況下每個用戶都會有自己發(fā)布的文章列表,如果需要展示文章列表,就可以使用List數(shù)據(jù)類型,不但可以有序而且可以按照索引范圍去查詢文章列表。

Set數(shù)據(jù)類型

Set數(shù)據(jù)類型和List數(shù)據(jù)類型有點類似,也可以用來保存多個元素,但最大的一點區(qū)別在于Set數(shù)據(jù)類型不允許出現(xiàn)重復(fù)的元素,并且Set中的元素是無序的,所以沒辦法和List一樣通過索引下標獲取元素,但是Set類型支持多個Set集合取交集、并集、差集,所以合理使用Set數(shù)據(jù)類型,可以在實際項目開發(fā)中解決很多問題。Set數(shù)據(jù)類型有兩種數(shù)據(jù)結(jié)構(gòu):IntSet和HashTable。首先我們來看看IntSet的結(jié)構(gòu):

typedef struct intset { // 編碼方式 uint32_t enconding; // 集合包含的元素數(shù)量 uint32_t length; // 保存元素的數(shù)組 int8_t contents[]; } intset;

當(dāng)Set集合中所有元素都為整型時,Redis才會使用IntSet數(shù)據(jù)結(jié)構(gòu)。有一點需要格外注意的是:IntSet數(shù)據(jù)結(jié)構(gòu)是有序的。因為為了減輕性能的消耗,Redis在Set集合元素都為整型時,會使用一種基于動態(tài)數(shù)組的結(jié)構(gòu)體,同時在push元素的時候控制元素的大小順序,這樣就可以使用二分查找算法來對元素進行push及pop操作,這樣時間復(fù)雜度僅為O(logN)。在Set集合中元素存在非整型數(shù)據(jù)時,Redis這時會自動采用HashTable數(shù)據(jù)結(jié)構(gòu)來存放數(shù)據(jù),在HashTable中,存放的只有key值而沒有value值,所以說在HashTable中,鍵值永遠為null。我們可以看下HashTable的結(jié)構(gòu):

typedef struct dict{ //類型特定函數(shù) dictType *type; //哈希表 兩個,一個用于實時存儲,一個用于rehash dictht ht[2]; //rehash索引 數(shù)據(jù)遷移時使用 unsigned rehashidx; }

Set數(shù)據(jù)類型使用場景:

  • 記錄唯一值:比如登錄ip,身份證號

  • 添加標簽:可以通過標簽的交并集計算用戶喜好程度等數(shù)據(jù)。

Hash數(shù)據(jù)類型 在Redis中哈希類型是指鍵本身又是一種鍵值對結(jié)構(gòu),也就是我們所說的對象,所以Hash數(shù)據(jù)類型用來存儲對象是最合適的數(shù)據(jù)類型。Hash數(shù)據(jù)類型的編碼可以是zipList或HashTable。當(dāng)哈希對象保存的所有鍵值對長度小于64字節(jié)并且元素數(shù)量少于512時使用zipList,否則使用HashTable。zipList與剛才List數(shù)據(jù)類型中講到的zipList實際上基本一致,唯一區(qū)別在于Hash存儲entry數(shù)量成對增加,所以長度一定為2的整數(shù)倍。當(dāng)然,使用zipList剛才已經(jīng)說過push和pop時間復(fù)雜度為O(n),所以只能在數(shù)據(jù)量少的情況下才允許使用。而HashTable其實有點類似于Java中的HashTable,HashTTable主要依賴于三個結(jié)構(gòu):dict、dictht、entry。三個結(jié)構(gòu)的關(guān)系可以表示為如下這幅圖: Redis五大數(shù)據(jù)類型分別是什么

Hash數(shù)據(jù)類型適用場景:

  • 存儲對象數(shù)據(jù)。

  • 結(jié)合Json描述對象集合。

SortSet數(shù)據(jù)類型

有序集合是在Set集合的基礎(chǔ)上,保留了Set集合中不能存在重復(fù)元素的特性,但是不同的是,SortSet集合中元素是可以排序的,SortSet排序和List排序都可以使用索引下標作為排序依據(jù),所以說SortSet實現(xiàn)了數(shù)據(jù)有序且鍵值對唯一的集合,SortSet的數(shù)據(jù)結(jié)構(gòu)有兩種:zipList和skipList + HashTable,zipList都不用多少了,是用于數(shù)據(jù)量較少的情況,默認排序為元素從小到大。而采用skipList + HashTable的數(shù)據(jù)結(jié)構(gòu),skipList會在保證集合有序的情況下優(yōu)化范圍查找的時間復(fù)雜性,而HashTable剛才已經(jīng)提到過它可以優(yōu)化push和pop元素時的時間復(fù)雜性。skipList基于有序鏈表,可以創(chuàng)建多層索引,實現(xiàn)以空間復(fù)雜度來換取時間復(fù)雜度的做法,最終實現(xiàn)時間復(fù)雜度為O(logN)的元素查詢過程,當(dāng)需要push或者pop元素時,則使用HashTable實現(xiàn)時間復(fù)雜度僅為O(1).

SortSet數(shù)據(jù)類型適用場景

  • 積分排行榜:根據(jù)積分排序從小到大

  • 獲取某個范圍的數(shù)據(jù):考試80-100分的數(shù)據(jù)

到此,相信大家對“Redis五大數(shù)據(jù)類型分別是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI