天天看點

redis-原理-資料結構-SDS(一)什麼是SDSSDS的應用場景SDS結構定義SDS和C字元串的差別SDS對于擴容的優化SDS的優點

什麼是SDS

1.redis沒有直接使用C的字元串,而是自己實作了字元串的實作名叫SDS

2.c的字元串隻會用在值不會改變的地方,比如redislog列印

SDS的應用場景

1.

本地:0>set msg hellowrd
OK      

鍵和值都是字元串對象,底層通過SDS實作

2.

本地:0>rpush fruits apple banana cherry
3      

鍵是字元串對象 由SDS實作, 值是清單對象,清單對象包含三個字元串對象 分别由SDS實作

SDS結構定義

SDS遵循C的字元串定義,以空字元串()作為字元串的結尾,空字元串1位元組不計算在len裡面,好處就是直接使用C字元串的函數如:print(%,s-buf)

帶有未使用位元組數量的SDS

SDS和C字元串的差別

1. C字元結構是沒有記錄長度的,如果要擷取長度必須周遊字元,複雜度是0(N)

2.SDS是記錄了字元串長度擷取字元串長度是0(1)如:

本地:0>strlen msg
8      

緩沖區溢出

因為C不記錄字元長度,如果在進行擴容時,隻能假定記憶體足夠,如果不足夠則會造成緩沖區溢出

擴容前 S1 和S2 2個字元緊鄰,我們要對S1進行擴容,因為沒有記錄長度我們并不知道記憶體是否足夠,執行:strcat(s1,"cluster")

擴容前:

擴容後

SDS如何解決緩沖區溢出 

與C不同因為SDS記錄了未使用空間,在擴容前會先判斷空間是否足夠,如果不夠sdscat(redis SDS的拼接API)先擴容空間

如執行

strcat(s1,"cluster")

擴容前

擴容後

二進制安全

C的字元必須符合某種編碼(ASCII),并且除了字元串末尾之外字元串裡面不能包含空字元,否則會誤認為字元串結尾,這些使得C隻能儲存文本而不能儲存圖檔、視訊、音頻、壓縮檔案這樣的二進制資料

因為SDS并沒有使用空字元()判斷字元的結尾而是len來判斷,使用SDS可以儲存圖檔 視訊 音頻等二進制資料

SDS對于擴容的優化

空間預配置設定

當我們對SDS空間進行擴充的時候,SDS除了配置設定必要的空間,還會為SDS配置設定額外的未使用空間 free記錄。

公式:

      1.如果對SDS進行修改後,len長度小于1M則配置設定len同樣大小的未使用空間 len+free+1為目前SDS占用空間 1為結尾空字元占用空間

      2.如果對SDS進行修改有len長度大于1M則會額外配置設定1M未使用空間   len+1m+1為目前SDS占用空間 1為結尾空字元占用空間

當每次擴充SDS API都會檢查free是否有足夠空間,如果有則不執行擴充 直接使用 減少了配置設定次數,

通過空間預配置設定優化,将連續增長N次字元串需要擴充N次,變為最多N次

惰性配置設定

當SDS縮短字元長度時候,并不會完全釋放,隻是将多出來的空間記錄到free

如果移除字元串中所有的 x和y

移除前

移除後

 将來需要拼接字元時則可以減少擴容

預配置設定和惰性配置設定空間浪費解決方式

通過上面的意思,會讓我們覺得會浪費空間,其實SDS也提供了API讓我們可以真正的釋放SDS未使用空間,是以不用擔心預配置設定和惰性配置設定造成的浪費

SDS的優點

1.比起C字元串,SDS擷取字元串長度是O(1)

2.比起C字元串,不會緩沖區溢出

3.減少字元串擴容時的配置設定次數

4.二進制安全

5.相容C字元串,可以重用C字元串的函數庫