Redis研究-1.簡單動態字符串

咱們知道,在C字符串中,底層的實現是使用c字符數組來實現的,可是在高性能以及內存安全方面,使用底層的c字符串是知足不了的,舉個簡單的例子,若是你使用strcat(s,s1)函數,若是在操做以前不判斷s的空間是否可以容納s1的內容,那麼就頗有可能致使內存溢出,而致使操做失敗,所以,爲了知足性能及內存安全方面的要求,Redis實現了SDS。 數組

SDS的定義是(位於sds.h): 安全

struct sdshdr {
   
    // buf 中已佔用空間的長度
    int len; 函數

    // buf 中剩餘可用空間的長度
    int free; 性能

    // 數據空間,默認是使用C字符串的空字符結尾的
    char buf[];
}; 優化

其中每項的含義已經在註釋中說明。 設計

經過上面的定義,咱們能夠看到,sds與傳統的c字符串作了幾方面的優化: 內存

  1. 在sds中,記錄了「字符數組」的的長度len; 字符串

  2. 經過使用free能夠實現預分配策略優化。 擴展

經過這兩方面的優化,咱們能夠獲得如下方面的提高: 程序

  1. 在作須要設計到內存擴展方面的操做的時候,只要檢查free屬性,就能夠很容易獲得是否須要擴展內存,從而避免內存溢出;

  2. 在獲取字符串長度方面,不再用花費O(N)時間複雜度,只主要得到len屬性就能夠獲得長度,時間複雜度變爲O(1);

  3. 咱們知道,C字符串和底層數組之間是有密切聯繫的,所以每次增長或者縮短一個C字符串,都會涉及到對內存的分配,可是使用sds的len屬性和free屬性,能夠減小內存的重分配次數。

關於上面提到的減小內存重分配優化方面,Redis作了兩方面的優化,一個是空間預分配和惰性空間釋放。

  1. 空間預分配:這方面的優化主要是用於字符串的增加操做:當用SDS的API來修改一個SDS,且須要進行空間擴展的時候,程序首先會爲SDS分配修改所必須的空間,其次,還會分配額外的使用空間,這裏面有兩個策略:

    1. 當對SDS的內存進行修改後,SDS的長度已經超過1M了,那麼Redis會自動的爲這個SDS分配1M的free看空間;

    2. 當對SDS的內存進行修改後,SDS的長度小於1M,那麼,Redis會自動給這個SDS分配等同於len的free空間。

  2. 惰性空間釋放:對於傳統的C字符串,若是咱們要縮短,那麼就必定要釋放對應的內存,不然會致使內存泄露,可是Redis中的SDS,會把這部份內存用free來記住,因此,能夠不用立刻釋放,這部份內存能夠供之後使用,固然,Redis也提供了相關釋放的API。

     

此外,咱們對於傳統的C字符串,咱們只能存儲簡單的文本字符串,爲何呢?由於在傳統的字符串中,咱們是使用空字符來判斷這個字符串是否是結束了,所以在字符串的中間就不能使用特殊的字符。這給要在多場景應用下的Redis帶來了弊端,所以,在Redis的SDS中,並非用簡單的空字符來判斷一個buf是否是已經結束了,而是要使用len屬性來判斷是否是已經結束,所以,在Redis的SDS中的buf 是能夠存儲文本字符串以外的數據的,所以,在Redis的SDS中,buf更多的是稱做一個字節數組。固然,SDS中的buf 也是使用空字符來做爲這個串的結尾的,這是爲了兼容一部分C字符串的操做函數。

相關文章
相關標籤/搜索