redis源碼剖析(六)—— Redis 數據庫、鍵過期的實現

文章目錄

    • 數據庫的實現
    • 數據庫讀寫操作
    • 鍵的過期實現

數據庫的實現

我們先看代碼 server.h/redisServer

struct redisServer{...//保存 db 的數組redisDb *db;//db 的數量int dbnum;...
}

再看redisDb的代碼:

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 */int id;                     /* Database ID */long long avg_ttl;          /* Average TTL, just for stats */
} redisDb;

總體來說redis的 server 包含若干個(默認16個) redisDb 數據庫。

在這里插入圖片描述
Redis 是一個 k-v 存儲的鍵值對數據庫。其中字典 dict 保存了數據庫中的所有鍵值對,這個地方叫做 keyspace 直譯過來就是“鍵空間”。

所以我們就可以這么認為,在 redisDb 中我們使用 dict(字典)來維護鍵空間。

keyspace 的 key 是數據庫的 key,每一個key 是一個字符串對象。注意不是字符串,而是字符串對象。

keyspace 的 value 是數據庫的 value,這個 value 可以是 redis 的,字符串對象,列表對象,哈希表對象,集合對象或者有序對象中的一種。

數據庫讀寫操作

所以對于數據的增刪改查,就是對 keyspace 這個大 map 的增刪改查。

當我們執行:

redis SET mobile "13800000000"
實際上就是為 keyspace 增加了一個 key 是包含字符串“mobile”的字符串對象,value 為包含字符“13800000000”的字符串對象。

看圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-eYHieGwP-1573628639724)(media/15663864485138/15663865237031.jpg)]

對于刪改查,沒啥好說的。類似java 的 map 操作,大多數程序員應該都能理解。

需要特別注意的是,再執行對鍵的讀寫操作的時候,Redis 還要做一些額外的維護動作:

  • 維護 hit 和 miss 兩個計數器。用于統計 Redis 的緩存命中率。
  • 更新鍵的 LRU 時間,記錄鍵的最后活躍時間。
  • 如果在讀取的時候發現鍵已經過期,Redis 先刪除這個過期的鍵然后再執行余下操作。
  • 如果有客戶對這個鍵執行了 WATCH 操作,會把這個鍵標記為 dirty,讓事務注意到這個鍵已經被改過。
  • 沒修改一次 dirty 會增加1。
  • 如果服務器開啟了數據庫通知功能,鍵被修改之后,會按照配置發送通知。

鍵的過期實現

Redis 作為緩存使用最主要的一個特性就是可以為鍵值對設置過期時間。

在 Redis 中與過期時間有關的命令

  • EXPIRE 設置 key 的存活時間單位秒
  • EXPIREAT 設置 key 的過期時間點單位秒
  • PEXPIRE 設置 key 的存活時間單位毫秒
  • PEXPIREAT 設置 key 的過期時間點單位毫秒

其實這些命令,底層的命令都是由 REXPIREAT 實現的。

在 redisDb 中使用了 dict *expires,來存儲過期時間的。其中 key 指向了 keyspace 中的 key(c 語言中的指針), value 是一個 long long 類型的時間戳,標定這個 key 過期的時間點,單位是毫秒。

如果我們為上文的 mobile 增加一個過期時間。

redis PEXPIREAT mobile 1521469812000
這個時候就會在過期的 字典中增加一個鍵值對。如下圖:

在這里插入圖片描述
對于過期的判斷邏輯就很簡單:

  1. 在 字典 expires 中 key 是否存在。
  2. 如果 key 存在,value 的時間戳是否小于當前系統時間戳。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/382366.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/382366.shtml
英文地址,請注明出處:http://en.pswp.cn/news/382366.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

多益網絡 視頻面試面試總結20180816

1.首先是自我介紹:因為等了半個小時,所以有點兒緊張,只說了一下自己的學校,愛好和興趣; 2.介紹了一個自己的最成功的項目:我介紹了一個關于GPS導航的項目,介紹了項目的內容和項目的一些工作&am…

redis源碼剖析(七)—— Redis 數據結構dict.c

文章目錄dict.hdict.cdict.h //定義錯誤相關的碼 #define DICT_OK 0 #define DICT_ERR 1//實際存放數據的地方 typedef struct dictEntry {void *key;void *val;struct dictEntry *next; } dictEntry;//哈希表的定義 typedef struct dict {//指向實際的哈希表記錄(用數組開鏈的…

簡述linux中動態庫和靜態庫的制作調用流程

假設現在有這些文件:sub.c add.c div.c mul.c mainc head.h(前4個.C文件的頭文件) 1.靜態庫制作流程 gcc -c sub.c add.c div.c mul.c -->生成 .o目標文件文件 ar rcs libmycal.a *.o …

redis源碼剖析(八)—— 當你啟動Redis的時候,Redis做了什么

文章目錄啟動過程初始化server結構體main函數會調用initServer函數初始化服務器狀態載入持久化文件,還原數據庫開始監聽事件流程圖啟動過程 初始化server結構體從配置文件夾在加載參數初始化服務器載入持久化文件開始監聽事件 初始化server結構體 服務器的運行ID…

linux中錯誤總結歸納

1.使用gcc編譯C文件,C文件在for循環語句中出現變量定義 編譯器提示錯誤:“for”loop initial declarations are only allowed in C99 mode. note:use option -stdc99or-stdgnu99 to compile; 原因:gcc的標準是基于c89的,c89不能在…

redis源碼剖析(十一)—— Redis字符串相關函數實現

文章目錄初始化字符串字符串基本操作字符串拼接操作other獲取指定范圍里的字符串將字符串中的所有字符均轉為小寫的形式將字符串中所有字符均轉為大寫的形式字符串比較other#define SDS_ABORT_ON_OOM#include "sds.h" #include <stdio.h> #include <stdlib.…

makefile內容小結

makefile中每個功能主要分為三部分&#xff1a;目標&#xff0c;依賴條件和命令語句 1.支持對比更新的Makefile寫法&#xff08;只會編譯文件時.o文件和.c文件時間不一致的文件&#xff09; 2.使用makefile自動變量和自定義變量的makefile寫法 其中&#xff1a;這三個符號為ma…

事務隔離級別動圖演示

事務的基本要素&#xff08;ACID&#xff09; 原子性&#xff08;Atomicity&#xff09; 事務開始后所有操作&#xff0c;要么全部做完&#xff0c;要么全部不做&#xff0c;不可能停滯在中間環節。事務執行過程中出錯&#xff0c;會回滾到事務開始前的狀態&#xff0c;所有的…

C/C++的優點和缺點

1.C/C語言的優點 C語言是面向過程的語言&#xff0c;常用來編寫操作系統。C語言是從C語言發展過來的&#xff0c;是一門面向對象的語言&#xff0c;它繼承了C語言的優勢&#xff0c;同時也添加了三個主要的內容&#xff1a;Oriented-Object class,Template,STL. 1)C/C可以潛入…

C/C++命令行參數那點事

int main(int argc, char *argv[ ]); 1.命令行參數&#xff1a;在命令行中給定的參數&#xff1b; 2.命令行參數在對函數main的調用時&#xff0c;主要有兩個參數送到main,一個是argc(argument count),命令行參數的個數&#xff0c;另外一個是argv,命令行參數的數組,命令行參…

mysql row_id為什么是6字節?為什么是8字節

mysql row_id是幾個字節&#xff1f; row_id InnoDB表中在沒有默認主鍵的情況下會生成一個6字節空間的自動增長主鍵 row_id是整型還是字符型&#xff1f; 源代碼中 row_id 是 ib_uint64_t 這是 8字節 uint64_t 是整形 為什么是6個字節&#xff1f; P.S. Base64編碼說明 B…

linux中的man文檔結構

使用命令 man chapter章節號查找的內容

偽隨機數和真隨機數

偽隨機數小項目 猜數字游戲 //C語言 猜數字游戲 https://blog.csdn.net/csdn_kou/article/details/79785709 C語言之隨機數生成超詳解 https://blog.csdn.net/csdn_kou/article/details/79788815 在上面的文章中&#xff0c;使用固定函數就一直是生成固定的隨機結果&#…

linux中的IO函數

1)open函數&#xff1a;以特定的方式打開一個文件&#xff1b; 頭文件&#xff1a;sys/type.h sys/stat.h fcntl.h 返回值&#xff1a;錯誤則返回-1&#xff0c;正確則返回文件描述符&#xff08;int類型&#xff0c;范圍為3~1023,文件的標號&#xff09; 函數原型&#xff…

ps -ef和ps aux

ps -ef和ps aux ps -ef unix風格 -e 列出所有進程 -f 完整格式 UID PID PPID C STIME TTY TIME CMD root 1 0 0 8月27 ? 00:25:08 /usr/lib/systemd/systemd --switched-root --system --deserialize 22 root 2 0 0 8月…

Linux中screen的用法

screen 查看當前有多少窗口 [rootpython ~]# screen -ls There are screens on:20706.khz (Attached)20679.khz (Attached)20453.khz (Attached)20143.khz (Detached)16993.pts-2.python (Attached) 5 Sockets in /var/run/screen/S-root.新建一…

linux文件操作相關函數

&#xff08;1&#xff09;stat函數&#xff1a;顯示文件的相關信息&#xff08;類似于 ls -l的感覺&#xff09; 頭文件及函數原型&#xff1a; 函數參數:path:文件的路徑&#xff0c;buf是指待寫入的文件信息&#xff0c;fd:表示文件描述符&#xff1b; stat,fstat,lstat三者…

linux查看硬盤是不是ssd固態硬盤

linux查看硬盤是不是ssd固態硬盤 sdb是ssd、sr0是SATA [root 01 ~]# cat /sys/block/sdb/queue/rotational 0 [root 01 ~]# cat /sys/block/sr0/queue/rotational 1

linux目錄操作函數

&#xff08;1&#xff09;chdir函數&#xff1a;修改當前進程的路徑 函數頭文件及原型&#xff1a; 參數&#xff1a;要修改的文件路徑或文件描述符&#xff08;一般是當前空閑最小的&#xff09; 返回值&#xff1a;成功&#xff08;0&#xff09;&#xff0c;失敗&#xff0…

linux中的dup和fcntl的用法

&#xff08;1&#xff09;dup函數&#xff1a;文件描述符的拷貝 函數頭文件及函數原型&#xff1a; 參數&#xff1a;原來的文件描述符&#xff0c;新的文件描述符&#xff0c;標志位&#xff1b; 返回值&#xff1a;成功&#xff08;返回新的文件描述符&#xff09;失敗&…