1. 程式人生 > >Redis 中的資料庫

Redis 中的資料庫

前面我們花了很多的時間介紹了 redis 中基本的資料結構,及其內部的實現情況,這些都是非常基礎的東西,可能不經意間你就會用到他們,希望你花點時間瞭解一下。

接下來,我們將走近 redis 資料庫,學習各種操作 redis 的命令,並介紹它的一些實現策略以及叢集配置等等內容。

一、redis 中的資料庫

server.h/redisServer 結構中有一個欄位,db 欄位:

redisDb *db;

db 被定義成一個 redisDb 陣列,其中 redisDb 的定義如下:

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 時間戳。

blocking_keys 儲存了被阻塞的鍵集合,ready_keys 儲存的是可以解除阻塞的鍵集合,watched_keys 儲存的是正在被 watch 命令監控的鍵的集合,id 記錄的是當前資料庫的一個編號,avg_ttl 收集了所有鍵剩餘存活時間的一個平均值。這一部分的幾個欄位的值這裡不做詳細的解釋,沒有基本的知識儲備,不容易理解的,後面我們還會遇到的。

server.h/redisServer 結構中還有一個欄位,dbnum 欄位:

int dbnum;  /* Total number of configured DBs */

與此同時,redis.conf 配置檔案中,預設有這麼一項配置。

所以,我們啟動 redis-server 的時候,會根據配置檔案中給定的配置預設建立 16 個數據庫。

1、select 命令

select 命令用於我們切換資料庫,例如:

預設連線上 redis-server 的客戶端使用 0 號資料庫,鑑於 redis 並沒有提供給客戶端查詢當前使用資料庫編號的命令,所以建議執行 redis 命令之前,尤其是修改、新增命令,先執行下切換資料庫的命令。

2、set 命令

set 命令其實無需過多介紹,它向資料庫中新增一個鍵值對,大部分情況下,鍵會是一個字串物件,而值可取我們 redis 的五大物件之一。

因為 redisDb 底層是字典結構,鍵不允許重複,故而 set 命令同樣適用於更新操作。

3、del 命令

del 命令用於刪除資料庫中一個鍵值對,標準語法如下:

del [KEY]

例如:

4、get 命令

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

get [KEY]

具體事例就不再演示了,get 命令對應於 set 命令,只能獲取由 set 命令新增的字串物件鍵值對,而例如一些集合物件,或列表物件需要用類似於 sadd、zadd 等命令進行資料庫的新增,自然 get 命令也是無法得到這些鍵值對物件值的。

5、其他命令

第一個我們介紹 dbsize 命令,它返回當前資料庫有多少鍵值對,基本語法格式如下:

dbsize

第二個我們要介紹的是 flushdb 命令,它用於清空當前資料庫,這是一個非常危險的命令,謹慎使用,基本語法格式如下:

flushdb

第三個我們要介紹一個 kyes 命令,它會返回資料庫中所有符合匹配規則的鍵的集合,這個規則起初我以為是正則表示式,幾番操作後發現匹配不上,查閱資料貌似不是正則,並且僅有以下三種規則:

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

正則表示式中的問號,用於匹配前一個字元出現零次或一次,即要麼出現要麼不出現,而我們這裡的 keys 模式,問號具有不同的意義。

不過 keys 命令這種遍歷整個資料庫的命令是非常耗 CPU 的,可能會導致 redis 效能下降,不做推薦使用。

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

二、過期鍵

有的時候我們希望給某些鍵一個過期時間,即希望它存活一段時間就失效,我們 redis 為我們提供了這樣的機制。

1、expire

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

expire [key] [time]

可以看到,五秒後 redis 為我們刪除了鍵 hello。與之對應的有一個命令 pexpire,他會將我們傳入的 time 引數解析為毫秒,例如 「pexpire hello 5」會將鍵通過五毫秒之後刪除。

2、expireat

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

expireat [key] [time]

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

3、ttl 和 pttl

這兩個命令用於檢視某個過期鍵還剩餘多少時間,基本語法格式如下:

ttl/pttl [key]

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

4、persist

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

persist [key]

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

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

三、過期鍵刪除策略

因為 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

https://github.com/SingleYam/overview_java

歡迎來踩!

相關推薦

Redis單機資料庫的實現

1. 記憶體操作層 zmalloc 系介面 redis為了優化記憶體操作, 封裝了一層記憶體操作介面. 預設情況下, 其底層實現就是最簡樸的libc中的malloc系列介面. 如果有定製化需求, 可以通過配置方式, 將底層記憶體操作的實現更換為tcmalloc或jemalloc庫. redis封裝的這一層介面

redis快取的資料與資料庫資料一致性的方案

方式1:資料庫儲存資料,redis不persist redis啟動後,從資料庫載入資料 不要求強一致實時性的讀請求,都由redis處理 要求強一致實時性的讀請求,由資料庫處理 寫請求有2種處理方式,由資料庫處理 - 應用先寫道資料庫,然後更新redis - 應用先寫道資料庫

資料庫資料放到redis並保持資料一致性方案

1、查詢時先查詢快取(redis),如果查詢不到,查詢資料庫,並將會員唯一標識(會員編號),放到redis佇列中(list) 2、啟動一個job從redis佇列中讀取會員唯一標識,並判斷會員編號作為key是否存在於redis中,如果存在,計數器減一,否則直接查詢會員資訊,放

redis快取的資料與資料庫資料一致性的方案(好)

方式1:資料庫儲存資料,redis不persistredis啟動後,從資料庫載入資料不要求強一致實時性的讀請求,都由redis處理要求強一致實時性的讀請求,由資料庫處理寫請求有2種處理方式,由資料庫處理- 應用先寫道資料庫,然後更新redis- 應用先寫道資料庫,然後其它da

$Django 路飛之redis記憶體資料庫安裝,python使用,與Memcached,mongodb的區別

一 redis記憶體資料庫安裝   1.官網下載   2.啟動服務端       redis-server 命令啟動redis服務。         啟動redis服務還有個更方便的方法是把redis加入到Windows服務。         使用cmd進到redis目

Redis的批量刪除資料庫的Key

./redis-cli keys "*" | xargs ./redis-cli del   批量刪除Key Redis 中有刪除單個 Key 的指令 DEL,但好像沒有批量刪除 Key 的指令,不過我們可以藉助 Linux 的 xargs 指令來完成這個動作 1

Redis 資料庫

前面我們花了很多的時間介紹了 redis 中基本的資料結構,及其內部的實現情況,這些都是非常基礎的東西,可能不經意間你就會用到他們,希望你花點時間瞭解一下。 接下來,我們將走近 redis 資料庫,學習各種操作 redis 的命令,並介紹它的一些實現策略以及叢集配置等等內容。 一、redis 中的資料庫 se

redis關閉rdb跟aof

server 數據庫 二進制 記錄 當往redis中導入數據時,有時會出現redis server went away的情況,出現這一問題的原因有:導入的數據量太大,而內存不夠(即內存1G,但數據有2G)。此時的redis服務需要重啟。可能是同一時間導入的數據太多,導致數據持久化的操作出問題,

redis 的配置文件redis.conf 相關配置信息

redis.conf redis配置文件 知識點有點分散,一點一點記錄把:(嘿,這需要極大耐性呢)1、需要註意:當相關配置中的內存大小需要指定時,通過可能指定的格式為 1k 、 5GB、4M等,大小寫可以不區分。2、Redis 默認不是守護進程的方式進行,可以通過該配置項修改,使用 yes 啟用守護進

如何提取Redis的大KEY

ash xxx obj zset 隨著 pre tin 功能 平滑 工作中,經常有些Redis實例使用不恰當,或者對業務預估不準確,或者key沒有及時進行處理等等原因,導致某些KEY相當大。 那麽大Key會帶來哪些問題呢? 如果是集群模式下,無法做到負載均衡,導致請求傾

Redis存入存儲的編碼方式不一致解決問題

rds import imp value res div rom 解決辦法 取出   在利用redis緩存的時候,存入的數據與取出的數據編碼方式不一致解決辦法。 from redis import StrictRedis #ecoding = ‘utf-8‘,默認解碼方式

Redis取得所有Key、過期時間配置與獲取、Key過期通知。

ive exceptio config lee var url multipl -c class string connection = "127.0.0.1:6379,password=xxxxx,connectRetry=5"; [TestM

redislist模擬案例-消息隊列

成功 inf use amp aos 數據 rep ces 是否 redis 數據類型:字符串string、list、set、zset、hash 主要的是list消息隊列 消息隊列的概念:先進先出 <?php//echo phpinfo();ini_set(‘disp

Redis在程序的應用

dtree tcollect base 條件 mil style mon ins print 1、導入redis的配置文件,因為要交給web容器管理,所以直接命名為ApplicationContext-redis.xml,具體配置如下:    <beans xmln

關於redisSDS簡單動態字符串

target fault per 預測 string com tab 分配 ews 1、SDS 定義 在C語言中,字符串是以’\0’字符結尾(NULL結束符)的字符數組來存儲的,通常表達為字符指針的形式(char *)。它不允許字節0出現在字符串中

redis不同value類型的存取操作方式

string類 array json數組字符串 div ont value conf cep ash public class CacheController {   public static void main(String[] args) throws Excep

redis與key相關的命令

nbsp 由於 src type 也不能 bsp type命令 mage string類 1、簡單描述 redis本質上是一個key-value db,value可以有多種類型(string、hash、set、sorted set、list等),本章節不講這些類型的命令,這

第三百五十八節,Python分布式爬蟲打造搜索引擎Scrapy精講—將bloomfilter(布隆過濾器)集成到scrapy-redis

分布式爬蟲 times 操作 加載 ger 目錄 需要 ini space 第三百五十八節,Python分布式爬蟲打造搜索引擎Scrapy精講—將bloomfilter(布隆過濾器)集成到scrapy-redis中,判斷URL是否重復 布隆過濾器(Bloom Filte

如何實現從 Redis 訂閱消息轉發到 WebSocket 客戶端

模式 func pen subscribe ssa ole ade 連接 回調函數 PHP 的redis擴展是阻塞式 IO ,使用訂閱/發布模式時,會導致整個進程進入阻塞。因此必須使用Swoole\Redis異步客戶端來實現。 實例代碼 1 $server = new

Redis中文內容顯示十六進制字符串處理

redis Redis的在使用的過程中有中文的內容都是以十六進制的形式存儲的,所以在使用redis-cli客戶端連接時如果是內容中有中文的部分都會以十六進制的形式顯示,因此查詢redis中的數據內容時就有點不太方便,其實在Unix系統下可以把查到的十六進制內容用echo中的“-e“參數用來轉換所查詢到的十