redis 基礎(chǔ)

redis 的源碼都是用C語言寫的,而且,整個redis的大小都很小。本文主要參考redis設(shè)計與實現(xiàn)一書,書中部分數(shù)據(jù)與最新的redis源碼有所出入,但不影響我們的使用學(xué)習(xí)。

基本類型:

建議這里的學(xué)習(xí)大家去參看一下源代碼,或者相應(yīng)的書籍,本節(jié)不對具體的細節(jié)做討論,僅總結(jié)沒種數(shù)據(jù)類型的作用。

1.動態(tài)字符串
struct sdshdr{
    // 記錄字符長度,不計 “\0”
    int len;
    // 剩余空間
    int free;
    // 字符數(shù)組
    char buff[];
}

重定義c語言中的字符串,使得字符串的大小可以改變,減少因為字符串大小改變導(dǎo)致的頻繁釋放內(nèi)存,分配內(nèi)存。以適應(yīng)數(shù)據(jù)庫的使用場景。

特點:
- 惰性空間釋放
- 避免過多的字符串
- 兼容底層的c字符串
2.鏈表

redis 內(nèi)置實現(xiàn)了鏈表的結(jié)構(gòu)。

typedef struct listNode {
    struct listNode *prev;
    struct listNode *next;
    // 定義void指針是因為可以指向任何類型
    void *value;
} listNode;


typedef struct list {
    listNode *head;
    listNode *tail;
    //復(fù)制函數(shù)
    void *(*dup)(void *ptr);
    // 釋放函數(shù)
    void (*free)(void *ptr);
    // 節(jié)點值對比函數(shù)
    int (*match)(void *ptr, void *key);
    // 節(jié)點數(shù)量
    unsigned long len;
} list;
3.字典

鍵值對,redis使用時的鍵值關(guān)系就是靠它了!

typedef struct dictht {
    // hash表數(shù)組
    dictEntry **table;
    unsigned long size;
    // 計算索引值的掩碼,大小為 size - 1
    unsigned long sizemask;
    // 已使用節(jié)點數(shù)
    unsigned long used;
} dictht;

typedef struct dictEntry {
    // 鍵值對
    void *key;
    union {
        void *val;
        uint64_t u64;
        int64_t s64;
        double d;
    } v;
    struct dictEntry *next;
} dictEntry;

// 字典中自帶了兩個hash表,一個平常使用,一個rehash的時候使用。rehash不是一次完成的,而是漸進完成的。
typedef struct dict {
    dictType *type;
    void *privdata;
    dictht ht[2];
    long rehashidx; /* rehashing not in progress if rehashidx == -1 */
    int iterators; /* number of iterators currently running */
} dict;

還有一些具體的類型定義等,可以參考源代碼。

4.跳躍表

跳躍表是一個有序的結(jié)構(gòu),先安分數(shù)排序,再按對象大小排序,聽起來是不是很像sorted set,我猜就是這種數(shù)據(jù)的底層結(jié)構(gòu)。一個跳躍表的例子:

5.整數(shù)集合

該數(shù)據(jù)結(jié)構(gòu)可以很便利的用于存取數(shù)據(jù)庫中的整數(shù)集合。

typedef struct intset {
    uint32_t encoding;
    uint32_t length;
    int8_t contents[];
} intset;

redis的整數(shù)集合還會有一定的升級和降級的操作以節(jié)省內(nèi)存。

6.壓縮列表

為了節(jié)約內(nèi)存而開發(fā)的,對于可以壓縮的小數(shù)值,小的字符串等進行鍵的壓縮。

7.對象

redis基于以上各種數(shù)據(jù)結(jié)構(gòu),建立相應(yīng)的對象結(jié)構(gòu),從而以對象構(gòu)建數(shù)據(jù)庫。對象包括:字符串對象,列表對象,集合對象,有序集合對象,哈希對象。除此之外,redis還引入引用計數(shù)和內(nèi)存回收機制。

8.數(shù)據(jù)庫
typedef struct redisDb {
    dict *dict;                 /* The keyspace for this DB */
    dict *expires;              /* Timeout of keys with a timeout set */
    dict *blocking_keys;        /* Keys with clients waiting for data (BLPOP) */
    dict *ready_keys;           /* Blocked keys that received a PUSH */
    dict *watched_keys;         /* WATCHED keys for MULTI/EXEC CAS */
    struct evictionPoolEntry *eviction_pool;    /* Eviction pool of keys */
    int id;                     /* Database ID */
    long long avg_ttl;          /* Average TTL, just for stats */
} redisDb;
  • struct redisServer
  • typedef struct client

定義了客戶端和服務(wù)器。

Redis 持久化

你可以理解為mysql一樣的在內(nèi)存留下的數(shù)據(jù)。

1.RDB 持久化

一定間隔內(nèi)將內(nèi)存的數(shù)據(jù)保存的本地的RDB文件中,它保存了某個時間點得數(shù)據(jù)集,非常適用于數(shù)據(jù)集的備份。

優(yōu)點:與AOF相比,在恢復(fù)大的數(shù)據(jù)集的時候,RDB方式會更快一些。
缺點:萬一在Redis意外宕機, 你可能會丟失間隔時間內(nèi)的數(shù)據(jù).

2.AOF 持久化

一個只進行追加的日志文件,記錄下每次執(zhí)行的命令,復(fù)原的時候把所有命令執(zhí)行一遍,不改變數(shù)據(jù)以及運行狀態(tài)的命令不記錄。過大的時候整理重寫。

優(yōu)點:備份時間極短。數(shù)據(jù)丟失量小。
缺點:AOF 文件的體積通常要大于 RDB 文件的體積。

關(guān)于持久化的詳細信息可參考官網(wǎng)指南

事務(wù)

MULTI 、 EXEC 、 DISCARD 和 WATCH 是 Redis 事務(wù)相關(guān)的命令。事務(wù)可以一次執(zhí)行多個命令, 并且?guī)в幸韵聝蓚€重要的保證:

  • 事務(wù)是一個單獨的隔離操作:事務(wù)中的所有命令都會序列化、按順序地執(zhí)行。事務(wù)在執(zhí)行的過程中,不會被其他客戶端發(fā)送來的命令請求所打斷。
  • 事務(wù)是一個原子操作:事務(wù)中的命令要么全部被執(zhí)行,要么全部都不執(zhí)行。

Redis 不支持回滾(roll back):

Redis 命令只會因為錯誤的語法而失敗(并且這些問題不能在入隊時發(fā)現(xiàn)),或是命令用在了錯誤類型的鍵上面:這也就是說,從實用性的角度來說,失敗的命令是由編程錯誤造成的,而這些錯誤應(yīng)該在開發(fā)的過程中被發(fā)現(xiàn),而不應(yīng)該出現(xiàn)在生產(chǎn)環(huán)境中。

因為不需要對回滾進行支持,所以 Redis 的內(nèi)部可以保持簡單且快速。

有種觀點認為 Redis 處理事務(wù)的做法會產(chǎn)生bug, 然而需要注意的是, 在通常情況下, 回滾并不能解決編程錯誤帶來的問題。 舉個例子, 如果你本來想通過 INCR 命令將鍵的值加上 1 , 卻不小心加上了 2 , 又或者對錯誤類型的鍵執(zhí)行了INCR , 回滾是沒有辦法處理這些情況的。

本人對于redis的 實操尚少,更多的知識來自書籍和官網(wǎng),本文尚介紹部分redis的特性,更多的學(xué)習(xí)可以參考官網(wǎng)文檔

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容