Redis 介绍
1、簡(jiǎn)介
Redis 是一款開(kāi)源的,基于 BSD 許可的,高級(jí)鍵值 (key-value) 緩存 (cache) 和存儲(chǔ) (store) 系統(tǒng)。由于 Redis 的鍵包括 string,hash,list,set,sorted set,bitmap 和 hyperloglog,所以常常被稱為數(shù)據(jù)結(jié)構(gòu)服務(wù)器。
為了滿足高性能,Redis 采用內(nèi)存 (in-memory) 數(shù)據(jù)集 (dataset)。根據(jù)你的使用場(chǎng)景,你可以通過(guò)每隔一段時(shí)間轉(zhuǎn)儲(chǔ)數(shù)據(jù)集到磁盤(pán),或者追加每條命令到日志來(lái)持久化。持久化也可以被禁用,如果你只是需要一個(gè)功能豐富,網(wǎng)絡(luò)化的內(nèi)存緩存。
Redis 還支持主從異步復(fù)制,非常快的非阻塞初次同步、網(wǎng)絡(luò)斷開(kāi)時(shí)自動(dòng)重連局部重同步。
Redis特點(diǎn):1、Redis支持?jǐn)?shù)據(jù)的持久化,可以將內(nèi)存中的數(shù)據(jù)保持在磁盤(pán)中,重啟的時(shí)候可以再次加載進(jìn)行使用。
2、Redis不僅僅支持簡(jiǎn)單的key-value類型的數(shù)據(jù),同時(shí)還提供list,set,sorted set,hash等數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)。
3、Redis支持?jǐn)?shù)據(jù)的備份,即master-slave模式的數(shù)據(jù)備份。
Redis優(yōu)勢(shì):
1、性能極高 – Redis能讀的速度是110000次/s,寫(xiě)的速度是81000次/s 。
2、豐富的數(shù)據(jù)類型 – Redis支持二進(jìn)制案例的 String, List, Hash, Set 及 Sorted Set 數(shù)據(jù)類型操作。
3、原子 – Redis的所有操作都是原子性的,同時(shí)Redis還支持對(duì)幾個(gè)操作全并后的原子性執(zhí)行。
4、豐富的特性 – Redis還支持 publish/subscribe, 通知, key 過(guò)期等等特性 2、多數(shù)據(jù)類型
- String
- List
- Set
- Hash
- Sorted Set
3、持久化
redis支持兩種持久化方式,一種是 RDB(快照)也是默認(rèn)方式,另一種是Append-only file(aof)的方式。
3.1 快照RDB
快照是默認(rèn)的持久化方式。這種方式是就是將內(nèi)存中數(shù)據(jù)以快照的方式寫(xiě)入到二進(jìn)制文件中,默認(rèn)的文件名為dump.rdb。可以通過(guò)配置設(shè)置自動(dòng)做快照持久化的方式。我們可以配置redis在n秒內(nèi)如果超過(guò)m個(gè)key被修改就自動(dòng)做快照。也可以命令行的方式讓redis進(jìn)行snapshotting。
快照生成過(guò)程大致如下:redis調(diào)用fork出父子進(jìn)程,父進(jìn)程繼續(xù)處理client請(qǐng)求,子進(jìn)程負(fù)責(zé)將內(nèi)存內(nèi)容寫(xiě)入到臨時(shí)文件。由于os的寫(xiě)時(shí)復(fù)制機(jī)制(copy on write)父子進(jìn)程會(huì)共享相同的物理頁(yè)面,當(dāng)父進(jìn)程處理寫(xiě)請(qǐng)求時(shí)os會(huì)為父進(jìn)程要修改的頁(yè)面創(chuàng)建副本,而不是寫(xiě)共享的頁(yè)面。所以子進(jìn)程的地址空間內(nèi)的數(shù)據(jù)是fork時(shí)刻整個(gè)數(shù)據(jù)庫(kù)的一個(gè)快照;當(dāng)子進(jìn)程將快照寫(xiě)入臨時(shí)文件完畢后,用臨時(shí)文件替換原來(lái)的快照文件,然后子進(jìn)程退出。 快照(snapshotting)不足之處在于兩次快照操作之間是有時(shí)間間隔的,一旦數(shù)據(jù)庫(kù)出現(xiàn)問(wèn)題,那么快照文件中保存的數(shù)據(jù)并不是全新的,從上次快照文件生成到Redis停機(jī)這段時(shí)間的數(shù)據(jù)全部丟掉了。 3.2 aof方式 比上面所說(shuō)的快照方式有更好的持久化性,是由于在使用aof持久化方式時(shí),redis會(huì)將每一個(gè)收到的寫(xiě)命令都通過(guò)write函數(shù)追加到文件中(默認(rèn)是 appendonly.aof)。當(dāng)redis重啟時(shí)會(huì)通過(guò)重新執(zhí)行文件中保存的寫(xiě)命令來(lái)在內(nèi)存中重建整個(gè)數(shù)據(jù)庫(kù)的內(nèi)容。 可以通過(guò)配置文件告訴redis我們想要通過(guò)fsync函數(shù)強(qiáng)制os寫(xiě)入到磁盤(pán)的時(shí)機(jī)。有三種方式如下(默認(rèn)是:每秒fsync一次): 1、appendonly yes //啟用aof持久化方式
2、appendfsync always //每次收到寫(xiě)命令就立即強(qiáng)制寫(xiě)入磁盤(pán),最慢的,但是保證完全的持久化,不推薦使用
3、appendfsync everysec //每秒鐘強(qiáng)制寫(xiě)入磁盤(pán)一次,在性能和持久化方面做了很好的折中,推薦
4、appendfsync no //完全依賴os,性能最好,持久化沒(méi)保證
aof方式的持久化也還是有可能會(huì)丟失部分修改,因?yàn)閛s會(huì)在內(nèi)核中緩存 write做的修改,所以可能不是立即寫(xiě)到磁盤(pán)上。另外aof 的方式可能會(huì)導(dǎo)致持久化文件會(huì)變的越來(lái)越大。為了壓縮aof的持久化文件。redis提供了bgrewriteaof命令。收到此命令redis將使用與快照類似的方式將內(nèi)存中的數(shù)據(jù)以命令的方式保存到臨時(shí)文件中,最后替換原來(lái)的文件。 bgrewriteaof命令執(zhí)行過(guò)程如下: redis調(diào)用fork出父子兩個(gè)進(jìn)程,子進(jìn)程根據(jù)內(nèi)存中的數(shù)據(jù)庫(kù)快照,往臨時(shí)文件中寫(xiě)入重建數(shù)據(jù)庫(kù)狀態(tài)的命令;
父進(jìn)程繼續(xù)處理client請(qǐng)求,除了把寫(xiě)命令寫(xiě)入到原來(lái)的aof文件中。同時(shí)把收到的寫(xiě)命令緩存起來(lái)。這樣就能保證如果子進(jìn)程重寫(xiě)失敗的話并不會(huì)出問(wèn)題;
當(dāng)子進(jìn)程把快照內(nèi)容寫(xiě)入以命令方式寫(xiě)到臨時(shí)文件中后,子進(jìn)程發(fā)信號(hào)通知父進(jìn)程。然后父進(jìn)程把緩存的寫(xiě)命令也寫(xiě)入到臨時(shí)文件;
現(xiàn)在父進(jìn)程可以使用臨時(shí)文件替換老的aof文件,并重命名,后面收到的寫(xiě)命令也開(kāi)始往新的aof文件中追加。
4、內(nèi)存管理
4.1?Redis對(duì)象
所有的Redis對(duì)象都被封裝在RedisObject這個(gè)結(jié)構(gòu)體當(dāng)中,如下:
typedef struct redisObject {unsigned type, // 4字節(jié),數(shù)據(jù)類型(String,List,Set,Hash,Sorted Set)unsigned encoding, // 4字節(jié),編碼方式unsigned lru, // 24字節(jié)int refcount, // 對(duì)象引用計(jì)數(shù)void *ptr // 數(shù)據(jù)具體存儲(chǔ)的指向 } robj;Redis 內(nèi)部使用一個(gè) redisObject 對(duì)象來(lái)表示所有的 key 和 value,type 代表一個(gè) value 對(duì)象具體是何種數(shù)據(jù)類型,encoding 是不同數(shù)據(jù)類型在 redis 內(nèi)部的存儲(chǔ)方式,比如:type=string 代表 value 存儲(chǔ)的是一個(gè)普通字符串,那么對(duì)應(yīng)的 encoding 可以是 raw 或者是 int,如果是 int 則代表實(shí)際 redis 內(nèi)部是按數(shù)值型類存儲(chǔ)和表示這個(gè)字符串的。
4.2 內(nèi)存淘汰策略
Redis提供了下面幾種淘汰策略供用戶選擇,其中默認(rèn)的策略為noeviction策略:
- noeviction:當(dāng)內(nèi)存使用達(dá)到閾值的時(shí)候,所有引起申請(qǐng)內(nèi)存的命令會(huì)報(bào)錯(cuò)。
- allkeys-lru:在主鍵空間中,優(yōu)先移除最近未使用的key。
- volatile-lru:在設(shè)置了過(guò)期時(shí)間的鍵空間中,優(yōu)先移除最近未使用的key。
- allkeys-random:在主鍵空間中,隨機(jī)移除某個(gè)key。
- volatile-random:在設(shè)置了過(guò)期時(shí)間的鍵空間中,隨機(jī)移除某個(gè)key。
- volatile-ttl:在設(shè)置了過(guò)期時(shí)間的鍵空間中,具有更早過(guò)期時(shí)間的key優(yōu)先移除
5、主從同步
Redis的主從復(fù)制功能非常強(qiáng)大,一個(gè)master可以擁有多個(gè)slave,而一個(gè)slave又可以擁有多個(gè)slave,如此下去,形成了強(qiáng)大的多級(jí)服務(wù)器集群架構(gòu)。
Redis主從復(fù)制的一些特點(diǎn):
1.master可以有多個(gè)slave
2.除了多個(gè)slave連到相同的master外,slave也可以連接其他slave形成圖狀結(jié)構(gòu)
3.主從復(fù)制不會(huì)阻塞master。也就是說(shuō)當(dāng)一個(gè)或多個(gè)slave與master進(jìn)行初次同步數(shù)據(jù)時(shí),master可以繼續(xù)處理client發(fā)來(lái)的請(qǐng)求。相反slave在初次同步數(shù)據(jù)時(shí)則會(huì)阻塞不能處理client的請(qǐng)求。
4.主從復(fù)制可以用來(lái)提高系統(tǒng)的可伸縮性,我們可以用多個(gè)slave 專門(mén)用于client的讀請(qǐng)求,比如sort操作可以使用slave來(lái)處理。也可以用來(lái)做簡(jiǎn)單的數(shù)據(jù)冗余
5.可以在master禁用數(shù)據(jù)持久化,只需要注釋掉master 配置文件中的所有save配置,然后只在slave上配置數(shù)據(jù)持久化。
Redis主從復(fù)制的過(guò)程:
當(dāng)設(shè)置好slave服務(wù)器后,slave會(huì)建立和master的連接,然后發(fā)送sync命令。無(wú)論是第一次同步建立的連接還是連接斷開(kāi)后的重新連接,master都會(huì)啟動(dòng)一個(gè)后臺(tái)進(jìn)程,將數(shù)據(jù)庫(kù)快照保存到文件中,同時(shí)master主進(jìn)程會(huì)開(kāi)始收集新的寫(xiě)命令并緩存起來(lái)。后臺(tái)進(jìn)程完成寫(xiě)文件后,master就發(fā)送文件給slave,slave將文件保存到磁盤(pán)上,然后加載到內(nèi)存恢復(fù)數(shù)據(jù)庫(kù)快照到slave上。接著master就會(huì)把緩存的命令轉(zhuǎn)發(fā)給slave。而且后續(xù)master收到的寫(xiě)命令都會(huì)通過(guò)開(kāi)始建立的連接發(fā)送給slave。從master到slave的同步數(shù)據(jù)的命令和從 client發(fā)送的命令使用相同的協(xié)議格式。當(dāng)master和slave的連接斷開(kāi)時(shí)slave可以自動(dòng)重新建立連接。如果master同時(shí)收到多 slave發(fā)來(lái)的同步連接命令,只會(huì)使用啟動(dòng)一個(gè)進(jìn)程來(lái)寫(xiě)數(shù)據(jù)庫(kù)鏡像,然后發(fā)送給所有slave。
redis的主從復(fù)制策略是通過(guò)其持久化的rdb文件來(lái)實(shí)現(xiàn)的,其過(guò)程是先dump出rdb文件,將rdb文件全量傳輸給slave,然后再將dump后的操作實(shí)時(shí)同步到slave中。
1、Slave端在配置文件中添加了slaveof指令,于是Slave啟動(dòng)時(shí)讀取配置文件,初始狀態(tài)為REDIS_REPL_CONNECT;
2、Slave端在定時(shí)任務(wù)serverCron中連接Master,發(fā)送sync命令,然后阻塞等待master發(fā)送回其內(nèi)存快照文件(最新版的Redis已經(jīng)不需要讓Slave阻塞);
3、Master端收到sync命令簡(jiǎn)單判斷是否有正在進(jìn)行的內(nèi)存快照子進(jìn)程,沒(méi)有則立即開(kāi)始內(nèi)存快照,有則等待其結(jié)束,當(dāng)快照完成后會(huì)將該文件發(fā)送給Slave端;
4、Slave端接收Master發(fā)來(lái)的內(nèi)存快照文件,保存到本地,待接收完成后,清空內(nèi)存表,重新讀取Master發(fā)來(lái)的內(nèi)存快照文件,重建整個(gè)內(nèi)存表數(shù)據(jù)結(jié)構(gòu),并最終狀態(tài)置位為 REDIS_REPL_CONNECTED狀態(tài),Slave狀態(tài)機(jī)流轉(zhuǎn)完成;
5、Master端在發(fā)送快照文件過(guò)程中,接收的任何會(huì)改變數(shù)據(jù)集的命令都會(huì)暫時(shí)先保存在Slave網(wǎng)絡(luò)連接的發(fā)送緩存隊(duì)列里(list數(shù)據(jù)結(jié)構(gòu)),待快照完成后,依次發(fā)給Slave,之后收到的命令相同處理,并將狀態(tài)置位為 REDIS_REPL_ONLINE。
6、事物機(jī)制:
Redis事務(wù)通常會(huì)使用MULTI,EXEC,WATCH等命令來(lái)完成,redis的事務(wù)不支持回滾,事務(wù)執(zhí)行時(shí)會(huì)阻塞其它客戶端的請(qǐng)求執(zhí)行。Redis事務(wù)從開(kāi)始到結(jié)束通常會(huì)通過(guò)三個(gè)階段:1、事務(wù)開(kāi)始 2、命令入隊(duì) 3、命令執(zhí)行。 與實(shí)務(wù)相關(guān)的狀態(tài)標(biāo)識(shí)flag,用于標(biāo)識(shí)當(dāng)前客戶端的事物狀態(tài),如下: #define REDIS_MULTI (1<<3) #define REDIS_DIRTY_EXEC (1<<12) #define REDIS_DIRTY_CAS (1<<5)
7、應(yīng)用場(chǎng)景
1、session會(huì)話共享緩存
2、數(shù)據(jù)緩存
3、隊(duì)列:1)Redis自帶的PUB/SUB機(jī)制,即發(fā)布-訂閱模式。2)Redis的PUSH/POP機(jī)制,利用的Redis的列表(lists)數(shù)據(jù)結(jié)構(gòu)。比較好的使用模式是,生產(chǎn)者lpush消息,消費(fèi)者brpop消息,并設(shè)定超時(shí)時(shí)間,可以減少redis的壓力。
?
Redis 命令參考Doc
轉(zhuǎn)載于:https://www.cnblogs.com/kingsonfu/p/10407413.html
總結(jié)
- 上一篇: 公司电脑用域账号访问团队文件夹
- 下一篇: 自动存款机转账多久到账