Redis是使用C語言實現的,沒有使用C語言傳統的字符串表示,而是使用本身構建的一種簡單動態字符串(simple dynamic string, SDS)的抽象類型,並用做Redis的默認字符串表示。依然遵照了C語言中以'\0'結尾的慣例。數組
除了保存字符串值以外,還被做用緩衝區(buffer):AOF模塊中的AOF緩衝區一級客戶端狀態中的輸入緩衝區,都是由SDS實現。安全
**注:**在保存空字符('\0'字符)空間不計算在SDS的len屬性中,爲空字符分配額外的1字節空間。對於空字符到字符串末尾等操做,均由SDS函數自動完成。遵循這一慣例,好處是SDS能夠直接重用一部分C字符創函數庫中的函數。jsp
C字符串不記錄自身長度信息,爲了獲取一個C字符串的長度,必須遍歷整個字符串,整個操做的複雜度爲O(N)。函數
SDS在len屬性中記錄了SDS字符串自己的長度,獲取長度的操做複雜度僅爲O(1)。SDS的長度操做由API自動完成,無須進行任何手動修改長度的工做。優化
C字符串容易形成緩衝區溢出(buffer overflow)。例如:在C字符串進行拼接時,源字符串長度未分配足夠多的內存,就會產生緩衝區溢出的問題。spa
SDS在字符串拼接以前則會先判斷源字符串的內存是否足夠。不夠則分配足夠的空間,從而杜絕了發生緩衝區溢出的肯能性。code
C字符串底層實現老是一個N+1長度的數組(額外的一個字符空間用於保存空字符)。若進行拼接操做,在執行這個操做前,須要經過內存重分配來擴展底層數組的空間大小,不然會產生緩衝區溢出。若進行截斷操做,須要經過內存重分配來釋放字符串再也不使用的空間,不然會產生內存泄漏。cdn
SDS中buf數組的長度 不必定就是字符數量加一,數組中能夠包含未使用的字節,數量則保存在free屬性中。blog
用於優化SDS的字符串增加操做:當SDS進行空間擴展時,程序不只會爲SDS分配必須的空間,還會分配額外的未使用空間。內存
1. 若是SDS的長度(len的屬性值)小於1MB,則會分配和len一樣大小的未使用free空間。此時實際長度爲:len + free + 1 字節
2. 若是SDS的長度大於等於1MB,則會分配1MB的未使用空間。
複製代碼
經過空間的預分配策略,Redis能夠減小連續執行字符串增加操做所需的內存重分配次數。SDS將連續增加N次字符串所需的內存重分配次數從一定N次下降爲最多N次。
用戶優化SDS的字符串的縮短操做:當SDS進行空間縮短時,程序不當即使用內存重分配來回收縮短後多出來的字節,而是使用free屬性將多餘的字節記錄起來,等待未來使用。
惰性釋放的策略,SDS避免了縮短字符串時須要的內存重分配操做,併爲未來的增加提供了優化。也能夠真正地釋放未使用空間,沒必要擔憂會形成的內存浪費。
複製代碼
避免了C字符串中,讀取到空字符('\0')結束讀取的問題。SDS結構中的buf數組,都會以二進制的方式進行處理,它保存的是一些列的二進制數據。SDS中使用len屬性值判斷字符串是否結束。Redis不只能夠存文本數據,還能保存任意格式的二進制數據。
遵循C字符的要求,能夠複用C中的一些函數,避免了沒必要要的代碼重複。