一.介紹sds:
在redis中並沒有直接使用c語言的字串(以空字元結尾的字元陣列),而是構建了一種名為簡單動態字元(sds)的抽象型別,並且sds用作redis的預設字串。
在redis中乙個可以被修改的字串值都是用sds來表示這樣乙個字串值的,因此在redis中鍵值對的底層都是由sds來實現的。
舉例:如果客戶端執行命令:set msg "hello world",那麼redis將在資料庫中建立乙個新的鍵值對,其中對於sds不僅用來儲存redis中的字串值,還被用作緩衝區(buffer):鍵值對的鍵是乙個字串物件,物件的底層實現是乙個儲存著字串"msg"的sds
鍵值對的值也是乙個字串物件,物件的底層實現是儲存著字串"hello world"的sds。
aof模組中的aof緩衝區
客戶端狀態中的輸入緩衝區。
二.定義
每個sds.h/sdshdr結構表示乙個sds值:
struct sdshdr{例子如下圖://記錄buf陣列中已使用位元組的數量
//等於sds所儲存字串的長度
int len;
//記錄buf陣列陣列中未使用位元組的數量
int free;
//位元組陣列,用於儲存字串
char buf;
上圖中定義了乙個redis字串,該字串存放的情況如上圖中。
sds遵循c語言字串以空字元結尾的慣例,儲存空字元的1位元組空間不計算在sds的len屬性中。並且為空字元分配額外的1位元組空間,以及新增空字元到字串末尾等操作都是由sds函式自動完成。這樣的乙個好處是可以重用c語言字串函式庫中的函式。
上圖的sds中並沒有分配未使用空間
下面為上圖中的redis分配未使用空間,如下圖:
圖中在redis字串後面新增了五個空位元組,這個五個位元組表示分配的未使用空間。因此free=5
2.1分析屬性 len
在sds中len屬性記錄sds的長度,所以獲取乙個sds長度的複雜度僅為o(1),這確保獲取字串長度的工作不會成為redis的效能瓶頸。
設定和更新sds長度的工作是由sds的api在執行時自動完成的,使用sds無需手動修改長度。
2.2杜絕緩衝區溢位
在平時初始化陣列時一般需要給陣列初始化一定的長度,那麼在sds中是如何保證buf(char陣列)的記憶體時足夠的呢?並且保證buf不會記憶體溢位的呢?
在sds中設定了一套空間分配策略,該策略完全杜絕了發生緩衝區溢位的可能性:
當sds api需要對sds進行修改時,api會先檢查sds的空間是否滿足修改所需要的要求,如果不滿足的話,api會自動講sds的空間擴充套件至執行修改所需的大小,然後才執行實際的修改操作,如果滿足則直接修改。因此使用sds不需要手動修改sds的空間大小,也不會出現緩衝區溢位的問題。
例如:我們使用sds api中的拼接字串函式sdscat拼接msg字串,那麼執行sdscat(msg,'cluster')
此時sds在執行sdscat(msg,'cluster')之前會檢查msg的長度是否足夠,如果msg目前的空間不足以拼接cluster,那麼sdscat會先擴充套件msg的空間,然後再去執行sdscat(msg,'cluster'),拼接完成後如圖
sdscat操作不僅對sds進行拼接操作,還會為sds分配13位元組的未使用空間(free=13),拼接後的字串長度是13,這就涉及到了sds的空間預分配策略。
2.3空間預分配策略
空間預分配策略主要用於優化sds的字串增長操作:當sds的api對乙個sds進行修改,並且需要對sds進行空間擴充套件時,此時會為sds分配額外的未使用空間。
空間預分配策略如下:
通過空間預分配策略redis可以減少連續執行字串增長操作所需的記憶體重分配次數。
2.4惰性空間釋放
惰性空間釋放主要用於優化sds的字串縮短操作,當sds的api需要縮短sds儲存的字串時,程式並不立即使用記憶體重分配來**縮短後多出來的位元組,而是使用free屬性將這些位元組的數量記錄起來,並等待以後使用。
例如通過sds api中的sdstrim函式來移除指定的字元,當執行sdstrim(msg,"cluster")後,sds並不會釋放cluster的7位元組空間,而是將這7個位元組保留在sds中,如果以後對sds進行增長操作,則這些空間就會排上用場。
2.5二進位制安全
在sds的buf陣列中儲存的並不是字元,而是儲存的一系列的二進位制資料,這樣就確保了redis可以適用各種不同的場景。
內容來自《redis設計與實現》黃健巨集著
字串右旋 字串去重
1.將n個字元的陣列,迴圈右移k位。時間複雜度o n 實現思路 兩種實現思路 1.借助輔助空間,按照後面的順序進行拷貝,最後拷貝回字串 2.三次反轉法就可實現 include void rotatekth char str,int size,int k 2.附加題 刪除小寫字母字串中重複字元。如果可...
字串去重
字串去重,思路是在乙個字串例如 strstrrtsiiiinnnggggg 中,遍歷所有的字元,拼接到stringbuffer中。在執行速度上來看stringbuffer的拼接速度要快與string。通過str.charat i 的方法得到當前遍歷到的字元。通過indexof方法得到該字元第一次出現...
字串去重
doctype html en utf 8 viewport content width device width,initial scale 1.0 document title head 思路 1.宣告乙個空字元 2.將需要去重字元,乙個乙個新增到空字串中 條件 s裡面沒有這個字元,就加進去 v...