中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

Redis字符串原理的深入理解

發布時間:2020-10-02 02:45:56 來源:腳本之家 閱讀:152 作者:YangSir 欄目:數據庫

前言

來掘進都有兩年多了一直當個小透明,今天終于發一次文章了.

最近在看 Redis,感覺收獲很多,寫篇博客記錄一下.

Redis 有五種基礎數據結構:string,list,set,zset,hash.其中 string是最最最簡單的也是最常用的.這個數據類型雖然簡單但是內部的結構設計卻很是精致.

基本介紹

相比于 Java,在 Redis 中 string 是可以修改的,是動態字符串(Simple Dynamic String 簡稱 SDS)他的內部結構更像是一個 ArrayList,維護一個字節數組并預分配冗余空間以減少內存的頻繁分配.當字符串的長度小于 1MB時,每次擴容都是加倍現有的空間,如果字符串長度超過 1MB 時,每次擴容時只會擴展 1MB 的空間.

ps:字符串長度為最大長度 512MB.

> set name test
OK
> get name
"test"
> mset name1 test1 name2 test2
OK
> mget name1 name2
1) "test1"
2) "test2"
> del name
(integer) 1

上面是字符串的基本操作 命令mset 和 mget 可以對多個字符串讀寫 節省網絡開銷

不僅如此redis 的字符串還可以用來儲存整數(更不像Java 的字符串了),并且可以自增操作.字符串保存整數類型的的范圍在 至
如果保存的數大于這個取值范圍就會變成普通字符類型 無法自增操作.這將由字符串編碼格式決定.

字符串由多個字節組成,每個字節有 8bit.這樣的數據結構還可以當做 bitmap 去使用.

> set foo 1
OK
> get foo 
"1"
> incr foo
(integer) 2
> get foo
"2"

內部原理

基本實現

Redis字符串原理的深入理解

上圖所示為字符串的基本結構,其中 content 里面保存的是字符串內容,和 c 一樣用 0x\0作為結束字符.這個結束字符不會被計算len 中.代碼如下:

struct SDS{
  T capacity;		//數組容量
  T len;			//實際長度
  byte flages;	//標志位,低三位表示類型
  byte[] content;	//數組內容
}

可以看到 capacity和len 都是泛型,為什么不直接使用 int 呢?因為 Redis 內部做了很多優化,為了減少內存的使用不同長度的字符串會使用不同的數據類型去表示.并且在創建字符串的時候 len 會和 capacity 一樣大,沒有冗余的空間,因為修改字符串的場景很少.(Redis 真的將內存優化到了極致)

編碼格式

Redis 字符串編碼格式有這么幾種:int 編碼、embstr編碼和raw 編碼 下面就詳細介紹下這幾種編碼的區別.

在這之前先要說說RedisObject. Redis 的對象頭,所有的 Redis 對象都有下面這個頭部結構.

struct RedisObject{
  int4 type;		//數據類型 5 種
  int4 encoding;	//鍵值內部編碼格式 int 或 embstr 等等
  int24 lru;		// 當內存超限時采用LRU算法清除內存中的對象
  
  int32 refcount;	//改鍵值被引用的數量
  void *ptr;		//對象內容
}

int 編碼

當儲存的值是64 位有符號整數類型的時候將會采用 int  編碼,這時可以使用鍵值自增操作.Redis 在啟動時會建立1w 個redisObject共享對象下文會講到,值在[0,1000)之間.如果存入整數的值在[0,1000)中Redis將不會創建新的對象,而是直接指向共享對象,鍵值不額外占用空間.

使用 object encoding命令可以查看編碼格式 使用 debug object命令可以查看更多信息

> set foo 1
OK
> object encoding foo
"int"
> set foo2 1
OK
> debug object foo
Value at:0x7f44b020aca0 refcount:2147483647 encoding:int serializedlength:2 lru:14691591 lru_seconds_idle:72588
> debug object foo2
Value at:0x7f44b020aca0 refcount:2147483647 encoding:int serializedlength:2 lru:14691591 lru_seconds_idle:72594

可以看到 foo 和 foo2  都在0x7f44b020aca0這里指向的是同一個對象

embstr 編碼

當存儲的字符串長度較短時(len<=44 字節),Redis將會采用 embstr 編碼.embstr 即embedded string 嵌入式的字符串.將SDS結構體嵌入RedisObject對象中, 使用 malloc 方法一次分配內存地址是連續的.

如圖所示:

Redis字符串原理的深入理解

raw 編碼

當存儲的字符串長度較長時(len>44 字節),Redis 將會采用 raw 編碼,和 embstr 最大的區別就是 RedisObject 和 SDS 不在一起了,內存地址不再連續了.

如圖所示:

Redis字符串原理的深入理解

思考

為什么字符串會有兩種格式 embstr 和格式和 raw分界線是 44 個字節?

Redis 默認的內存分配器jemalloc分配內存大小的單位是次方,為了容納一個完整的 embstr 對象,最少會分配 32 字節的空間,再長些就是 64 字節,再之后就認為這是一個大字符串不適合用 embstr 存儲,而改用 raw 編碼了.

那么問題來了,64 字節的空間字符串長度是多少呢?答案就是 44 字節.

下圖中 content 的長度為 45 字節減去結尾的 0x\0,就剩下 44 字節了.

Redis字符串原理的深入理解

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

离岛区| 民乐县| 锦屏县| 和平县| 汶川县| 饶河县| 桦甸市| 光山县| 阳谷县| 蒙城县| 光泽县| 昌吉市| 湘潭市| 西乌珠穆沁旗| 东安县| 泰来县| 喀什市| 晋江市| 新宾| 东山县| 三门峡市| 九台市| 金塔县| 南通市| 谷城县| 红安县| 武功县| 合肥市| 新田县| 沽源县| 康平县| 深州市| 达拉特旗| 东宁县| 徐州市| 武冈市| 平阳县| 黄骅市| 沙雅县| 方山县| 乌恰县|