Redis數(shù)據(jù)結(jié)構(gòu)中的String類(lèi)型有哪些

這篇文章主要介紹“redis數(shù)據(jù)結(jié)構(gòu)中的String類(lèi)型有哪些”,在日常操作中,相信很多人在Redis數(shù)據(jù)結(jié)構(gòu)中的String類(lèi)型有哪些問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Redis數(shù)據(jù)結(jié)構(gòu)中的String類(lèi)型有哪些”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

創(chuàng)新互聯(lián)公司2013年至今,先為永清等服務(wù)建站,永清等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為永清企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問(wèn)題。

Redis數(shù)據(jù)結(jié)構(gòu)中的String類(lèi)型有哪些

Redis常用作分布式KV緩存,很多人僅僅只會(huì)使用,卻不知道底層卻有著很多不為人知的秘密。

String類(lèi)型

String作為Redis支持的最基礎(chǔ)的數(shù)據(jù)類(lèi)型,首先我們來(lái)看下String,他的數(shù)據(jù)結(jié)構(gòu)和存儲(chǔ)是怎么樣的。

重新定義SDS 去存儲(chǔ)String

眾所周知,redis是用c語(yǔ)言進(jìn)行編寫(xiě)的,而c語(yǔ)言是沒(méi)有String類(lèi)型的,只有char[],并且在初始化的是時(shí)候就必須大小指定類(lèi)型后就不能改變。為了實(shí)現(xiàn)動(dòng)態(tài)增加和擴(kuò)展等功能,如incr命令,append命令,所以redis就自己定義維護(hù)了一個(gè)SDS(Simple Dynamic String)來(lái)實(shí)現(xiàn)這些功能。

我們先來(lái)看一下redis源碼中定義的數(shù)據(jù)結(jié)構(gòu),這里有5種類(lèi)型,目的是為了節(jié)省空間。

Redis數(shù)據(jù)結(jié)構(gòu)中的String類(lèi)型有哪些

1、len:獲取char[]的長(zhǎng)度,需要遍歷數(shù)組,len(char[])時(shí)間復(fù)雜度O(n);
2、alloc:c語(yǔ)言沒(méi)有String類(lèi)型, 只有char[],且char[]必須先分配空間長(zhǎng)度,char[]預(yù)先分配了長(zhǎng)度,數(shù)據(jù)增長(zhǎng)后需要擴(kuò)容;

3、falgs:總是占用一個(gè)字節(jié)。其中的最低3個(gè)bit用來(lái)表示header的類(lèi)型。header的類(lèi)型共有5種,在sds.h中有常量定義。
4、buf[]:c語(yǔ)言的char數(shù)組,用'\0'代表結(jié)束,意味著存儲(chǔ)二進(jìn)制數(shù)據(jù)不能包含'\0',圖片音頻等用二進(jìn)制存儲(chǔ)會(huì)有問(wèn)題——這就是為什么Redis說(shuō)自己實(shí)現(xiàn)的SDS是二進(jìn)制安全的字符串。

SDS對(duì)c原始char數(shù)組的改進(jìn)

1、Redis實(shí)現(xiàn)的SDS支持?jǐn)U容
2、包含長(zhǎng)度len,獲取長(zhǎng)度復(fù)雜度O(1)
3、空間預(yù)分配
4、惰性空間釋放(下面會(huì)講)

SDS的優(yōu)缺點(diǎn)

優(yōu)點(diǎn)

  • 能夠支持?jǐn)U容

  • 包含長(zhǎng)度len,獲取長(zhǎng)度復(fù)雜度O(1)

  • 空間預(yù)分配

缺點(diǎn)

  • 需要分配額外的內(nèi)存

  • 頻繁的分配和回收帶來(lái)的效率問(wèn)題

Redis 使用的內(nèi)存分配庫(kù) jemalloc

jemalloc 在分配內(nèi)存時(shí),會(huì)根據(jù)我們申請(qǐng)的字節(jié)數(shù) N,找一個(gè)比 N 大,但是最接近 N 的 2 的冪次數(shù)作為分配的空間,這樣可以減少頻繁分配的次數(shù)。舉個(gè)例子。如果你申請(qǐng) 6 字節(jié)空間,jemalloc 實(shí)際會(huì)分配 8 字節(jié)空間;如果你申請(qǐng) 24 字節(jié)空間,jemalloc 則會(huì)分配 32 字節(jié)。所以,在我們剛剛說(shuō)的場(chǎng)景里,dictEntry 結(jié)構(gòu)就占用了 32 字節(jié)。

空間預(yù)分配

空間預(yù)分配用于優(yōu)化 SDS 的字符串增長(zhǎng)操作: 當(dāng) SDS 的 API 對(duì)一個(gè) SDS 進(jìn)行修改, 并且需要對(duì) SDS 進(jìn)行空間擴(kuò)展的時(shí)候, 程序不僅會(huì)為 SDS 分配修改所必須要的空間, 還會(huì)為 SDS 分配額外的未使用空間。

其中, 額外分配的未使用空間數(shù)量由以下公式?jīng)Q定:

  • 如果對(duì) SDS 進(jìn)行修改之后, SDS 的長(zhǎng)度(也即是 len 屬性的值)將小于 1 MB , 那么程序分配和 len 屬性同樣大小的未使用空間, 這時(shí) SDS len 屬性的值將和 free 屬性的值相同。 舉個(gè)例子, 如果進(jìn)行修改之后, SDS 的 len 將變成 13 字節(jié), 那么程序也會(huì)分配13 字節(jié)的未使用空間, SDS 的 buf 數(shù)組的實(shí)際長(zhǎng)度將變成 13 + 13 + 1 = 27 字節(jié)(額外的一字節(jié)用于保存空字符)。

  • 如果對(duì) SDS 進(jìn)行修改之后, SDS 的長(zhǎng)度將大于等于 1 MB , 那么程序會(huì)分配 1 MB 的未使用空間。 舉個(gè)例子, 如果進(jìn)行修改之后, SDS 的 len 將變成 30 MB , 那么程序會(huì)分配 1 MB 的未使用空間, SDS 的 buf 數(shù)組的實(shí)際長(zhǎng)度將為 30 MB + 1 MB + 1 byte 。

通過(guò)空間預(yù)分配策略, Redis 可以減少連續(xù)執(zhí)行字符串增長(zhǎng)操作所需的內(nèi)存重分配次數(shù)。

惰性釋放

惰性空間釋放用于優(yōu)化 SDS 的字符串縮短操作: 當(dāng) SDS 的 API 需要縮短 SDS 保存的字符串時(shí), 程序并不立即使用內(nèi)存重分配來(lái)回收縮短后多出來(lái)的字節(jié), 而是使用 free 屬性將這些字節(jié)的數(shù)量記錄起來(lái), 并等待將來(lái)使用。

Redis的KV存儲(chǔ)結(jié)構(gòu)

在redis中,所有的存儲(chǔ)都是以KV鍵值對(duì)的形式存儲(chǔ)的,K是字符串類(lèi)型,就是SDS;V 可能是字符串、list、hash等(Redis支持的數(shù)據(jù)結(jié)構(gòu)),V并沒(méi)有直接定成具體的類(lèi)型,而是用redisObject封裝了一層;實(shí)際存儲(chǔ)的數(shù)據(jù)結(jié)構(gòu)是由ptr指針具體指向。

并且,redis為了更好的節(jié)省空間,ptr指針也有不同方式的存儲(chǔ),一方面,當(dāng)保存的是 Long 類(lèi)型整數(shù)時(shí),RedisObject 中的指針就直接賦值為整數(shù)數(shù)據(jù)了,這樣就不用額外的指針再指向整數(shù)了,節(jié)省了指針的空間開(kāi)銷(xiāo)。另一方面,當(dāng)保存的是字符串?dāng)?shù)據(jù),并且字符串小于等于 44 字節(jié)時(shí),RedisObject 中的元數(shù)據(jù)、指針和 SDS 是一塊連續(xù)的內(nèi)存區(qū)域,這樣就可以避免內(nèi)存碎片。這種布局方式也被稱(chēng)為 embstr 編碼方式。當(dāng)然,當(dāng)字符串大于 44 字節(jié)時(shí),SDS 的數(shù)據(jù)量就開(kāi)始變多了,Redis 就不再把 SDS 和 RedisObject 布局在一起了,而是會(huì)給 SDS 分配獨(dú)立的空間,并用指針指向 SDS 結(jié)構(gòu)。這種布局方式被稱(chēng)為 raw 編碼模式。如圖所示

Redis數(shù)據(jù)結(jié)構(gòu)中的String類(lèi)型有哪些

  • embstr 編碼
    存儲(chǔ)簡(jiǎn)短字符串,一次的內(nèi)存分配;
    它是只讀的,如果對(duì)內(nèi)容進(jìn)行修改,就會(huì)變成raw編碼(即使沒(méi)超過(guò)44字節(jié));

  • raw 編碼
    可分配多次內(nèi)存空間,存儲(chǔ)大于44個(gè)字節(jié)的長(zhǎng)字符串。

raw 原生SDS 字符長(zhǎng)度 縮減到小于44,會(huì)逆向變成embstr編碼嗎?
不會(huì);Redis底層編碼,轉(zhuǎn)變后 不可逆(不會(huì)回退)。

到此,關(guān)于“Redis數(shù)據(jù)結(jié)構(gòu)中的String類(lèi)型有哪些”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

網(wǎng)站題目:Redis數(shù)據(jù)結(jié)構(gòu)中的String類(lèi)型有哪些
轉(zhuǎn)載注明:http://bm7419.com/article12/pscggc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供Google、網(wǎng)站建設(shè)網(wǎng)站維護(hù)、云服務(wù)器、App開(kāi)發(fā)、網(wǎng)頁(yè)設(shè)計(jì)公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)