redis的zset的底層實現_Redis(三)--- Redis的五大數據類型的底層實現

1、簡介

Redis的五大數據類型也稱五大數據對象;前面介紹過6大數據結構,Redis并沒有直接使用這些結構來實現鍵值對數據庫,而是使用這些結構構建了一個對象系統redisObject;這個對象系統包含了五大數據對象,字符串對象(string)、列表對象(list)、哈希對象(hash)、集合(set)對象和有序集合對象(zset);而這五大對象的底層數據編碼可以用命令OBJECT ENCODING來進行查看。

redisObject結構

1 typedef structredisObject {2 //類型

3 unsigned type:4;4 //編碼

5 unsigned encoding:4;6 //指向底層實現數據結構的指針

7 void *ptr;8 //...

9 } robj;

redis是以鍵值對存儲數據的,所以對象又分為鍵對象和值對象,即存儲一個key-value鍵值對會創建兩個對象,鍵對象和值對象。

鍵對象總是一個字符串對象,而值對象可以是五大對象中的任意一種。

type屬性存儲的是對象的類型,也就是我們說的?string、list、hash、set、zset中的一種,可以使用命令 TYPE key?來查看。

encoding屬性記錄了隊形所使用的編碼,即這個對象底層使用哪種數據結構實現。

表中列出了底層編碼常量及對應的OBJECT ENCODING?命令的輸出,前三項都是字符串結構

我們在存入key-value鍵值對時并不會指定對象的encoding,而是Redis會根據不統的使用場景來為一個對象設置不同的編碼,可以達到節約內存、加快訪問速度等目的。

2、字符串對象(string)

字符串對象底層數據結構實現為簡單動態字符串(SDS)和直接存儲,但其編碼方式可以是int、raw或者embstr,區別在于內存結構的不同。

(1)int編碼

字符串保存的是整數值,并且這個正式可以用long類型來表示,那么其就會直接保存在redisObject的ptr屬性里,并將編碼設置為int,如圖:

(2)raw編碼

字符串保存的大于32字節的字符串值,則使用簡單動態字符串(SDS)結構,并將編碼設置為raw,此時內存結構與SDS結構一致,內存分配次數為兩次,創建redisObject對象和sdshdr結構,如圖:

(3)embstr編碼

字符串保存的小于等于32字節的字符串值,使用的也是簡單的動態字符串(SDS結構),但是內存結構做了優化,用于保存頓消的字符串;內存分配也只需要一次就可完成,分配一塊連續的空間即可,如圖:

字符串對象總結:

在Redis中,存儲long、double類型的浮點數是先轉換為字符串再進行存儲的。

raw與embstr編碼效果是相同的,不同在于內存分配與釋放,raw兩次,embstr一次。

embstr內存塊連續,能更好的利用緩存在來的優勢

int編碼和embstr編碼如果做追加字符串等操作,滿足條件下會被轉換為raw編碼;embstr編碼的對象是只讀的,一旦修改會先轉碼到raw。

3、列表對象(list)

列表對象的編碼可以是ziplist和linkedlist之一。

(1)?ziplist編碼

ziplist編碼的哈希隨想底層實現是壓縮列表,每個壓縮里列表節點保存了一個列表元素。

(2)linkedlist編碼

linkedlist編碼底層采用雙端鏈表實現,每個雙端鏈表節點都保存了一個字符串對象,在每個字符串對象內保存了一個列表元素。

列表對象編碼轉換:

列表對象使用ziplist編碼需要滿足兩個條件:一是所有字符串長度都小于64字節,二是元素數量小于512,不滿足任意一個都會使用linkedlist編碼。

兩個條件的數字可以在Redis的配置文件中修改,list-max-ziplist-value選項和list-max-ziplist-entries選項。

圖中StringObject就是上一節講到的字符串對象,字符串對象是唯一個在五大對象中作為嵌套對象使用的。

4、哈希對象(hash)

哈希對象的編碼可以是ziplist和hashtable之一。

(1)ziplist編碼

ziplist編碼的哈希對象底層實現是壓縮列表,在ziplist編碼的哈希對象中,key-value鍵值對是以緊密相連的方式放入壓縮鏈表的,先把key放入表尾,再放入value;鍵值對總是向表尾添加。

(2)hashtable編碼

hashtable編碼的哈希對象底層實現是字典,哈希對象中的每個key-value對都使用一個字典鍵值對來保存。

字典鍵值對即是,字典的鍵和值都是字符串對象,字典的鍵保存key-value的key,字典的值保存key-value的value。

哈希對象編碼轉換:

哈希對象使用ziplist編碼需要滿足兩個條件:一是所有鍵值對的鍵和值的字符串長度都小于64字節;二是鍵值對數量小于512個;不滿足任意一個都使用hashtable編碼。

以上兩個條件可以在Reids配置文件中修改hash-max-ziplist-value選項和hash-max-ziplist-entries選項。

5、集合對象(set)

集合對象的編碼可以是intset和hashtable之一。

(1)intset編碼

intset編碼的集合對象底層實現是整數集合,所有元素都保存在整數集合中。

(2)hashtable編碼

hashtable編碼的集合對象底層實現是字典,字典的每個鍵都是一個字符串對象,保存一個集合元素,不同的是字典的值都是NULL;可以參考java中的hashset結構。

集合對象編碼轉換:

集合對象使用intset編碼需要滿足兩個條件:一是所有元素都是整數值;二是元素個數小于等于512個;不滿足任意一條都將使用hashtable編碼。

以上第二個條件可以在Redis配置文件中修改et-max-intset-entries選項。

6、有序集合對象(zset)

有序集合的編碼可以是ziplist和skiplist之一。

(1)ziplist編碼

ziplist編碼的有序集合對象底層實現是壓縮列表,其結構與哈希對象類似,不同的是兩個緊密相連的壓縮列表節點,第一個保存元素的成員,第二個保存元素的分值,而且分值小的靠近表頭,大的靠近表尾。

(2)skiplist編碼

skiplist編碼的有序集合對象底層實現是跳躍表和字典兩種;

每個跳躍表節點都保存一個集合元素,并按分值從小到大排列;節點的object屬性保存了元素的成員,score屬性保存分值;

字典的每個鍵值對保存一個集合元素,字典的鍵保存元素的成員,字典的值保存分值。

為何skiplist編碼要同時使用跳躍表和字典實現?

跳躍表優點是有序,但是查詢分值復雜度為O(logn);字典查詢分值復雜度為O(1) ,但是無序,所以結合連個結構的有點進行實現。

雖然采用兩個結構但是集合的元素成員和分值是共享的,兩種結構通過指針指向同一地址,不會浪費內存。

有序集合編碼轉換:

有序集合對象使用ziplist編碼需要滿足兩個條件:一是所有元素長度小于64字節;二是元素個數小于128個;不滿足任意一條件將使用skiplist編碼。

以上兩個條件可以在Redis配置文件中修改zset-max-ziplist-entries選項和zset-max-ziplist-value選項。

7、總結

在Redis的五大數據對象中,string對象是唯一個可以被其他四種數據對象作為內嵌對象的;

列表(list)、哈希(hash)、集合(set)、有序集合(zset)底層實現都用到了壓縮列表結構,并且使用壓縮列表結構的條件都是在元素個數比較少、字節長度較短的情況下;

四種數據對象使用壓縮列表的優點:

(1)節約內存,減少內存開銷,Redis是內存型數據庫,所以一定情況下減少內存開銷是非常有必要的。

(2)減少內存碎片,壓縮列表的內存塊是連續的,并分配內存的次數一次即可。

(3)壓縮列表的新增、刪除、查找操作的平均時間復雜度是O(N),在N再一定的范圍內,這個時間幾乎是可以忽略的,并且N的上限值是可以配置的。

(4)四種數據對象都有兩種編碼結構,靈活性增加。

參考:

《Redis設計與實現》黃健宏著,網上對Redis的詳解等

此博客為筆者使用redis很久之后,參考網絡上各類文章總結性書寫,原創手打,如有錯誤歡迎指正。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/396389.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/396389.shtml
英文地址,請注明出處:http://en.pswp.cn/news/396389.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

科學計算機簡單編程_是“計算機科學”還是“編程”?

科學計算機簡單編程by Sam Corcos由Sam Corcos 是“計算機科學”還是“編程”? (Is It “Computer Science” or “Programming”?) 教育政策白皮書(提示:它們不是同一個東西) (An education policy white paper (hint: they’re not the same thing))…

[Matlab] 畫圖命令

matlab畫圖命令,不定時更新以便查找 set(gcf, color, [1 1 1]);     % 使圖背景為白色 alpha(0.4);           %設置平面透明度 plot(Circle1,Circle2,k--,linewidth,1.25);  % k--設置線型  ‘linewidth’,1.25  設置線寬度為1.25 %線型   …

django入門記錄 2

1. 創建一個app, python manage.py startapp appname 2. 設計model,在appname/目錄下編輯好model 3. 檢測model的修改,python manage.py makemigrations appname 4. 自動執行數據庫遷移,并同步管理數據庫結構, python…

spark sql 數據類型轉換_SparkSql 數據類型轉換

1、SparkSql數據類型 1.1數字類型 ByteType:代表一個字節的整數。范圍是-128到127 ShortType:代表兩個字節的整數。范圍是-32768到32767 IntegerType:代表4個字節的整數。范圍是-2147483648到2147483647 LongType:代表8個字節的整數。范圍是-9223372036854775808到92233720…

【Python】 list dict str

list & dict & str 這三種類型是python中最常用的幾種數據類型。他們都是序列的一種 ■  序列通用操作 1. 分片 s[a:b] 返回序列s中從s[a]到s[b-1]的片段。注意s[0:0]是空集而不是s[0] s[a:b:c]  加入第三個參數以設置取樣步長。可以設置成負數來從右向左取樣 2. 加…

終端terminal的顏色配置

PS1 color 終端terminal的顏色配置 PS1"\[\e[92;1m\][\u\e[90;5m\e[25m\[\e[91;4m\]Atlas\e[24m\[\e[1m\]\[\e[92;1m\] \W ]\\$\[\e[0m\]" Set CodeDescriptionExamplePreview1Bold/Bright echo -e "Normal \e[1mBold" 2Dim echo -e "Normal \e[2mDi…

速度與激情的Webpack

Also published in my tech blog也發布在我的技術博客中 This is a guide that is meant to help you ease your development workflow and save your time by using a bunch of awesome tools that you’ve read about on the internet (does React Hot Loader ring any bells…

java nio socket長連接_nio實現Socket長連接和心跳

前段時間用bio方式,也就是傳統io實現了socket的長連接和心跳,總覺著服務端開啟多線程管理socket連接的方式過于消耗資源,數據并發的情況下可能會影響到性能,因此就嘗試使用nio改進原來的代碼。然而改進的過程卻不像我起初設想的那…

unity讓對象作為參數_C#+Unity學習筆記:類與對象

參考文獻蜜酒廳通訊社 游戲部 石中居士對象(object):有狀態、行為和身份的東西。狀態(state):表示物體特征的信息,可以用來跟蹤對象的狀態。屬性(properties):因為編程人員需要把控對象的狀態,所以要對其進行訪問。通過…

Tomcat 報 The valid characters are defined in RFC 7230 and RFC 3986

問題 24-Mar-2017 23:43:21.300 INFO [http-apr-8001-exec-77] org.apache.coyote.http11.AbstractHttp11Processor.process Error parsing HTTP request header Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level. java.lang.IllegalAr…

Linux Kernel Oops異常分析

0.linux內核異常常用分析方法 異常地址是否在0附近,確認是否是空指針解引用問題異常地址是否在iomem映射區,確認是否是設備訪問總線異常問題,如PCI異常導致的地址訪問異常異常地址是否在stack附近,如果相鄰&#xff0c…

Centos7.5 VMtools的安裝與卸載

一、安裝1、自帶tools: 選擇VMware工具欄 > 虛擬機 > 安裝VMtools2、掛載光驅3、tar -zxvf VMwareTools-10.3.2-9925305.tar.gz(這里以tar文件為例)4、切換到目標目錄,執行(一定要使用root權限執行)…

gitter 卸載_最佳Gitter渠道:開發人員工具

gitter 卸載by Gitter通過吉特 最佳Gitter渠道:開發人員工具 (Best Gitter channels: Developer Tools) Developer tools have become essential to any kind of serious software development, also in the open source setting. They can ease the daily develop…

java 過濾腳本_我寫的得到天氣的Java代碼,其中有過濾腳本和過濾HTMLtag的函數。...

public class WeatherFilter{private String html;private String target"http://weather.news.sohu.com/query.php?city北京";public WeatherFilter()throws Exception{this(null);}public WeatherFilter(String targetIn)throws Exception{if(targetIn!null)this.…

【懶癌發作】收集各種懶癌發作時用程序寫作業的程序

updata:20170621 好的,已經是準高一了,現在看起來太蠢了。。。 -------------------------------------------------------------------------------------- 要真正的運用,程序一定是要來解決實際問題的——比如作業(懶就直說&…

50歐姆線設計 高頻pcb_硬件設計基礎100問(三)

硬件基礎知識問答今天依舊是節前知識儲備哦,jacky大神整理的硬件基礎知識很細致,第三彈學起來!01 1、晶體管基本放大電路有共射、共集、共基三種接法,請簡述這三種基本放大電路的特點。共射:共射放大電路具有放大電流和…

如何正確實現 Java 中的 HashCode

相等 和 Hash Code 從一般角度來看,Equality 是不錯的,但是 hash code 更則具技巧性。如果我們在 hash code上多下點功夫,我們就能了解到 hash code 就是用在細微處去提升性能的。 大部分的數據結構使用equals去檢查是否他們包含一個元素。例…

一億小目標成就_成就卓越的一種方式:自我選擇

一億小目標成就by Prosper Otemuyiwa通過Prosper Otemuyiwa 成就卓越的一種方式:自我選擇 (One way to Greatness: Pick Yourself) I’ve heard many people say this: “I want to be great”, but most people only just have wild thoughts & imaginations …

java操作文件愛女_Java的IO操作---File類

目標1)掌握File類作用2)可以使用file類中方法對文件進行讀寫操作。File類唯一與文件有關的類。使用file類可進行創建或刪除操作,要想使用File類,首先觀察File類的構造方法。public File(String pathname);實例化File類的時候,必須設置好路徑。…

openssl創建私有ca

openssl創建私有ca1.ssl大概內容PKI:公鑰基礎設施結構CA:證書權威機構,PKI的核心CRL:證書吊銷列表,使用證書之前需要檢測證書有效性證書存儲格式常見的X509格式包含內容 公鑰有效期限證書的合法擁有人證書該如何使用CA的信息CA簽名…