您好,登錄后才能下訂單哦!
這篇文章主要介紹“Redis數據結構中的String類型有哪些”,在日常操作中,相信很多人在Redis數據結構中的String類型有哪些問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Redis數據結構中的String類型有哪些”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
Redis常用作分布式KV緩存,很多人僅僅只會使用,卻不知道底層卻有著很多不為人知的秘密。
String作為Redis支持的最基礎的數據類型,首先我們來看下String,他的數據結構和存儲是怎么樣的。
眾所周知,redis是用c語言進行編寫的,而c語言是沒有String類型的,只有char[],并且在初始化的是時候就必須大小指定類型后就不能改變。為了實現動態增加和擴展等功能,如incr命令,append命令,所以redis就自己定義維護了一個SDS(Simple Dynamic String)來實現這些功能。
我們先來看一下redis源碼中定義的數據結構,這里有5種類型,目的是為了節省空間。
1、len:獲取char[]的長度,需要遍歷數組,len(char[])時間復雜度O(n);
2、alloc:c語言沒有String類型, 只有char[],且char[]必須先分配空間長度,char[]預先分配了長度,數據增長后需要擴容;
3、falgs:總是占用一個字節。其中的最低3個bit用來表示header的類型。header的類型共有5種,在sds.h中有常量定義。
4、buf[]:c語言的char數組,用'\0'代表結束,意味著存儲二進制數據不能包含'\0',圖片音頻等用二進制存儲會有問題——這就是為什么Redis說自己實現的SDS是二進制安全的字符串。
1、Redis實現的SDS支持擴容
2、包含長度len,獲取長度復雜度O(1)
3、空間預分配
4、惰性空間釋放(下面會講)
優點
能夠支持擴容
包含長度len,獲取長度復雜度O(1)
空間預分配
缺點
需要分配額外的內存
頻繁的分配和回收帶來的效率問題
jemalloc 在分配內存時,會根據我們申請的字節數 N,找一個比 N 大,但是最接近 N 的 2 的冪次數作為分配的空間,這樣可以減少頻繁分配的次數。舉個例子。如果你申請 6 字節空間,jemalloc 實際會分配 8 字節空間;如果你申請 24 字節空間,jemalloc 則會分配 32 字節。所以,在我們剛剛說的場景里,dictEntry 結構就占用了 32 字節。
空間預分配用于優化 SDS 的字符串增長操作: 當 SDS 的 API 對一個 SDS 進行修改, 并且需要對 SDS 進行空間擴展的時候, 程序不僅會為 SDS 分配修改所必須要的空間, 還會為 SDS 分配額外的未使用空間。
其中, 額外分配的未使用空間數量由以下公式決定:
如果對 SDS 進行修改之后, SDS 的長度(也即是 len 屬性的值)將小于 1 MB , 那么程序分配和 len 屬性同樣大小的未使用空間, 這時 SDS len 屬性的值將和 free 屬性的值相同。 舉個例子, 如果進行修改之后, SDS 的 len 將變成 13 字節, 那么程序也會分配13 字節的未使用空間, SDS 的 buf 數組的實際長度將變成 13 + 13 + 1 = 27 字節(額外的一字節用于保存空字符)。
如果對 SDS 進行修改之后, SDS 的長度將大于等于 1 MB , 那么程序會分配 1 MB 的未使用空間。 舉個例子, 如果進行修改之后, SDS 的 len 將變成 30 MB , 那么程序會分配 1 MB 的未使用空間, SDS 的 buf 數組的實際長度將為 30 MB + 1 MB + 1 byte 。
通過空間預分配策略, Redis 可以減少連續執行字符串增長操作所需的內存重分配次數。
惰性空間釋放用于優化 SDS 的字符串縮短操作: 當 SDS 的 API 需要縮短 SDS 保存的字符串時, 程序并不立即使用內存重分配來回收縮短后多出來的字節, 而是使用 free 屬性將這些字節的數量記錄起來, 并等待將來使用。
在redis中,所有的存儲都是以KV鍵值對的形式存儲的,K是字符串類型,就是SDS;V 可能是字符串、list、hash等(Redis支持的數據結構),V并沒有直接定成具體的類型,而是用redisObject封裝了一層;實際存儲的數據結構是由ptr指針具體指向。
并且,redis為了更好的節省空間,ptr指針也有不同方式的存儲,一方面,當保存的是 Long 類型整數時,RedisObject 中的指針就直接賦值為整數數據了,這樣就不用額外的指針再指向整數了,節省了指針的空間開銷。另一方面,當保存的是字符串數據,并且字符串小于等于 44 字節時,RedisObject 中的元數據、指針和 SDS 是一塊連續的內存區域,這樣就可以避免內存碎片。這種布局方式也被稱為 embstr 編碼方式。當然,當字符串大于 44 字節時,SDS 的數據量就開始變多了,Redis 就不再把 SDS 和 RedisObject 布局在一起了,而是會給 SDS 分配獨立的空間,并用指針指向 SDS 結構。這種布局方式被稱為 raw 編碼模式。如圖所示
embstr 編碼
存儲簡短字符串,一次的內存分配;
它是只讀的,如果對內容進行修改,就會變成raw編碼(即使沒超過44字節);
raw 編碼
可分配多次內存空間,存儲大于44個字節的長字符串。
raw 原生SDS 字符長度 縮減到小于44,會逆向變成embstr編碼嗎?
不會;Redis底層編碼,轉變后 不可逆(不會回退)。
到此,關于“Redis數據結構中的String類型有哪些”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。