Redis 一 Redis的簡單動態字串SDS

2021-09-12 23:00:47 字數 2427 閱讀 9718

redis沒有直接使用c語言傳統的字串表示(以空字元 \0 結尾的字元陣列),而是構建了一種名為簡單動態字串sds的抽象型別,並將sds用作redis的預設字串表示。

上圖中是乙個 sds物件, 字串的值是 redis; 長度為5,剩餘可用空間為3 ; 『\0』 是sds遵循了c字串以空字串結尾的慣例(之所以遵循是因為可以讓sds重用c語言的一些庫函式 ), 儲存這個空字串的乙個位元組空間不計算在 len中;

c語言使用長度為n+1的字元陣列來表示長度為n的字串,並且數字最後乙個元素總是 空字串』\0』.

對比兩個結構,我們來分析一下 為何 redis要自己定義sds

因為c字串不自己記錄自身的長度資訊,所以為了獲取長度,那麼必須每次都要遍歷整個字串才能獲取,時間複雜度是o(n).

而sds自身有個屬性len儲存了自身的長度,所以只需要獲取這個屬性就行了,時間複雜度是 o(1).

而且設定和更新sds的長度是用sds的api在執行時自動完成。

所以確保了 獲取長度strlen命令不會成為我們的瓶頸。

c字串不記錄len 除了獲取長度的複雜度高之外,還會容易造成緩衝區溢位。

比如c字串拼接char *strcat(char *dest,const char *src)操作;

需要事先為dest 分配足夠的記憶體, 如果事先忘記給dest 分配記憶體,就會產生緩衝區溢位。舉個例子

與c字元不同的是,sds的空間分配策略杜絕了發生緩衝區溢位的可能性; 當sds api需要對sds進行修改時,api會先檢查sds空間是否滿足修改所需的要求,如果不滿足 api會自動sds的空間擴充套件至執行修改所需大小。因為擴容自動由api進行,所以不會發生緩衝區溢位!

因為c字串的每次增長或者縮短都需要程式進行一次記憶體重分配的操作:

-- 增長,程式需要先通過記憶體重分配來擴充套件底層陣列的空間大小----如果忘記了,則會產生上面2的緩衝區溢位

-- 縮短,比如 階段操作(trim),那麼執行這個操作之後,需要記憶體重分配來釋放多餘的那部分空間,如果忘記會發生記憶體洩露;

因為記憶體重分配涉及複雜的演算法,並且可能需要執行系統呼叫,它通常是乙個比較耗時的操作 redis作為資料庫,如果每次都要重新記憶體分配會影響效能sds 有個字段 free 為未使用空間,通過它可以實現空間預分配惰性空間釋放兩種優化策略

空間預分配

空間預分配使用者優化sds字串增長操作.當api對乙個sds進行修改,並且需要擴充套件空間的時候,程式會為sds分配額外的未使用空間

– 如果對sds進行修改之後,sds長度(len 屬性的值)將小於1m,那麼程式分配和len屬性同樣大小的未使用空間。

例如 len增長之後等於13位元組,那麼預分配之後的記憶體大小等於

13+13+1 = 27(額外的1位元組是 空字串)

– 如果sds長度大於1m; 那麼會分配未使用空間1m;

例如增長之後sds長度將變成30m ,那麼再分配1m的未使用空間

30m+1m +1byte ;

也可以說增長之後大於1m,那麼最多隻會預分配出1m的未使用空間;

通過預分配策略,redis可以減少連續執行字串增長操作所需要的記憶體重分配次數

惰性空間釋放

惰性空間釋放用於優化sds的字串縮短操作,當api需要縮短字串時候,程式不會立即使用記憶體重新分配來**多餘的位元組;

但是sds提供了相應的api,讓我們可以在有需要的時候真正的釋放sds的未使用空間,所以不用擔心惰性空間釋放策略會造成記憶體浪費!

sds就不存在這樣的問題,redis的buf陣列是用來儲存一系列的二進位制資料。

1.redis 什麼時候用c語言字串?

redis裡面,c字串只會作為字串字面量用在一些無須對字串值進行修改的地方,例如列印日誌;

2.sds與c字串的區別

①. c字串獲取字串長度複雜度o(n);sds是o(1),因為sds有個專門的len屬性;

②.c字串可能發生緩衝區溢位,sds不會,因為sds的api會自動記憶體分配

③.c字串每次增長縮短都需要重新記憶體分配,而sds有自己的優化策略:空間預分配惰性空間釋放

④.c字串只能存文字資料,sds存的二進位制資料

redis的簡單介紹 一

redis支援的常用資料結構127.0.0.1 6379 set name toegg ok127.0.0.1 6379 get name toegg 127.0.0.1 6379 hset user name toegg1 integer 1 127.0.0.1 6379 hset user ag...

redis簡單應用一

redis是乙個開放源 bsd許可證 在記憶體資料結構儲存中,用作資料庫 快取和訊息 它支援資料結構,如字串 雜湊 列表 集合 帶有範圍查詢的排序集 位圖 超對數和地理空間索引以及radius查詢。redis具有內建複製 lua指令碼 lru驅逐 事務和不同級別的磁碟永續性,並通過ridis前哨和r...

Redis的簡單使用

redis 是完全開源免費的,遵守bsd協議,是乙個高效能的key value資料庫。redis 與其他 key value 快取產品有以下三個特點 tar zvxf redis 3.0.5.tar.gz cd redis 3.0.5 make redis server 這種方式是啟動的redis使...