Redis底层实现--字符串
Redis字符串存儲實現(xiàn)原理
- Redis 中的字符串是可以修改的字符串,在內存中他是以字節(jié)數(shù)組的形式存在的。我們在入門語言C語言里面的字符串標準形式是以NULL(即0x\0)作為結束符,但是Redis里面,字符串表示方法不是這樣,因為,要獲取以null結尾的字符串需要遍歷整個字符串,時間復雜度是O(n),對應單線程對外服務的Redis來說是無法承受的。
- Redis的字符串結構叫做SDS,Simple Dynamic String。他的結構是一個帶上長度信息的字節(jié)數(shù)組,類似C語言中的結構體。
- Redis中SDS存儲結構的設計類似于ArrayList機構,因為Redis允許字符串的修改,因此初始申請可以有一部分的冗余空間。
- capacity 標識所有分配數(shù)組的長度,包括未存儲數(shù)據(jù)的部分空間
- len標識字符串的實際長度
- 當冗余的空間不夠時候,先擴容,在復制舊的內容,然后在添加新內容,如果字符串長度非常長,內存的分配和復制開銷會特別大。
- 以上結構體中,使用的泛型T,其中Capacity和len的類型是T,因為Redis對存儲的壓縮優(yōu)化
- 當存儲字符串比較短的時候,了你和capacity可以使用byte和short來表示,
- Redis規(guī)定字符串長度不超過512M,創(chuàng)建字符串時候len和capacity一樣長,不會多分配冗余空間,這是因為絕大多數(shù)場景下我們不會去修改字符串。
embstr OR raw
- Redis字符串有兩種存儲方式,在長度短的時候,使用embstr形式存儲,長度超過44 字節(jié)時候,使用raw形式存儲,如下實驗:
-
一下我們通過分析Redis字符串對象存儲結構來說明兩個問題
- 問題一:為什么是44個字節(jié)作為界限
- 問題二:embstr 和raw存儲的區(qū)別
-
Redis對象存儲都會有一個頭部結構,如下形式
-
不同的對象具有不同的type 類型(4bit)。
-
同一個類型的type也會有不同的存儲方式encoding(4bit)。
-
為了記錄對象的lru信息,使用了24bit來記錄lru信息
-
每個對象都有一個引用計數(shù),refcount,當他歸零時候,對象不被任何地方使用,對象將被銷毀,內存被回收
-
ptr指針結構將指向對象的具體存儲位置(body)
-
以上所有的綜合一起 4bit+ 4bit+ 24bit + 32 bit + 64bit = 128bit = 16byte,所有Redis對象的對象頭結構都需要占據(jù)16字節(jié)存儲空間。
-
接著我們在分享SDS結構體大小,在字符串比較小的時候,SDS對象頭結構的大小如下:
-
如上結構中 capacity ,len, flags 三個都占用1byte的內存,其他的就是 capacity長度的數(shù)組,用來存儲具體數(shù)據(jù)。也就是最少也要3 個字節(jié)的存儲空間。加上上面的16byte,我們一個沒有存儲字符串的Redis字符串對象,已經(jīng)有19 byte的空間被系統(tǒng)各種屬性占用。
-
我們在內存分配的時候,使用jemalloc, tcmalloc等分配內存大小的單元都是2/4/4/8/16/32/64 byte,
-
為了容納完整的embstr對象,jemalloc最少分配32byte空間,如果字符串稍微長點,那就是64byte,如果字符串超過64byte,Redis會認為是一個大字符串,不在適合emdstr存儲的形式,而使用raw形式
-
我們用最大內存空間64 來計算最大字符串長度, 64 - 19 = 45 ,但是之前實驗得到的是44
-
SDS結構中content中字符串是以null結尾,多出這個字節(jié),便于直接使用glbc的字符串處理函數(shù),以及便于字符串的調試打印輸出。最終得出了44 的長度。如下圖:
-
問題二中embstr存儲形式與 raw的存儲形式如下
- embst存儲將RedisObject對象頭結構和SDS對象連續(xù)存儲在一起,使用malloc方法一次性分配內存
- raw存儲形式不一樣,他需要兩次malloc方法,兩個對象頭在內存地址上不連續(xù)通過對象頭中 ptr指針來尋址存儲位置。
擴容策略
- 字符串的擴容兩種方式:
- 字符串長度在1MB之前,擴容空間都是加倍擴容,也就是保留100%的冗余空間
- 字符串長度超過1MB后,避免加倍后冗余空間浪費過多,每次只多分配1MB大小的冗余空間。
上一篇:Redis服務信息–Info指令
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結
以上是生活随笔為你收集整理的Redis底层实现--字符串的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手机中国移动的视讯中国手机电视业务怎么退
- 下一篇: 冠捷(AOC)显示器好用吗?