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

溫馨提示×

溫馨提示×

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

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

redis整數集為什么不能降級

發布時間:2021-07-21 16:38:58 來源:億速云 閱讀:120 作者:chen 欄目:開發技術

本篇內容主要講解“redis整數集為什么不能降級”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“redis整數集為什么不能降級”吧!

目錄
  • 前言

  • 基本結構

  • 何時使用intset

  • intset

  • 添加元素

  • 類型變動

  • 升級

  • 加入65535

  • 舊數據移位

  • 降級

  • 為什么不實現降級


前言

整數集合相信有的同學沒有聽說過,因為redis對外提供的只有封裝的五大對象!而我們本系列主旨是學習redis內部結構。內部結構是redis五大結構重要支撐!

前面我們分別從redis內部結構分析了redis的List、Hash、Zset三種數據結構了。今天我們再來分析set數據結構內部是如何存儲的

基本結構

在src/t_set.c中我們發現這樣一段代碼

redis整數集為什么不能降級

由此我們可知在set中是由兩種數據結構構成的: hashtable+intset 。關于redis內部其他的結構我專門在【redis專欄中有介紹】。hashtable不是我們今天的主角,我們今天先分析intset俗稱整數集合。

redis整數集為什么不能降級

從上圖中我們可以看出,我構造了兩個set集合分別為【commonset】、【cs】。兩個集合前者存儲字符串、后者專門存儲數字。

我們在通過object encoding key 來查看下兩個集合的底層數據結構,發現一個是hashtable 一個是intset 。這也驗證了我們上面對set基本結構的描述。

在redis中對外提供五大類型實際上都是redis的一個抽象對象叫做redisobject。在內部映射了我們redis內部的數據結構

redis整數集為什么不能降級

針對commonset和cs兩個集合在內部數據結構大概可以這么理解

redis整數集為什么不能降級

何時使用intset

你可以單純的認為只要是數字就會使用intset結構來存儲,我恐怕要給你當頭一棒了。實際上并不是這樣

需要同時滿足以下兩個條件:

redis整數集為什么不能降級

redis整數集為什么不能降級

intset

redis整數集為什么不能降級

圖中表示的很清楚了,在intset中的encoding有三種取值分別代表contents保存數據類型。這里有人可能會有疑問了contents的類型不就是int8_t嗎?為什么還需要encoding呢?這里通過源碼跟蹤內部的確跟int8_t沒啥關系。而且數據的默認類型就是int16_t 。關于length這里無需太多解釋,記住一點表示contents元素的個數并非表示contents數組的長度!

了解intset的同學都知道在encoding三種取值范圍中涉及了升級的操作!在講升級之前我們先來了解下C、C++中int的取值范圍是如何定義的

int8_t的取值范圍是【-128,127】 。 類似于java中byte占1個字節也就是8位。他的取值范圍是

redis整數集為什么不能降級

redis整數集為什么不能降級

添加元素

sadd juejin -123
sadd juejin -6
sadd juejin 12
sadd juejin 56
sadd juejin 321	

juejin這個key內部就是intset 。

redis整數集為什么不能降級

上面我們添加了5個元素且這五個元素的長度都在16之內!所以當前的intset的encoding=INTSET_ENC_INT16。-123在contents中占前16位。

所以當前五個元素占contents的長度是16*5=80 ;

注意set在存儲int類型數據時,內部是按照從小到大的順序存儲的。

類型變動

redis整數集為什么不能降級

上面的問題不知道你有沒有考慮過,或者說有沒有遇到過!intset默認是int16位,正如我們上面添加的五個元素。加入此時我們添加第6個元素是65535(32位)。那么此時16位的長度就不夠存儲了這個時候intset會怎么做!

另外當我們添加第6個元素后又將65535刪除了之后,結構和添加之前是否一樣!下面我們帶著這兩個問題來一探究竟!!!

升級

首先我們針對第一問題來看看。原來五個元素都是16位就可以滿足了,這個時候添加的65535是32位長度的。那么是不是可以直接追加32位分配給65535呢?

答案是肯定不行,首先直接追加無法保證數組元素的大小順序!其次如果前五個分別是16位,第6個是32位那么在intset結構中沒有多余的字段來進行標記。也就是說在解析的時候就無法判斷應該解析16位還是32位了.

redis為了方便解析所以在有高長度加入時會將整個contents進行升級。意思就是將整個contents先進行擴容,然后在重新填充數據

redis整數集為什么不能降級

加入65535

首先根據length可以確定擴容后元素個數為6 , 每個占位32,所以contents長度為32*6=192 。 此時前80位內容保持不變

redis整數集為什么不能降級

舊數據移位

開辟了足夠的空間后,我們就可以對舊數據進行移位了這里我們從原數組的末尾開始移動,在移動之前需要明確在新數組中的排序位置。此時我們首先將321進行比對確定在新數組中他的排名是第五名,那么他將占用新contents中128~159區間。

redis整數集為什么不能降級

最終前5 個元素就會被移動好 。

redis整數集為什么不能降級

最后將新加入的元素填充進去。當發生升級時肯定是因為新元素的長度大于原有長度了。那么他的值一定會是在新數組的兩端。負數在最左側,正數在最右側

redis整數集為什么不能降級

降級

接下來就是第二個問題當新加入的65535又被刪除了redis該怎么辦,這個時候元素長度實際16位就可以滿足了,但是此時encoding卻是32位的。按照我的看法應該在實現降級!

但是遺憾的是redis并沒有,那么請思考為什么沒有?如果讓你實現你將如何實現

為什么不實現降級

當加入元素超過當前長度我們很容易就知道此時需要進行升級操作,但是當我們刪除一個數據時我們如何判斷是否需要降級卻很困難,我們需要重新遍歷一遍剩下的元素是否小于當前長度,實現復雜度O(N) 。這就是為什么不進行降級原因之一

你可能會說重新遍歷一遍很快的反正在內存中,那么你有沒有想過如果降級之后又遇到升級情況,這樣來回的升級降級就降低了我們程序的性能了。我們知道升級是必須的所以這里降級redis采取的是忽略的策略

到此,相信大家對“redis整數集為什么不能降級”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

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

AI

白银市| 林州市| 师宗县| 连江县| 双柏县| 西和县| 黄石市| 堆龙德庆县| 哈密市| 科技| 民权县| 任丘市| 西华县| 石林| 本溪市| 宁远县| 西昌市| 海淀区| 密山市| 湘乡市| 连城县| 加查县| 美姑县| 祁阳县| 延寿县| 玉屏| 江津市| 枝江市| 临泉县| 肥乡县| 太白县| 福清市| 林芝县| 大同市| 潜江市| 肃北| 辽阳县| 武山县| 虎林市| 宜城市| 邛崃市|