初學redis

剛開始看redis..總結一下看到的東西,有些話是參考網上的,有些話是類似自己白話說的,若有不對請指正。

Redis

redis常用五種數據結構:string hash list set sortedset

 

String:(字符串)

一個key對應一個value,是二進制安全的

typedef char *sds;

struct sdshdr {

        int len;// 記錄 buf 數組中已使用字節的數量  等於 SDS 所保存字符串的長度

        int free;// 記錄 buf 數組中未使用字節的數量

        char buf[];// 字節數組,用於保存字符串

};

一個sds實際申請的內存: sizeof(sdshdr)+len+free+1 剛開始free爲0,當需要增長時根據策略進行動態增長

 

List:(列表/雙向鏈表)

typedef struct listNode {

    struct listNode *prev;  //指向前一個節點

    struct listNode *next; //指向後一個節點

void *value;//值

} listNode;//節點

 

typedef struct list {

    listNode *head;//雙向鏈表的頭節點

listNode *tail;//雙向鏈表的尾節點

    void *(*dup)(void *ptr);//複製

    void (*free)(void *ptr);//釋放

    int (*match)(void *ptr, void *key);//匹配

unsigned long len;//鏈表長度

} list;//雙向鏈表/列表

typedef struct listIter {

    listNode *next;//指向列表的某個節點

int direction;//迭代方向

} listIter;//訪問鏈表的迭代器

 

Hash:(哈希)

是一個string類型的field和value的映射表,適用於儲存對象

Set:(集合)

底層實現是哈希,一般情況使用0號哈希表,如果在rehash時,則會同時使用0號和1號哈希表

哈希表採用鏈地址法解決鍵衝突,自動rehash收縮或者擴展哈希表

typedef struct dictEntry {

    void *key; //鍵

    union {

        void *val;

        uint64_t u64;

        int64_t s64;

    } v; //值

struct dictEntry *next;//指向下一個節點

} dictEntry;//哈希節點

 

typedef struct dictht {

    dictEntry **table; //桶 哈希節點類型

    unsigned long size;//指針數組大小

    unsigned long sizemask;//指針數組掩碼,用於計算索引值    

unsigned long used;//hash表現有節點數量

} dictht;//哈希表

 

typedef struct dict {

    dictType *type; //類型處理函數

    void *privdata; //類型處理函數私有值

    dictht ht[2];//兩個hash表

int rehashidx; //rehash標示,爲-1表示不在rehash,不爲0表示正在rehash的桶

int iterators; //當前正在運行的安全迭代器數量

} dict;//集合有2個哈希表

Rehash:創建比ht[0]->table更大的ht[1]->table,size爲大於use*2的2的指數,開始值爲4,然後把ht[0]的鍵值對遷移到ht[1]中,將ht[0]中數據清空,將新的ht[1]替代ht[0]。

進行rehash的條件:

自然 rehash : ratio >= 1 ,且變量 dict_can_resize 爲真。

強制 rehash : ratio 大於變量 dict_force_resize_ratio (目前版本中, dict_force_resize_ratio 的值爲 5 )。

Sorted set:(有序集合)

Redis 有序集合和集合一樣也是string類型元素的集合,且不允許重複的成員。

不同的是每個元素都會關聯一個double類型的分數。redis正是通過分數來爲集合中的成員進行從小到大的排序。

有序集合的成員是唯一的,但分數(score)卻可以重複。

typedef struct zskiplistNode {

    robj *obj; // 成員對象

    double score;// 分值

    struct zskiplistNode *backward; // 後退指針

    struct zskiplistLevel {

        struct zskiplistNode *forward; // 前進指針

        unsigned int span;// 跨度

    } level[]; // 層

} zskiplistNode;//有序集合的節點

 

typedef struct zskiplist {

    struct zskiplistNode *header, *tail;  // 表頭節點和表尾節點

    unsigned long length;// 表中節點的數量

    int level;// 表中層數最大的節點的層數

} zskiplist;//有序集合

數據庫:

Redis客戶端默認目標數據庫爲0號數據庫

數據庫由dict(保存鍵值對)和expires(保存鍵的過期時間)兩字典組成

 

RDB持久化

服務器中的非空數據庫以及他們的鍵值對統稱爲數據庫狀態。

RDB持久化可將數據庫狀態保存在磁盤,可手動執行也可定期執行。通過該文件可還原數據庫狀態。

RDB文件是經過壓縮的二進制文件,對於不同類型的鍵值對,RDB會以不同方式來保存。

SAVE或者BGSAVE可生成rdb文件。

SAVE會阻塞服務器進程,到創建完成前都不能處理任何命令請求。BGSAVE會派生出一個子進程來創建RDB,父進程就可以執行其他命令了。

服務器啓動時如果檢測到RDB文件就會載入,如果開啓了AOF持久化功能,則優先用AOF文件。

AOF持久化

AOF持久化是通過保存redis服務器所執行的寫命令來記錄數據庫狀態。

實現:命令追加、文件寫入、文件同步

命令追加:服務器執行寫命令過後,會將寫命令追加到服務器狀態緩衝區的末尾。

文件寫入與同步:在每次結束一個事件循環前,會考慮將緩衝區的內容寫入AOF文件。

 

發佈和訂閱:

SUBSCRIBE:客戶端可以訂閱一個或多個頻道,成爲這些頻道的訂閱者。每當有客戶端向這些頻道發消息的時候,頻道的所有訂閱者都可以收到這條消息。

PSUBSCRIBE:客戶端可以訂閱一個或多個模式,成爲這些模式的訂閱者。每當有客戶端向這些頻道發消息的時候,訂閱頻道以及與這個頻道相匹配的模式的訂閱者都會收到消息。

 

事務:redis用multi和exec打包事務

以multi開始exec結束,服務器執行事務期間不會中斷去執行其他命令。

redis不支持回滾機制,若一個事務在入隊命令過程中,出現了命令不存在或者格式錯誤則服務器拒絕執行此事務。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章