Redis的字符串類型

原由

今天面試慘敗,面試官問了不到10個問題就讓我出來寫題了……對其中的一個題目印象深入:c++

Redis獲取字符串長度的複雜度是多少?

剛開始我是一臉懵逼的,由於不清楚Redis的字符串類型是怎麼實現的,因此徹底無法答下去了……回來後立刻開始學習。面試

字符串類型

字符串是Redis裏很是常見的類型,而用C實現的RedisJava不同。在C裏字符串是用長度爲N+1的字符數組實現的,且使用空字符串'\0'做爲結束符號。獲取字符串的長度須要遍歷一遍,找到空字符串'\0'才知道字符串的長度,複雜度是O(N)數據庫

若是有一個長度很是大的字符串,單線程的Redis獲取它的長度就可能會阻塞好久,這是不能接受的,因此Redis須要一種更高效的字符串類型。數組

SDS

Redis實現了一個叫SDS(simple dynamic string)的字符串類型,其中有兩個變量來分別表明字符串的長度和字符數組未使用的字符數量,這樣就能夠用O(1)的複雜度來獲取字符串的長度了,並且一樣也是使用空字符串'\0'做爲結束符號。學習

struct sdshdr {
    // 字符串長度
    int len;
    // 字符數組未使用的字符數量
    int free;
    // 保存字符串的字符數組
    char buf[];
}

如今已經能夠回答上面的面試題了,實際上是很是簡單的一個問題,怪不得答不出來面試官立刻就說面試結束了……優化

擴容機制

SDS在字符數組空間不足於容納新字符串的時候會自動擴容。ui

若是把一個C字符串拼接到一個SDS後面,當字符數組空間不足時,SDS會先擴容到恰好能夠容納新字符串的長度,而後再擴充新字符串的空字符長度,最終SDS的字符數組長度等於 2 * 新字符串 + 1(結束符號'\0')。不過當新字符串的大小超過1MB後,擴充的空字符長度大小會固定爲1MBspa

之因此會有這個機制,是由於Redis做爲一個NoSQL數據庫,會頻繁的修改字符串,擴容機制至關於給SDS作了一個緩衝池。把SDS連續增加N次字符串須要內存重分配N次優化成了SDS連續增加N次字符串最多須要內存重分配N次,這其實和Java裏的StringBuilder實現思想是同樣的。線程

後記

此次翻車是有緣由的,我看過兩本關於Redis的書,裏面都是講Redis如何實戰的可是並無講Redis的設計和實現。這也就致使了面試很尷尬,由於面試官最喜歡問原理相關的東西了,因此之後學習技術的時候不要從實戰類的書籍開始了,仍是先看懂原理比較好。設計

參考資料

這是《Redis設計與實現》裏字符串一節的總結。

相關文章
相關標籤/搜索