日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

读《redis设计与实现》笔记--redis数据结构

發布時間:2024/7/19 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 读《redis设计与实现》笔记--redis数据结构 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

redis五大數據結構:string,hash,list,set,zset(有序集合)

redis底層數據結構:簡單動態字符串(SDS),鏈表,字典,跳表,整數集合,壓縮列表

底層數據結構詳解:

1.簡單動態字符串:類似于c的結構體,但是SDS擁有記錄已用長度(len)與剩余空間長度(free),當空間不足時會進行擴容。SDS最后會保存一個空字符

所以SDS獲取字符串長度的時間復雜度為o(1),SDS自動擴容也不會像C一樣產生溢出

利用未使用空間,SDS擁有空間預分配和惰性空間釋放兩種優化方法。

空間預分配:

修改SDS之后之后,如果len<1MB,將free修改為和len一樣的長度,如果len>=1MB,將free修改為1MB。

例如:str = "redis"

如果拼接str與"cluster",那么修改之后len為5+6=11,11+11+1=23,len/free值都是11,加上最后一個空字符,總長為23。

要是str修改之后大小為20MB,那擴容之后就是20MB+1MB+1byte

將擴容需要的次數從最多n次變為至多n次。

惰性空間釋放:

不會真正釋放內存大小,例如刪除redis中的字符e與d,那么str就變為ris,但是free=2。

這樣減少釋放空間的操作,將來擴容也會減少操作。

tips:SDS有專門的api可以真正釋放空間,不用擔心惰性釋放帶來空間的浪費。

二進制安全

C字符串中的字符必須符合某種編碼(比如ASCII),并且除了字符串的末尾之外,字符串里面不能包含空字符,否則最先被程序讀入的空字符將被誤認為是字符串結尾,這些限制使得C字符串只能保存文本數據,而不能保存像圖片、音頻、視頻、壓縮文件這樣的二進制數據。

因此,為了確保Redis可以適用于各種不同的使用場景,SDS的API都是二進制安全的。

SDS和c的區別:

?

2.鏈表

應用:列表鍵的底層實現之一就是鏈表。當一個列表鍵包含了數量比較多的元素,又或者列表中包含的元素都是比較長的字符串時,Redis就會使用鏈表作為列表鍵的底層實現。

除了鏈表鍵之外,發布與訂閱、慢查詢、監視器等功能也用到了鏈表,Redis服務器本身還使用鏈表來保存多個客戶端的狀態信息,以及使用鏈表來構建客戶端輸出緩沖區。

一個鏈表結點:

鏈表:

3.字典(key-value)

字典在Redis中的應用相當廣泛,比如Redis的數據庫就是使用字典來作為底層實現的,對數據庫的增、刪、查、改操作也是構建在對字典的操作之上的。

字典還是哈希鍵的底層實現之一,當一個哈希鍵包含的鍵值對比較多,又或者鍵值對中的元素都是比較長的字符串時,Redis就會使用字典作為哈希鍵的底層實現。

Redis的字典使用哈希表作為底層實現,而每個哈希表節點就保存了字典中的一個鍵值對。

字典所用的哈希表結構:

每個dictEntry結構保存著一個鍵值對

dictEntry結構:

字典結構:

type屬性是一個指向dictType結構的指針,每個dictType結構保存了一簇用于操作特定類型鍵值對的函數,Redis會為用途不同的字典設置不同的類型特定函數。

privdata屬性則保存了需要傳給那些類型特定函數的可選參數。

Redis的哈希表使用鏈地址法來解決鍵沖突。

擴展和收縮哈希表的工作可以通過執行rehash(重新散列)操作來完成。

Redis Bgsave 命令用于在后臺異步保存當前數據庫的數據到磁盤。

對哈希表進行擴展:1.正在執行bgsave,負載因子>=5? ? ? 2.沒有執行bgsave,負載因子>=1

對哈希表進行收縮:負載因子<0.1

漸進式hash:rehash動作并不是一次性、集中式地完成的,而是分多次、漸進式地完成的。

原因:如果哈希表里保存的鍵值對數量千萬甚至億個鍵值對,那么要一次性將這些鍵值對全部rehash的話,龐大的計算量可能會導致服務器在一段時間內停止服務。

所以rehash期間,更新,刪除,查找在兩個表里進行,舊表查找不到的話去新表查找。

而插入就直接在新表進行,所以舊表只減不增。

字典使用哈希表作為底層實現,每個字典帶有兩個哈希表,一個平時使用,另一個僅在進行rehash時使用。

4.跳躍表

Redis使用跳躍表作為有序集合鍵的底層實現之一,如果一個有序集合包含的元素數量比較多,又或者有序集合中元素的成員是比較長的字符串時,Redis就會使用跳躍表來作為有序集合鍵的底層實現。

Redis只在兩個地方用到了跳躍表,一個是實現有序集合鍵,另一個是在集群節點中用作內部數據結構。

每個節點都有向前,向后的指針,向后的可能有多個(看有多少層有這個數據),向前的只有一個。

插入方法:從底層開始,每一層選擇插入或者不插入,插入一層的話就停止。

所以第一層的插入概率1/2,第二次1/4...

5.整數集合

整數集合是集合鍵的底層實現之一。

整數集合的結構:

contents數組各個項在數組中按值的大小從小到大有序地排列,并且數組中不包含任何重復項。contents數組的真正類型取決于encoding屬性的值。

升級:

每當我們要將一個新元素添加到整數集合里面,并且新元素的類型比整數集合現有所有元素的類型都要長時,整數集合需要先進行升級,然后才能將新元素添加到整數集合里面。

升級步驟:1.根據新數據類型,擴展底層數組大小 2.將其他數據設置為新數據類型 3.新元素添加到底層數組

升級好處:一個是提升整數集合的靈活性,另一個是盡可能地節約內存。

節約內存:有int_16,int_32,int_64三種類型,整數集合現在的做法既可以讓集合能同時保存三種不同類型的值,又可以確保升級操作只會在有需要的時候進行,這可以盡量節省內存。

沒有降級操作。

6.壓縮列表

壓縮列表是列表鍵和哈希鍵的底層實現之一。

一個列表鍵只包含少量列表項,并且每個列表項要么就是小整數值,要么就是長度比較短的字符串,就會用壓縮列表。

總結

以上是生活随笔為你收集整理的读《redis设计与实现》笔记--redis数据结构的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。