Redis 中的數據庫

前面咱們花了不少的時間介紹了 redis 中基本的數據結構,及其內部的實現狀況,這些都是很是基礎的東西,可能不經意間你就會用到他們,但願你花點時間瞭解一下。java

接下來,咱們將走近 redis 數據庫,學習各類操做 redis 的命令,並介紹它的一些實現策略以及集羣配置等等內容。git

1、redis 中的數據庫

server.h/redisServer 結構中有一個字段,db 字段:程序員

redisDb *db;
複製代碼

db 被定義成一個 redisDb 數組,其中 redisDb 的定義以下:github

typedef struct redisDb {
    dict *dict;                 
    dict *expires;              
    dict *blocking_keys;        
    dict *ready_keys;          
    dict *watched_keys;         
    int id;                    
    long long avg_ttl;      
} redisDb;
複製代碼

咱們常常說 redis 具備十六個數據庫,能夠切換不通的數據庫作數據隔離,這裏你就能夠將一個 redisDb 實例理解爲一個數據庫,而 db 指針則能夠訪問 redis 預約義的全部數據庫。正則表達式

其中,dict 是一個字典結構,用於實際存儲數據,expires 也是一個字典結構,它存儲的是數據庫中全部設置過時時間的鍵值對,保存他們的過時時間,是一個 UNIX 時間戳。redis

blocking_keys 存儲了被阻塞的鍵集合,ready_keys 存儲的是能夠解除阻塞的鍵集合,watched_keys 存儲的是正在被 watch 命令監控的鍵的集合,id 記錄的是當前數據庫的一個編號,avg_ttl 收集了全部鍵剩餘存活時間的一個平均值。這一部分的幾個字段的值這裏不作詳細的解釋,沒有基本的知識儲備,不容易理解的,後面咱們還會遇到的。數據庫

server.h/redisServer 結構中還有一個字段,dbnum 字段:數組

int dbnum;  /* Total number of configured DBs */
複製代碼

與此同時,redis.conf 配置文件中,默認有這麼一項配置。bash

image

因此,咱們啓動 redis-server 的時候,會根據配置文件中給定的配置默認建立 16 個數據庫。服務器

一、select 命令

select 命令用於咱們切換數據庫,例如:

image

默認鏈接上 redis-server 的客戶端使用 0 號數據庫,鑑於 redis 並無提供給客戶端查詢當前使用數據庫編號的命令,因此建議執行 redis 命令以前,尤爲是修改、添加命令,先執行下切換數據庫的命令。

二、set 命令

set 命令其實無需過多介紹,它向數據庫中添加一個鍵值對,大部分狀況下,鍵會是一個字符串對象,而值可取咱們 redis 的五大對象之一。

由於 redisDb 底層是字典結構,鍵不容許重複,故而 set 命令一樣適用於更新操做。

三、del 命令

del 命令用於刪除數據庫中一個鍵值對,標準語法以下:

del [KEY]
複製代碼

例如:

image

四、get 命令

get 命令用於獲取一個鍵值對的值,標準語法是:

get [KEY]
複製代碼

具體事例就再也不演示了,get 命令對應於 set 命令,只能獲取由 set 命令添加的字符串對象鍵值對,而例如一些集合對象,或列表對象須要用相似於 sadd、zadd 等命令進行數據庫的添加,天然 get 命令也是沒法獲得這些鍵值對對象值的。

五、其餘命令

第一個咱們介紹 dbsize 命令,它返回當前數據庫有多少鍵值對,基本語法格式以下:

dbsize
複製代碼

第二個咱們要介紹的是 flushdb 命令,它用於清空當前數據庫,這是一個很是危險的命令,謹慎使用,基本語法格式以下:

flushdb
複製代碼

image

第三個咱們要介紹一個 kyes 命令,它會返回數據庫中全部符合匹配規則的鍵的集合,這個規則起初我覺得是正則表達式,幾番操做後發現匹配不上,查閱資料貌似不是正則,而且僅有如下三種規則:

  1. ?:用於匹配單個字符
  2. *:用於匹配零個或者多個字符
  3. []:能夠用來指定模式的選擇區間

正則表達式中的問號,用於匹配前一個字符出現零次或一次,即要麼出現要麼不出現,而咱們這裏的 keys 模式,問號具備不一樣的意義。

image

不過 keys 命令這種遍歷整個數據庫的命令是很是耗 CPU 的,可能會致使 redis 性能降低,不作推薦使用。

最後還有一個簡單的命令就是 exists,它用於判斷給定的 key 是否存在,返回 0 說明不存在,返回 1 說明存在。

2、過時鍵

有的時候咱們但願給某些鍵一個過時時間,即但願它存活一段時間就失效,咱們 redis 爲咱們提供了這樣的機制。

一、expire

expire 用於設定某個鍵的過時時間,單位是秒,基本語法格式以下:

expire [key] [time]
複製代碼

image

能夠看到,五秒後 redis 爲咱們刪除了鍵 hello。與之對應的有一個命令 pexpire,他會將咱們傳入的 time 參數解析爲毫秒,例如 「pexpire hello 5」會將鍵經過五毫秒以後刪除。

二、expireat

expireat 用於設定某個鍵在某個具體 Unix 時間戳過時,單位秒,基本語法以下:

expireat [key] [time]
複製代碼

image

過時鍵會在咱們指定 Unix 時間戳別刪除。固然它也有一個對應毫秒單位的命令,pexpireat ,他會解析命令參數時間戳爲毫秒,也就是你須要傳入的時間戳再也不是秒單位的,而是毫秒單位的時間戳。

三、ttl 和 pttl

這兩個命令用於查看某個過時鍵還剩餘多少時間,基本語法格式以下:

ttl/pttl [key]
複製代碼

image

ttl 命令輸出的單位是秒,pttl 輸出的單位是毫秒,僅此區別。

四、persist

persist 用於移除某個過時鍵的過時時間,也就是讓這個鍵成爲永久有效鍵。基本語法格式以下:

persist [key]
複製代碼

image

以上就是 redis 中過時鍵相關的命令,以前也說過,redisDb 數據結構中有一個 expires 字典,它存儲的就是庫中全部過時鍵以及他們生存截止時間。

那麼,你可能會好奇了,redis 只記錄了某個過時鍵的截止有效時間,那麼何時刪除這些過時鍵呢?

3、過時鍵刪除策略

由於 redis 經過 expires 字典記錄全部的過時鍵以及他們的過時時間(一個 Unix時間戳),那麼咱們只須要比對當前系統時間戳 Unix 是否大於鍵的過時時間戳便可判斷鍵是否過時。

咱們直接介紹 redis 使用的兩種刪除策略,按期刪除和惰性刪除。

  1. 按期刪除:redis 每間隔一段時間進行一次小規模,有限時長的刪除過時鍵操做。
  2. 惰性刪除:redis 每次讀取某個鍵的時候,會先判斷這個鍵是否過時,若是過時,執行刪除操做。

這兩個策略,每個都有缺點,按期刪除須要每間隔一段時間觸發一次刪除,因此須要用戶對系統的業務量、請求峯谷點有熟悉的的瞭解,才能配置合適的頻率,不然過於高頻會平白增長 CPU 壓力,過於低頻會致使內存中過多無用內存佔用,下降系統性能。

而惰性刪除缺點很是直接,若是某些鍵過時了,且程序永遠不會訪問這些鍵,那麼 redis 就永遠不會釋放這些鍵佔用的內存,進而致使內存泄漏。

redis 中同時使用了這兩種刪除策略,一方面,每次讀取鍵的時候會調用方法 db.c/expireIfNeeded 判斷當前鍵是否過時,若是過時則刪除並返回 nil。另外一方面,redis 中有一個按期的時間事件函數,server.c/serverCron,每次執行都會收集與更新一些與服務器狀態相關的信息,好比更新服務器時間、計算對象空轉時長,管理客戶端鏈接資源的釋放等等。

其中也會執行一個 expire.c/activeExpireCycle 函數,默認配置了一千微妙內返回,activeExpireCycle 會在時間內選定數據庫,隨機的處理這些過時鍵,並給予刪除。

因此,其實上 redis 經過這兩種策略的結合,按期刪除保證不存在某些過時鍵永遠得不到刪除以進而引起內存泄漏,惰性刪除使得 redis 不用集中大量時間處理這些過時鍵以引發 CPU 負載過大。

下一節,咱們講 redis 如何作持久化存儲,畢竟數據放在內存,一旦服務器宕機、斷點,全部數據都會丟失,因此咱們也須要將數據備份磁盤。下節見~


關注公衆不迷路,一個愛分享的程序員。 公衆號回覆「1024」加做者微信一塊兒探討學習! 每篇文章用到的全部案例代碼素材都會上傳我我的 github github.com/SingleYam/o… 歡迎來踩!

YangAM 公衆號
相關文章
相關標籤/搜索