我們先從redis支援的資料型別學起,了解不同的資料型別的差異和底層實現的資料結構。
一般的鍵值對資料庫只支援string一種資料型別,例如memcached,而redis支援的資料型別非常豐富,一共有5種,分別是string(字串)、list(列表)、hash(字典)、set(集合)、sortset(有序集合)。除string外,其餘四種資料型別是集合型別。
string是最簡單的資料型別了,它是由簡單動態字串實現的。
list支援儲存一組資料,有兩種實現方式:壓縮列表(ziplist)和雙向迴圈鍊錶。
hash用來儲存一組資料對,每個資料對又包含鍵和值兩部分。hash也有兩種實現方式:壓縮列表和雜湊表。
set這種資料型別用來儲存一組不重複的資料。有兩種實現方式:有序陣列和雜湊表。
sortedset用來儲存一組資料,並且每個資料會附帶乙個得分。通過得分的大小,我們將資料組織成跳表這種資料結構,以支援快速地按照得分值、得分區間獲得資料。
sortedset也有兩種實現方式:跳表和壓縮列表。
redis底層一共有六種資料結構,分別是簡單動態字串、雙向鍊錶、壓縮列表、雜湊表、跳表、整數陣列。
與字串本身不同,簡單動態字串(sds)保留字串長度資訊,只需要o(1)就能得到字串長度。
雙向鍊錶是節點儲存前置和後置節點的指標的鍊錶結構。
類似於陣列,但與陣列不同的是,壓縮列表在表頭有三個字段(zlbytes、zltail、zllen)和表名有乙個字段(zlend)。
查詢第乙個元素和最後乙個元素只需要o(1),其他o(n)。
乙個雜湊表,其實就是乙個陣列,陣列的每個元素稱為乙個雜湊桶。
雜湊表最大的好處是查詢元素只需要o(1)時間複雜度,但隨著雜湊表寫入大量資料後,就可能出現操作變慢的情況,這是因為雜湊表的衝突問題和rehash可能帶來的操作阻塞。
為什麼雜湊表操作變慢了?
當雜湊表中寫入大量資料時,雜湊衝突是不可避免的。這裡的雜湊衝突指的是兩個key的雜湊值相同,落在同乙個雜湊桶中。
redis解決雜湊衝突的方式是:鏈式雜湊,即同乙個雜湊桶中的多個元素用乙個鍊錶來儲存。
但這裡還存在乙個問題,雜湊衝突鏈上查詢元素的時間複雜度是o(n),當雜湊衝突鏈過長,查詢元素耗時長,效率降低。這對redis來說是不能接受的。
所以redis會對雜湊表做rehash操作。rehash就是增加現有的雜湊桶數量,即擴容。
redis執行rehash有三步:
給雜湊表2分配更大的空間,例如是當前雜湊表1大小的兩倍;
把雜湊表1中的資料重新對映並拷貝到雜湊表2中;
釋放雜湊表1的空間。
這個過程看似簡單,但是步驟2涉及大量的資料拷貝,如果一次性把資料都遷移完,會造成redis執行緒阻塞,無法處理其他請求。
為了避免這個問題,redis採用了漸進式rehash。
簡單來說,就是把步驟2拷貝資料這一次性開銷分攤到多次請求裡,例如請求key1,會把key1所在的雜湊桶從雜湊表1遷移到雜湊表2裡,直到所有雜湊桶都遷移到雜湊表2裡。在這個過程裡,雜湊表1要一直保留,等到遷移完成後才釋放。
除了鍵值對請求操作進行資料遷移,redis本身還會有乙個定時任務來執行rehash。
有序鍊錶只能逐一查詢元素,導致操作非常緩慢,於是出現了跳表。具體來說,跳表是在鍊錶的基礎上,增加了多級索引,通過索引位置的幾個跳轉,實現資料的快速定位。如下圖所示:
可以看到,這個查詢過程就是在多級索引上跳來跳去,最後定位到元素。跳表的查詢時間複雜度是o(logn)。
就是乙個陣列,元素型別是整數,並且是有序的。
redis能夠快速操作鍵值對,一方面是因為使用了o(1)的雜湊表,另一方面是也採用了o(logn)的跳表。
集合型別的範圍操作的時間複雜度通常是o(n)。建議用其他命令替換,例如scan。
list的複雜度較高,要因地制宜使用list。
整數陣列和壓縮列表在查詢時間複雜度方面沒有很大的優勢,redis為什麼還會把它們作為底層資料結構?
兩方面原因:
陣列和壓縮列表可以提公升記憶體利用率,因為他們的資料結構緊湊
陣列對cpu快取記憶體支援友好,當資料元素超過閾值時,會轉為hash和跳表,保證查詢效率
c 基礎(一) 資料型別
c 的資料型別分為兩類 值和引用,值型是乙個長度固定的資料,引用型是乙個長度可變的。具體來說 值 整數型 浮點數 布林型 字元型 結構 列舉 六種 引用 c 預定義引用 陣列 類 介面 下面具體介紹 整數型 8 16 32 64位,每種又有正負和非負兩種整數,共8種,sbyte byte short...
C 基礎(一) 資料型別
using system namespace base 01 endregion 說明 1 每個程式只能有乙個main方法 2 region 摺疊塊,endregion可以實現 塊摺疊 3 c 需要引用命名空間,類似於c 新增標頭檔案,命名空間裡有相關類。例如console是system名字空間裡的...
C 基礎 一 資料型別
常量的定義 1.define 2.const 注意 define 的形式不要在結尾寫分號了 include using namespace std define day 7 int main 資料型別 1.整形 short 短整型2位元組 16bit int 整形4位元組 long 長整型win4位...