Redis官網(wǎng)對(duì)Redis的定義是:“Redis is an open source, BSD licensed, advanced key-value cache and store”,可以看出,Redis是一種鍵值系統(tǒng),可以用來(lái)緩存或存儲(chǔ)數(shù)據(jù)。Redis是“Remote Dictionary Server”(遠(yuǎn)程字典服務(wù))的縮寫,提供了字符串(string),列表(list),哈希(hash),集合(set)和有序集合(sorted set)等5種數(shù)據(jù)結(jié)構(gòu),這些數(shù)據(jù)結(jié)構(gòu)使它成為一種便于使用的鍵值系統(tǒng)。
作為Redis提供的最簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu),字符串示意圖及其常用命令如下圖所示:
圖1
可見(jiàn),Redis字符串類型實(shí)際上類似于C++中的map,一個(gè)鍵對(duì)應(yīng)一個(gè)值。列表類型則是一種相對(duì)高級(jí)的數(shù)據(jù)結(jié)構(gòu),其示意圖和常用命令如下圖所示:
圖2
列表實(shí)際上由一個(gè)雙向鏈表實(shí)現(xiàn),所以在列表兩端插入或刪除數(shù)據(jù)效率極高,可以用于實(shí)現(xiàn)類似于微博、人人網(wǎng)上的“新鮮事”功能。 Redis提供的一個(gè)更有趣的結(jié)構(gòu)稱為哈希,其示意圖和常用命令如下圖所示:
圖3
一個(gè)哈希實(shí)際上是一組鍵值對(duì)的集合,哈希本身的鍵是“父鍵”,哈希中包含的若干字段是“子鍵”,每個(gè)“子鍵”都有相應(yīng)的值。“子鍵”之間并沒(méi)有一定的聯(lián)系,但是它們共同組成了一個(gè)完整的哈希結(jié)構(gòu)。我們可以把一個(gè)哈希看做關(guān)系數(shù)據(jù)庫(kù)中的一行,哈希的每個(gè)子鍵對(duì)應(yīng)行的一個(gè)字段。因此,當(dāng)把關(guān)系數(shù)據(jù)庫(kù)中的數(shù)據(jù)緩存至Redis時(shí),使用哈希結(jié)構(gòu)可能會(huì)帶來(lái)方便。需要注意的是,哈希結(jié)構(gòu)內(nèi)部的子鍵之間是沒(méi)有順序關(guān)系的。Redis提供的另一個(gè)無(wú)順序關(guān)系的結(jié)構(gòu)是集合,其示意圖和常用命令如下圖所示:
圖4
集合中的數(shù)據(jù)滿足唯一性和無(wú)序性。集合在Redis內(nèi)部是用哈希表實(shí)現(xiàn)的,所以插入和刪除操作的時(shí)間復(fù)雜度均為O(1)。Redis為集合提供了求交并差等運(yùn)算命令,使用起來(lái)非常方便。與集合密切相關(guān)的另一個(gè)數(shù)據(jù)結(jié)構(gòu)是有序集合,其示意圖和常用命令如下圖所示:
圖5
有序集合與集合的最大差異在于有序集合中的每個(gè)數(shù)據(jù)都有一個(gè)對(duì)應(yīng)的分?jǐn)?shù),集合中的元素就是按照這些分?jǐn)?shù)進(jìn)行排序的。從結(jié)構(gòu)功能和使用方法上來(lái)看,有序集合可能是Redis提供的5種數(shù)據(jù)結(jié)構(gòu)中最高級(jí)的一種。
Redis是一種內(nèi)存數(shù)據(jù)庫(kù),這使其在數(shù)據(jù)存取效率方面表現(xiàn)突出。由于內(nèi)存中的數(shù)據(jù)時(shí)刻面臨丟失的危險(xiǎn),Redis提供了兩種持久化機(jī)制,及時(shí)將內(nèi)存中的數(shù)據(jù)寫入硬盤。第一種機(jī)制為RDB,利用存儲(chǔ)快照的方式把內(nèi)存數(shù)據(jù)定期寫入硬盤;第二種機(jī)制為AOF,利用寫日志的方式,每執(zhí)行一條更改Redis數(shù)據(jù)的命令,就在日志里附加上該命令并保存在硬盤上。Redis默認(rèn)開(kāi)啟RDB模式,關(guān)閉AOF模式,這是因?yàn)锳OF更加耗時(shí)。但是,如果對(duì)數(shù)據(jù)安全要求極高,無(wú)法承擔(dān)任何數(shù)據(jù)丟失的后果,AOF模式就變成了持久化的首選。
當(dāng)然,即使Redis具備持久化機(jī)制,但是一旦本地硬盤損壞,數(shù)據(jù)丟失依然在所難免。所以,Redis又提供了復(fù)制功能,作用是將一個(gè)主數(shù)據(jù)庫(kù)(master)的數(shù)據(jù)自動(dòng)同步到多個(gè)從數(shù)據(jù)庫(kù)(slave),從而盡可能防止數(shù)據(jù)丟失。Redis主從機(jī)制可以簡(jiǎn)單描述為:從數(shù)據(jù)庫(kù)啟動(dòng)后,先向主數(shù)據(jù)庫(kù)發(fā)送SYNC命令;主數(shù)據(jù)庫(kù)接到SYNC命令后就開(kāi)始保存快照,在此期間,所有發(fā)給主數(shù)據(jù)庫(kù)的命令都被緩存起來(lái);快照保存完成后,主數(shù)據(jù)庫(kù)把快照和緩存的命令一起發(fā)給從數(shù)據(jù)庫(kù);從數(shù)據(jù)庫(kù)保存主數(shù)據(jù)庫(kù)發(fā)來(lái)的快照文件,并依次執(zhí)行主數(shù)據(jù)庫(kù)發(fā)來(lái)的緩存命令。在同步過(guò)程中,從數(shù)據(jù)庫(kù)不會(huì)阻塞,它默認(rèn)使用同步之前的數(shù)據(jù)繼續(xù)響應(yīng)客戶端發(fā)來(lái)的命令。
事務(wù)是Redis提供的特性之一。首先利用MULTI命令通知Redis,接下來(lái)的若干命令屬于同一事務(wù);然后輸入若干命令,這些命令都被放入命令隊(duì)列而不會(huì)被立即執(zhí)行;最后,利用EXEC命令通知Redis,屬于同一事務(wù)的所有命令均已輸入完成,現(xiàn)在開(kāi)始執(zhí)行該事物。屬于同一個(gè)事務(wù)的所有有效命令或者全部被執(zhí)行,或者全部不執(zhí)行,且在執(zhí)行過(guò)程中不會(huì)插入其他命令。管道(pipeline)是Redis提供的另一個(gè)特性。該特性使Redis能夠一次性接收多個(gè)命令,執(zhí)行之后再一次性返回結(jié)果。這樣能夠減少客戶端與Redis服務(wù)器的通信次數(shù),從而降低往返時(shí)延。
除事務(wù)和管道以外,Redis還提供了很多其他特性,如設(shè)置鍵的過(guò)期時(shí)間,利用BLPOP/BRPOP命令實(shí)現(xiàn)優(yōu)先級(jí)隊(duì)列,利用PUBLISH/SUBSCRIBE命令實(shí)現(xiàn)消息訂閱和發(fā)布等,這里不再贅述。
Redis由ANSI C寫成,能夠運(yùn)行在包括Linux和OS X在內(nèi)的大部分POSIX系統(tǒng)上,官方推薦的操作系統(tǒng)為L(zhǎng)inux。Redis沒(méi)有官方的Windows版本,但是微軟移植并維護(hù)了一個(gè)能夠運(yùn)行在Windows上的Redis并放在github上(https://github.com/MSOpenTech/redis)。
Redis的編程接口被稱為客戶端(clients),絕大部分主流編程語(yǔ)言都有官方推薦的客戶端。下圖中,具有Redis官方推薦客戶端的語(yǔ)言標(biāo)為綠色,沒(méi)有官方推薦客戶端的標(biāo)為藍(lán)色:
圖6
由于Redis沒(méi)有官方推薦的C++客戶端,因此可以使用C客戶端予以代替。官方推薦的C客戶端是hiredis,可以從github上找到(https://github.com/redis/hiredis)。
作為一款功能強(qiáng)大,效率極高的NoSQL數(shù)據(jù)庫(kù),Redis已被包括新浪微博,知乎,Stackoverflow,暴雪和Flickr在內(nèi)的多家公司成功用于實(shí)戰(zhàn)。
注:圖1-5均來(lái)自《Redis in Action》,Josiah L.Carlson, Manning Publications, 2013
參考文獻(xiàn):
1. 李子驊,Redis入門指南,人民郵電出版社,2013年5月第1版
2.Josiah L.Carlson, Redis in Action, Manning Publications, 2013
3. Redis官方網(wǎng)站http://www.redis.io