2.1 SDS的定義
SDS的結(jié)構(gòu)體:
int len//記錄buf數(shù)組中已使用字節(jié)的數(shù)列
int free;//記錄buf數(shù)組中未使用字節(jié)的數(shù)列
char buf[];//字節(jié)數(shù)組,用于保存字符串
2.2 SDS與C字符串的區(qū)別
2.2.1 常數(shù)復雜度獲取字符串的長度:
C語言字符串獲取長度時間復雜度為O(n)
2.2.2 杜絕緩沖區(qū)溢出
C字符串不記錄自身長度,會造成緩沖區(qū)溢出
在對SDS進行修改時,API會檢查SDS對空間是否滿足修改所需對有求,如果不滿足,API會自動將SDS的空間擴展至執(zhí)行修改所需的大小,然后才執(zhí)行所需的修改操作
2.2.3 減少修改字符串時帶來的內(nèi)存重分配次數(shù)
1.空間預分配
用于優(yōu)化SDS字符串增長操作:當一個API對SDS進行修改,并且需要對SDS對空間進行擴展的時候,程序不僅會為SDS分配修改所必須要的空間,還會為SDS分配額外的未使用空間
當SDS的長度小于1MB,程序分配和len屬性同樣大小的未使用空間
當SDS的長度大于等于1MB,程序會分配1MB的未使用空間。
2.惰性空間釋放
用于優(yōu)化SDS字符串縮短操作:當SDS的API需要縮短SDS保存的字符串時,程序并不立即使用內(nèi)存重分配來回收縮短后多出來的字節(jié),而是使用free屬性將這些字節(jié)的數(shù)量記錄起來,并等待將來使用。
2.2.4 二進制安全
C字符串只能存儲文本數(shù)據(jù)
Redis不是使用buf來保存字符,而是用它來保存一系列二進制數(shù)據(jù)
2.2.5 兼容部分C字符串函數(shù)
可以重用一部分庫定義的函數(shù)
3.鏈表
鏈表提供了高效的節(jié)點重排能力,以及順序性的節(jié)點訪問方式,并且可以通過增刪節(jié)點來靈活地調(diào)整鏈表的長度
鏈表鍵、發(fā)布與訂閱、慢查詢、監(jiān)視器等功能也用到來鏈表
3.1 鏈表和鏈表節(jié)點的實現(xiàn)
listnode{
listnode *head;
listNode *tail;
unsigned long len;
void *(*dup)(void *ptr);
void (*free)(void *ptr);
int (*match)(void *ptr, void *key);
}
Redis鏈表實現(xiàn)特性:
雙端:prev指針,獲取當前節(jié)點的前置節(jié)點,next指針,用來獲取當前節(jié)點的后置節(jié)點
無環(huán):表頭節(jié)點的prev指針和next指針都指向NULL,對鏈表的訪問以NULL為終點
帶有表頭節(jié)點和表尾節(jié)點指針:通過list的head指針和tail指針,程序獲取鏈表的表頭節(jié)點和表尾節(jié)點的復雜度為O(1)
帶鏈表長度計數(shù)器:程序使用list結(jié)構(gòu)的len屬性來對list持有的鏈表節(jié)點進行計數(shù),程序獲取鏈表長度的時間復雜度為O(1)
多態(tài):鏈表節(jié)點使用void*指針來保存節(jié)點值,可以通過dup,free,match為節(jié)點值設置類型特定函數(shù),所以鏈表可以用于保存各種不同類型的值