《Redis設計與實現》讀書筆記一
Redis是什麼
Redis(全稱:Remote Dictionary Server 遠程字典服務)是一個開源的使用ANSI C語言編寫、支持網絡、可基於內存亦可持久化的日誌型、Key-Value數據庫,並提供多種語言的API。 ——百度百科
Redis的常見應用場景
1.做緩存
Redis讀寫性能優異,且支持事務,在使用時能保證數據的一致性。
2.應對海量數據和高併發
3.消息隊列
消息隊列,顧名思義,就是用來存放消息的容器,多用於分佈式系統,生產者產生消息,消費者消費消息。使用消息隊列可以通過異步處理緩衝高併發事件,比如大量數據庫寫入事件,可以先存入消息隊列中,而後由數據庫異步執行。
第二章 簡單動態字符串
雖然Redis是用C語言編寫,但它並沒有直接使用C語言傳統的字符串表示,而是自己構建了一種叫做簡單動態字符串(SDS)的抽象類型作爲Redis的默認字符串表示。Redis只在使用靜態字符串時才使用C語言的字符串。
來看實現:
struct sdshdr{
//記錄buf數組中已使用字節的數量(不算最後的'\0')
int len;
//記錄buf數組中未使用字節的數量
int free;
//字節數組,用於保存字符串
char buf[]
}
圖中,free爲0,len爲5.
底層採用C字符串的好處是可以直接使用一部分C語言字符串函數庫的函數,而無須爲SDS編寫專門的打印函數。
SDS比C字符串更加安全:
1.空間預分配
當SDS的API對一個SDS進行修改,並且需要對SDS進行空間擴展時,程序不僅會爲SDS分配修改所需的空間,還會爲SDS分配額外的未使用的空間。
預分配公式:(1)若修改後SDS的長度小於1MB,那麼程序將分配和len屬性同樣大小的未使用空間。(2)若修改後的SDS長度大於1MB,那麼程序將分配1MB的未使用空間。
2.惰性空間釋放
當SDS的API需要縮短SDS保存的字符串時,程序並不立即使用內存重分配來回收字節,而是使用free屬性將這些字節記錄起來,並等待使用。
思考:如果有很多很長的SDS,在假性釋放後,會不會造成浪費?
答:SDS也提供了相應的API,可以真正的釋放SDS未使用的空間。
二進制安全
二進制安全是指對所有二進制文件一視同仁,不對其中某些01序列賦予特殊意義,防止損壞二進制文件。
SDS是二進制安全的,而C字符串不是。例如“Redis Cluster”,C字符串所用的函數只會識別到Redis。
總結
比起C字符串,SDS具有以下優點:
1.常數複雜度獲取字符串長度。
2.杜絕緩衝區溢出。
3.減少修改字符串長度時所需的內存重分配次數。
4.二進制安全。
5.兼容部分C字符串函數。
第三章 鏈表
Redis中,鏈表健、發佈與訂閱、慢查詢、監視器等功能也用到了鏈表。
來看實現:
typedef struct listNode{
//前置節點
struct listNode *prev;
//後置節點
struct listNode *next;
//節點的值
void *value;
}listNode
Redis實現了list結構來儲存鏈表,使得一些常用操作的時間複雜度控制在O(1).
typedef struct list{
//表頭節點
listNode *head;
//表尾節點
listNode *tail;
//節點數量
unsigned long len;
//節點值複製函數
void *(*dup)(void *ptr);
//節點釋放函數
void (*free)(void *ptr);
//節點比較函數
int (*match)(void *ptr,void *key);
}
Redis鏈表特點
1.是無環鏈表。
2.Redis的鏈表可以用於保存各種不同類型的值。