redis的持久化和緩存機(jī)制解讀
redis的持久化和緩存機(jī)制
說(shuō)道redis,我們可能都會(huì)知道了他是一個(gè)類似緩存的一個(gè)內(nèi)存數(shù)據(jù)庫(kù),我們從未感知到它的存在是因?yàn)樗芸?,為什么非常快,是因?yàn)樗陌l(fā)展到應(yīng)用很快,還有他的反應(yīng)速度也是非常快的。
以前文章我們講到了緩存以及非關(guān)系型數(shù)據(jù)庫(kù)的由來(lái),這篇我們來(lái)講講redis這種非關(guān)系型數(shù)據(jù)庫(kù)用在什么地方,以及他的特色——持久化是怎么實(shí)現(xiàn)的。
一、redis的適用環(huán)境
首先作為一個(gè)nosql的key—value組成的數(shù)據(jù)庫(kù),它們能存儲(chǔ)的數(shù)據(jù)結(jié)構(gòu)必須是簡(jiǎn)單的,因?yàn)橛嘘P(guān)系的數(shù)據(jù)即使存儲(chǔ)進(jìn)去之后查詢也是很困難的,并且對(duì)于海量的數(shù)據(jù)存儲(chǔ)還是關(guān)系型數(shù)據(jù)庫(kù)比較合適。
舉一個(gè)把一般數(shù)據(jù)庫(kù)數(shù)據(jù)存儲(chǔ)到key-value中的例子:
student | |||
學(xué)號(hào) | 姓名 | 年齡 | 班級(jí) |
001 | 小明 | 18 | 2 |
key | value |
student:001:姓名 | 小明 |
student:001:年齡 | 18 |
student:001:班級(jí) | 2 |
遵從規(guī)則為
key 表名:主鍵值:列名value 列值
如果加上表關(guān)系的話還要復(fù)雜好幾倍的。
那么什么樣的數(shù)據(jù)適合存儲(chǔ)在非關(guān)系型數(shù)據(jù)庫(kù)中的呢?
1、關(guān)系不是很密切的的數(shù)據(jù),比如用戶信息,班級(jí)信息,評(píng)論數(shù)量等等。
2、量比較大的數(shù)據(jù),如訪問(wèn)記錄等
3、訪問(wèn)比較頻繁的數(shù)據(jù),如用戶信息,訪問(wèn)數(shù)量,最新微博等
二、持久化
那么這么多,這么重要的數(shù)據(jù)都存儲(chǔ)在內(nèi)存中,如果突然斷電,豈不是很糟糕,于是就有了數(shù)據(jù)的持久化機(jī)制,這個(gè)其實(shí)就是把內(nèi)存中的數(shù)據(jù)存儲(chǔ)到硬盤中,方便數(shù)據(jù)的持續(xù)存在,也可以減少斷電造成的損失。
那么我們?cè)趺闯志没瘮?shù)據(jù)呢?多長(zhǎng)時(shí)間進(jìn)行一次持久化呢?
redis 支持兩種持久化方式,一種是 Snapshotting(快照)也是默認(rèn)方式,另一種是 Append-only file(縮寫(xiě) aof)的方式。下面分別介紹:
Snapshotting
快照是默認(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)做快照,下面是默認(rèn)的快照保存配置:
- save 900 1 #900 秒內(nèi)如果超過(guò) 1 個(gè) key 被修改,則發(fā)起快照保存
- save 300 10 #300 秒內(nèi)容如超過(guò) 10 個(gè) key 被修改,則發(fā)起快照保存
- save 60 10000
下面介紹詳細(xì)的快照保存過(guò)程:
1.redis 調(diào)用 fork,現(xiàn)在有了子進(jìn)程和父進(jìn)程。
2. 父進(jìn)程繼續(xù)處理 client 請(qǐng)求,子進(jìn)程負(fù)責(zé)將內(nèi)存內(nèi)容寫(xiě)入到臨時(shí)文件。由于 os 的實(shí)時(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è)快照。
3.當(dāng)子進(jìn)程將快照寫(xiě)入臨時(shí)文件完畢后,用臨時(shí)文件替換原來(lái)的快照文件,然后子進(jìn)程退出。client 也可以使用 save 或者 bgsave 命令通知 redis 做一次快照持久化。 save 操作是在主線程中保存快照的,由于 redis 是用一個(gè)主線程來(lái)處理所有 client 的請(qǐng)求,這種方式會(huì)阻塞所有client 請(qǐng)求。所以不推薦使用。另一點(diǎn)需要注意的是,每次快照持久化都是將內(nèi)存數(shù)據(jù)完整寫(xiě)入到磁盤一次,并不是增量的只同步變更數(shù)據(jù)。如果數(shù)據(jù)量大的話,而且寫(xiě)操作比較多,必然會(huì)引起大量的磁盤 io 操作,可能會(huì)嚴(yán)重影響性能。
AOF方式
由于快照方式是在一定間隔時(shí)間做一次的,所以如果 redis 意外 down 掉的話,就會(huì)丟失最后一次快照后的所有修改。如果應(yīng)用要求不能丟失任何修改的話,可以采用 aof 持久化方式。
下面介紹 Append-only file:aof 比快照方式有更好的持久化性,是由于在使用 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)容。
當(dāng)然由于 os 會(huì)在內(nèi)核中緩存 write 做的修改,所以可能不是立即寫(xiě)到磁盤上。這樣 aof 方式的持久化也還是有可能會(huì)丟失部分修改。不過(guò)我們可以通過(guò)配置文件告訴 redis 我們想要通過(guò) fsync 函數(shù)強(qiáng)制 os 寫(xiě)入到磁盤的時(shí)機(jī)。
有三種方式如下(默認(rèn)是:每秒 fsync 一次)
- appendonly yes //啟用 aof 持久化方式
- # appendfsync always //收到寫(xiě)命令就立即寫(xiě)入磁盤,最慢,但是保證完全的持久化
- appendfsync everysec //每秒鐘寫(xiě)入磁盤一次,在性能和持久化方面做了很好的折中
- # appendfsync no //完全依賴 os,性能最好,持久化沒(méi)保證
aof 的方式也同時(shí)帶來(lái)了另一個(gè)問(wèn)題。持久化文件會(huì)變的越來(lái)越大。
例如我們調(diào)用 incr test命令 100 次,文件中必須保存全部的 100 條命令,其實(shí)有 99 條都是多余的。
因?yàn)橐謴?fù)數(shù)據(jù)庫(kù)的狀態(tài)其實(shí)文件中保存一條 set test 100 就夠了。為了壓縮 aof 的持久化文件。
redis 提供了 bgrewriteaof 命令。收到此命令 redis 將使用與快照類似的方式將內(nèi)存中的數(shù)據(jù)以命令的方式保存到臨時(shí)文件中,最后替換原來(lái)的文件。
redis緩存和兩種持久化機(jī)制
redis的優(yōu)點(diǎn)第一個(gè)就是速度快它是由c語(yǔ)言實(shí)現(xiàn)的基于內(nèi)存讀寫(xiě)的效率特別高第二個(gè)優(yōu)點(diǎn)就是單線程模型所謂的單線程就是一個(gè)每個(gè)請(qǐng)求都會(huì)有一個(gè)新的線程來(lái)處理請(qǐng)求第三個(gè)優(yōu)點(diǎn)就是使用的是非阻塞 i/o(i/o流)
不會(huì)再網(wǎng)上浪費(fèi)時(shí)間第四個(gè)優(yōu)點(diǎn)就是支持多數(shù)據(jù)類型存儲(chǔ)
兩種持久化機(jī)制
rdb (Rrdis DataBase)默認(rèn)的持久化方案是某個(gè)時(shí)間內(nèi)的間隔執(zhí)行指定次數(shù)的寫(xiě)操作則會(huì)將內(nèi)存中的數(shù)據(jù)存入磁盤中 是以快照方式進(jìn)行備份緩存
rdb的優(yōu)點(diǎn):
1.適合大規(guī)模的數(shù)據(jù)恢復(fù)操作
2.業(yè)務(wù)操作對(duì)數(shù)據(jù)的完整行和一致性要求不高 那么Rdb是最好的選擇,
rdb的缺點(diǎn):
1.就是數(shù)據(jù)的不完整行和一致性不高,可能是在最后一次備份是宕機(jī),
2:備份時(shí)會(huì)占用內(nèi)存因?yàn)閞edis在備份的時(shí)候會(huì)獨(dú)立創(chuàng)建一個(gè)線程(此時(shí)的內(nèi)存中有兩份相同的數(shù)據(jù));
Aof:默認(rèn)不開(kāi)啟的持久化它的出現(xiàn)就是為了彌補(bǔ)RdB的不足(數(shù)據(jù)不一致)所以它采用的是日志的方式儲(chǔ)存
優(yōu)點(diǎn):數(shù)據(jù)的完整性和一致性更高
缺點(diǎn):因?yàn)锳OF記錄的內(nèi)容多,文件會(huì)越來(lái)越大,數(shù)據(jù)恢復(fù)也會(huì)越來(lái)越慢。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring+Redis+RabbitMQ開(kāi)發(fā)限流和秒殺項(xiàng)目功能
本項(xiàng)目將通過(guò)整合Springboot和Redis以及Lua腳本來(lái)實(shí)現(xiàn)限流和秒殺的效果,將通過(guò)RabbitMQ消息隊(duì)列來(lái)實(shí)現(xiàn)異步保存秒殺結(jié)果的效果,對(duì)Spring?Redis?RabbitMQ限流秒殺功能實(shí)現(xiàn)感興趣的朋友一起看看吧2022-02-02Redis集群增加節(jié)點(diǎn)與刪除節(jié)點(diǎn)的方法詳解
這篇文章主要給大家介紹了關(guān)于Redis集群增加節(jié)點(diǎn)與刪除節(jié)點(diǎn)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Redis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09解決redis-cli報(bào)錯(cuò)Could not connect to Redis&
這篇文章主要介紹了解決redis-cli報(bào)錯(cuò)Could not connect to Redis at 127.0.0.1:6379: Connection refused,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-04-04Redis模擬延時(shí)隊(duì)列實(shí)現(xiàn)日程提醒的方法
文章介紹了如何使用Redis實(shí)現(xiàn)一個(gè)簡(jiǎn)單的延時(shí)任務(wù)隊(duì)列,通過(guò)Redis的有序集合特性來(lái)存儲(chǔ)和管理延時(shí)任務(wù),通過(guò)定期檢查集合中小于等于當(dāng)前時(shí)間的任務(wù)并執(zhí)行,可以實(shí)現(xiàn)延時(shí)任務(wù)的管理,感興趣的朋友跟隨小編一起看看吧2024-11-11redis客戶端實(shí)現(xiàn)高可用讀寫(xiě)分離的方式詳解
基于sentienl 獲取和動(dòng)態(tài)感知 master、slaves節(jié)點(diǎn)信息的變化,我們的讀寫(xiě)分離客戶端就能具備高可用+動(dòng)態(tài)擴(kuò)容感知能力了,接下來(lái)通過(guò)本文給大家分享redis客戶端實(shí)現(xiàn)高可用讀寫(xiě)分離的方式,感興趣的朋友一起看看吧2021-07-07