- 1.在項(xiàng)目中緩存是如何使用的月培?緩存如果使用不當(dāng)會(huì)造成什么后果嘁字?
- 2.用了緩存之后會(huì)有啥不良的后果?
- 3.redis和memcached有什么區(qū)別杉畜?
- 4.redis的線程模型是什么纪蜒?為什么單線程的redis比多線程的memcached效率要高得多(為什么redis是單線程的但是還可以支撐高并發(fā))?
- 5.redis都有哪些數(shù)據(jù)類型此叠?分別在哪些場(chǎng)景下使用比較合適纯续?
- 6.redis的過(guò)期策略都有哪些??jī)?nèi)存淘汰機(jī)制都有哪些?手寫(xiě)一下LRU代碼實(shí)現(xiàn)猬错?
- 7.redis不持久化會(huì)怎么樣窗看,redis掛了會(huì)怎么樣?
1倦炒、在項(xiàng)目中緩存是如何使用的显沈?緩存如果使用不當(dāng)會(huì)造成什么后果?
緩存的目的:緩存就是為了高性能逢唤、高并發(fā)
1)高性能
比如一個(gè)非常耗時(shí)的mysql操作拉讯,每次都去請(qǐng)求mysql,但是查出來(lái)的數(shù)據(jù)可能很長(zhǎng)一段時(shí)間不會(huì)改變鳖藕,或者即使改變了也不用馬上通知用戶魔慷,那就可以用緩存,下次再有人查著恩,直接從緩存里面查院尔。這就是所謂的高性能。項(xiàng)目里的復(fù)雜查詢就可以這樣页滚。
2)高并發(fā)
mysql單機(jī)支撐到2000qps也開(kāi)始容易報(bào)警了召边。
緩存支持高并發(fā)就是說(shuō)面對(duì)突然的高峰期請(qǐng)求铺呵,mysql無(wú)法支撐裹驰,就可以把很多數(shù)據(jù)放在緩存。
緩存功能簡(jiǎn)單片挂,說(shuō)白了就是key-value式操作幻林,單機(jī)支撐的并發(fā)量輕松一秒幾萬(wàn)十幾萬(wàn),支撐高并發(fā)so easy音念。單機(jī)承載并發(fā)量是mysql單機(jī)的幾十倍沪饺。
2.用了緩存之后會(huì)有啥不良的后果?
1)緩存與數(shù)據(jù)庫(kù)雙寫(xiě)不一致
2)緩存雪崩
3)緩存穿透
4)緩存并發(fā)競(jìng)爭(zhēng)
3.redis和memcached有什么區(qū)別闷愤?
1)Redis支持服務(wù)器端的數(shù)據(jù)操作:Redis相比Memcached來(lái)說(shuō)整葡,擁有更多的數(shù)據(jù)結(jié)構(gòu)和支持更豐富的數(shù)據(jù)操作,通常在Memcached里讥脐,你需要將數(shù)據(jù)拿到客戶端來(lái)進(jìn)行類似的修改再set回去遭居。這大大增加了網(wǎng)絡(luò)IO的次數(shù)和數(shù)據(jù)體積。在Redis中旬渠,這些復(fù)雜的操作通常和一般的GET/SET一樣高效俱萍。所以,如果需要緩存能夠支持更復(fù)雜的結(jié)構(gòu)和操作告丢,那么Redis會(huì)是不錯(cuò)的選擇枪蘑。
2)集群模式:memcached沒(méi)有原生的集群模式,需要依靠客戶端來(lái)實(shí)現(xiàn)往集群中分片寫(xiě)入數(shù)據(jù);但是redis目前是原生支持cluster模式的岳颇,redis官方就是支持redis cluster集群模式的照捡,比memcached來(lái)說(shuō)要更好。
4..redis的線程模型是什么话侧?為什么單線程的redis比多線程的memcached效率要高得多(為什么redis是單線程的但是還可以支撐高并發(fā))麻敌?
redis的線程模型
1)件事件處理器
redis基于reactor模式開(kāi)發(fā)了網(wǎng)絡(luò)事件處理器,這個(gè)處理器叫做文件事件處理器掂摔,file event handler术羔。這個(gè)文件事件處理器,是單線程的乙漓,redis才叫做單線程的模型级历,采用IO多路復(fù)用機(jī)制同時(shí)監(jiān)聽(tīng)多個(gè)socket,根據(jù)socket上的事件來(lái)選擇對(duì)應(yīng)的事件處理器來(lái)處理這個(gè)事件叭披。
如果被監(jiān)聽(tīng)的socket準(zhǔn)備好執(zhí)行accept寥殖、read、write涩蜘、close等操作的時(shí)候嚼贡,跟操作對(duì)應(yīng)的文件事件就會(huì)產(chǎn)生,這個(gè)時(shí)候文件事件處理器就會(huì)調(diào)用之前關(guān)聯(lián)好的事件處理器來(lái)處理這個(gè)事件同诫。
文件事件處理器是單線程模式運(yùn)行的粤策,但是通過(guò)IO多路復(fù)用機(jī)制監(jiān)聽(tīng)多個(gè)socket,可以實(shí)現(xiàn)高性能的網(wǎng)絡(luò)通信模型误窖,又可以跟內(nèi)部其他單線程的模塊進(jìn)行對(duì)接叮盘,保證了redis內(nèi)部的線程模型的簡(jiǎn)單性。
文件事件處理器的結(jié)構(gòu)包含4個(gè)部分:多個(gè)socket霹俺,IO多路復(fù)用程序柔吼,文件事件分派器,事件處理器(命令請(qǐng)求處理器丙唧、命令回復(fù)處理器愈魏、連接應(yīng)答處理器,等等)想际。
多個(gè)socket可能并發(fā)的產(chǎn)生不同的操作培漏,每個(gè)操作對(duì)應(yīng)不同的文件事件,但是IO多路復(fù)用程序會(huì)監(jiān)聽(tīng)多個(gè)socket沼琉,但是會(huì)將socket放入一個(gè)隊(duì)列中排隊(duì)北苟,每次從隊(duì)列中取出一個(gè)socket給事件分派器,事件分派器把socket給對(duì)應(yīng)的事件處理器打瘪。
然后一個(gè)socket的事件處理完之后友鼻,IO多路復(fù)用程序才會(huì)將隊(duì)列中的下一個(gè)socket給事件分派器傻昙。文件事件分派器會(huì)根據(jù)每個(gè)socket當(dāng)前產(chǎn)生的事件,來(lái)選擇對(duì)應(yīng)的事件處理器來(lái)處理彩扔。
2)文件事件
當(dāng)socket變得可讀時(shí)(比如客戶端對(duì)redis執(zhí)行write操作妆档,或者close操作),或者有新的可以應(yīng)答的sccket出現(xiàn)時(shí)(客戶端對(duì)redis執(zhí)行connect操作)虫碉,socket就會(huì)產(chǎn)生一個(gè)AE_READABLE事件贾惦。
當(dāng)socket變得可寫(xiě)的時(shí)候(客戶端對(duì)redis執(zhí)行read操作),socket會(huì)產(chǎn)生一個(gè)AE_WRITABLE事件敦捧。
IO多路復(fù)用程序可以同時(shí)監(jiān)聽(tīng)AE_REABLE和AE_WRITABLE兩種事件须板,要是一個(gè)socket同時(shí)產(chǎn)生了AE_READABLE和AE_WRITABLE兩種事件,那么文件事件分派器優(yōu)先處理AE_REABLE事件兢卵,然后才是AE_WRITABLE事件习瑰。
3)文件事件處理器
如果是客戶端要連接redis,那么會(huì)為socket關(guān)聯(lián)連接應(yīng)答處理器
如果是客戶端要寫(xiě)數(shù)據(jù)到redis秽荤,那么會(huì)為socket關(guān)聯(lián)命令請(qǐng)求處理器
如果是客戶端要從redis讀數(shù)據(jù)甜奄,那么會(huì)為socket關(guān)聯(lián)命令回復(fù)處理器
4)客戶端與redis通信的一次流程
在redis啟動(dòng)初始化的時(shí)候,redis會(huì)將連接應(yīng)答處理器跟AE_READABLE事件關(guān)聯(lián)起來(lái)窃款,接著如果一個(gè)客戶端跟redis發(fā)起連接课兄,此時(shí)會(huì)產(chǎn)生一個(gè)AE_READABLE事件,然后由連接應(yīng)答處理器來(lái)處理跟客戶端建立連接晨继,創(chuàng)建客戶端對(duì)應(yīng)的socket烟阐,同時(shí)將這個(gè)socket的AE_READABLE事件跟命令請(qǐng)求處理器關(guān)聯(lián)起來(lái)。
當(dāng)客戶端向redis發(fā)起請(qǐng)求的時(shí)候(不管是讀請(qǐng)求還是寫(xiě)請(qǐng)求踱稍,都一樣)曲饱,首先就會(huì)在socket產(chǎn)生一個(gè)AE_READABLE事件,然后由對(duì)應(yīng)的命令請(qǐng)求處理器來(lái)處理珠月。這個(gè)命令請(qǐng)求處理器就會(huì)從socket中讀取請(qǐng)求相關(guān)數(shù)據(jù),然后進(jìn)行執(zhí)行和處理楔敌。
接著redis這邊準(zhǔn)備好了給客戶端的響應(yīng)數(shù)據(jù)之后啤挎,就會(huì)將socket的AE_WRITABLE事件跟命令回復(fù)處理器關(guān)聯(lián)起來(lái),當(dāng)客戶端這邊準(zhǔn)備好讀取響應(yīng)數(shù)據(jù)時(shí)卵凑,就會(huì)在socket上產(chǎn)生一個(gè)AE_WRITABLE事件庆聘,會(huì)由對(duì)應(yīng)的命令回復(fù)處理器來(lái)處理,就是將準(zhǔn)備好的響應(yīng)數(shù)據(jù)寫(xiě)入socket勺卢,供客戶端來(lái)讀取伙判。
命令回復(fù)處理器寫(xiě)完之后,就會(huì)刪除這個(gè)socket的AE_WRITABLE事件和命令回復(fù)處理器的關(guān)聯(lián)關(guān)系黑忱。
(3)為啥redis單線程模型也能效率這么高宴抚?
1)所有的應(yīng)答處理器基于純內(nèi)存操作勒魔,速度非常快
2)核心是基于非阻塞的IO多路復(fù)用機(jī)制
3)單線程反而避免了多線程的頻繁上下文切換問(wèn)題
5.redis都有哪些數(shù)據(jù)類型菇曲?分別在哪些場(chǎng)景下使用比較合適冠绢?
(1)string
這是最基本的類型了,沒(méi)啥可說(shuō)的常潮,就是普通的set和get弟胀,做簡(jiǎn)單的kv緩存
(2)hash
這個(gè)是類似map的一種結(jié)構(gòu),這個(gè)一般就是可以將結(jié)構(gòu)化的數(shù)據(jù)喊式,比如一個(gè)對(duì)象(前提是這個(gè)對(duì)象沒(méi)嵌套其他的對(duì)象)給緩存在redis里孵户,然后每次讀寫(xiě)緩存的時(shí)候,可以就操作hash里的某個(gè)字段岔留。
key=150
value={
“id”: 150,
“name”: “zhangsan”,
“age”: 20
}
hash類的數(shù)據(jù)結(jié)構(gòu)延届,主要是用來(lái)存放一些對(duì)象,把一些簡(jiǎn)單的對(duì)象給緩存起來(lái)贸诚,后續(xù)操作的時(shí)候方庭,你可以直接僅僅修改這個(gè)對(duì)象中的某個(gè)字段的值
value={
“id”: 150,
“name”: “zhangsan”,
“age”: 21
}
(3)list
有序列表,這個(gè)是可以玩兒出很多花樣的
微博酱固,某個(gè)大v的粉絲械念,就可以以list的格式放在redis里去緩存
key=某大v
value=[zhangsan, lisi, wangwu]
比如可以通過(guò)list存儲(chǔ)一些列表型的數(shù)據(jù)結(jié)構(gòu),類似粉絲列表了运悲、文章的評(píng)論列表了之類的東西龄减。
比如可以通過(guò)lrange命令,就是從某個(gè)元素開(kāi)始讀取多少個(gè)元素,可以基于list實(shí)現(xiàn)分頁(yè)查詢,這個(gè)很棒的一個(gè)功能贤笆,基于redis實(shí)現(xiàn)簡(jiǎn)單的高性能分頁(yè)襟雷,可以做類似微博那種下拉不斷分頁(yè)的東西,性能高淆院,就一頁(yè)一頁(yè)走
比如可以搞個(gè)簡(jiǎn)單的消息隊(duì)列,從list頭懟進(jìn)去,從list尾巴那里弄出來(lái)
(4)set
無(wú)序集合违崇,自動(dòng)去重
直接基于set將系統(tǒng)里需要去重的數(shù)據(jù)扔進(jìn)去,自動(dòng)就給去重了诊霹,如果你需要對(duì)一些數(shù)據(jù)進(jìn)行快速的全局去重羞延,你當(dāng)然也可以基于jvm內(nèi)存里的HashSet進(jìn)行去重,但是如果你的某個(gè)系統(tǒng)部署在多臺(tái)機(jī)器上呢脾还?
得基于redis進(jìn)行全局的set去重
可以基于set玩兒交集伴箩、并集、差集的操作鄙漏,比如交集吧嗤谚,可以把兩個(gè)人的粉絲列表整一個(gè)交集棺蛛,看看倆人的共同好友是誰(shuí)?對(duì)吧
把兩個(gè)大v的粉絲都放在兩個(gè)set中呵恢,對(duì)兩個(gè)set做交集
(5)sorted set
排序的set鞠值,去重但是可以排序,寫(xiě)進(jìn)去的時(shí)候給一個(gè)分?jǐn)?shù)渗钉,自動(dòng)根據(jù)分?jǐn)?shù)排序彤恶,這個(gè)可以玩兒很多的花樣,最大的特點(diǎn)是有個(gè)分?jǐn)?shù)可以自定義排序規(guī)則
比如說(shuō)你要是想根據(jù)時(shí)間對(duì)數(shù)據(jù)排序鳄橘,那么可以寫(xiě)入進(jìn)去的時(shí)候用某個(gè)時(shí)間作為分?jǐn)?shù)声离,人家自動(dòng)給你按照時(shí)間排序了
排行榜:將每個(gè)用戶以及其對(duì)應(yīng)的什么分?jǐn)?shù)寫(xiě)入進(jìn)去,zadd board score username瘫怜,接著zrevrange board 0 99术徊,就可以獲取排名前100的用戶;zrank board username鲸湃,可以看到用戶在排行榜里的排名
zadd board 85 zhangsan
zadd board 72 wangwu
zadd board 96 lisi
zadd board 62 zhaoliu
96 lisi
85 zhangsan
72 wangwu
62 zhaoliu
zrevrange board 0 3
獲取排名前3的用戶
96 lisi
85 zhangsan
72 wangwu
zrank board zhaoliu
6.redis的過(guò)期策略都有哪些赠涮??jī)?nèi)存淘汰機(jī)制都有哪些?手寫(xiě)一下LRU代碼實(shí)現(xiàn)暗挑?
1)往redis里寫(xiě)的數(shù)據(jù)怎么沒(méi)了笋除?
redis主要是基于內(nèi)存來(lái)進(jìn)行高性能、高并發(fā)的讀寫(xiě)操作的炸裆。
所以說(shuō)垃它,這是緩存的一個(gè)最基本的概念,數(shù)據(jù)是會(huì)過(guò)期的烹看,要么是你自己設(shè)置個(gè)過(guò)期時(shí)間国拇,要么是redis自己給干掉。
2)redis的過(guò)期策略都有哪些惯殊?
答案是:定期刪除+惰性刪除
所謂定期刪除酱吝,指的是redis默認(rèn)是每隔100ms就隨機(jī)抽取一些設(shè)置了過(guò)期時(shí)間的key,檢查其是否過(guò)期靠胜,如果過(guò)期就刪除掉瞳。假設(shè)redis里放了10萬(wàn)個(gè)key,都設(shè)置了過(guò)期時(shí)間浪漠,你每隔幾百毫秒,就檢查10萬(wàn)個(gè)key霎褐,那redis基本上就死了址愿,cpu負(fù)載會(huì)很高的。注意冻璃,這里可不是每隔100ms就遍歷所有的設(shè)置過(guò)期時(shí)間的key响谓,那樣就是一場(chǎng)性能上的災(zāi)難损合。實(shí)際上redis是每隔100ms隨機(jī)抽取一些key來(lái)檢查和刪除的。
但是問(wèn)題是娘纷,定期刪除可能會(huì)導(dǎo)致很多過(guò)期key到了時(shí)間并沒(méi)有被刪除掉嫁审,那咋整呢?所以就是惰性刪除了赖晶。在你獲取某個(gè)key的時(shí)候律适,redis會(huì)檢查一下 ,這個(gè)key如果設(shè)置了過(guò)期時(shí)間那么是否過(guò)期了遏插?如果過(guò)期了此時(shí)就會(huì)刪除捂贿,不會(huì)給你返回任何東西。
并不是key到時(shí)間就被刪除掉胳嘲,而是你查詢這個(gè)key的時(shí)候厂僧,redis再懶惰的檢查一下。
但是實(shí)際上這還是有問(wèn)題的了牛,如果定期刪除漏掉了很多過(guò)期key颜屠,然后你也沒(méi)及時(shí)去查,也就沒(méi)走惰性刪除鹰祸,此時(shí)會(huì)怎么樣甫窟?如果大量過(guò)期key堆積在內(nèi)存里,導(dǎo)致redis內(nèi)存塊耗盡了福荸。
答案是:走內(nèi)存淘汰機(jī)制蕴坪。
3)內(nèi)存淘汰機(jī)制都有哪些?
如果redis的內(nèi)存占用過(guò)多的時(shí)候敬锐,此時(shí)會(huì)進(jìn)行內(nèi)存淘汰背传,有如下一些策略:
1)noeviction:當(dāng)內(nèi)存不足以容納新寫(xiě)入數(shù)據(jù)時(shí),新寫(xiě)入操作會(huì)報(bào)錯(cuò)台夺,這個(gè)一般沒(méi)人用吧径玖,實(shí)在是太惡心了
2)allkeys-lru:當(dāng)內(nèi)存不足以容納新寫(xiě)入數(shù)據(jù)時(shí),在鍵空間中颤介,移除最近最少使用的key
3)allkeys-random:當(dāng)內(nèi)存不足以容納新寫(xiě)入數(shù)據(jù)時(shí)梳星,在鍵空間中,隨機(jī)移除某個(gè)key滚朵,這個(gè)一般沒(méi)人用吧冤灾,為啥要隨機(jī),肯定是把最近最少使用的key給干掉啊
4)volatile-lru:當(dāng)內(nèi)存不足以容納新寫(xiě)入數(shù)據(jù)時(shí)辕近,在設(shè)置了過(guò)期時(shí)間的鍵空間中韵吨,移除最近最少使用的key
5)volatile-random:當(dāng)內(nèi)存不足以容納新寫(xiě)入數(shù)據(jù)時(shí),在設(shè)置了過(guò)期時(shí)間的鍵空間中移宅,隨機(jī)移除某個(gè)key
6)volatile-ttl:當(dāng)內(nèi)存不足以容納新寫(xiě)入數(shù)據(jù)時(shí)归粉,在設(shè)置了過(guò)期時(shí)間的鍵空間中椿疗,有更早過(guò)期時(shí)間的key優(yōu)先移除
(3)手寫(xiě)一個(gè)LRU算法?
public class LRUCache<K, V> extends LinkedHashMap<K, V> {
private final int CACHE_SIZE;
// 這里就是傳遞進(jìn)來(lái)最多能緩存多少數(shù)據(jù)
public LRUCache(int cacheSize) {
super((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true); // 這塊就是設(shè)置一個(gè)hashmap的初始大小糠悼,同時(shí)最后一個(gè)true指的是讓linkedhashmap按照訪問(wèn)順序來(lái)進(jìn)行排序届榄,最近訪問(wèn)的放在頭,最老訪問(wèn)的就在尾
CACHE_SIZE = cacheSize;
}
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > CACHE_SIZE; // 這個(gè)意思就是說(shuō)當(dāng)map中的數(shù)據(jù)量大于指定的緩存?zhèn)€數(shù)的時(shí)候倔喂,就自動(dòng)刪除最老的數(shù)據(jù)
}
}
7.redis不持久化會(huì)怎么樣铝条,redis掛了會(huì)怎么樣?
redis如果僅僅只是將數(shù)據(jù)緩存在內(nèi)存里面滴劲,如果redis宕機(jī)了攻晒,再重啟,內(nèi)存里的數(shù)據(jù)就全部都弄丟了班挖,必須得用redis的持久化機(jī)制鲁捏,將數(shù)據(jù)寫(xiě)入內(nèi)存的同時(shí),異步的慢慢的將數(shù)據(jù)寫(xiě)入磁盤文件里萧芙,進(jìn)行持久化如果redis宕機(jī)了给梅,重啟啟動(dòng),自動(dòng)從磁盤上加載之前持久化的一些數(shù)據(jù)双揪,就可以了动羽,也許會(huì)丟失少許數(shù)據(jù),但是至少不會(huì)將所有數(shù)據(jù)都弄丟 渔期。
redis整個(gè)掛了运吓,如果你沒(méi)做數(shù)據(jù)備份,這個(gè)時(shí)候redis啟動(dòng)了疯趟,數(shù)據(jù)都沒(méi)了拘哨,大量的請(qǐng)求過(guò)來(lái),緩存全部無(wú)法命中信峻,在redis里根本找不到數(shù)據(jù)倦青,緩存雪崩問(wèn)題,所有請(qǐng)求盹舞,沒(méi)有在redis命中产镐,就會(huì)去mysql數(shù)據(jù)庫(kù)這種數(shù)據(jù)源頭中去找,一下子mysql承接高并發(fā)踢步,然后就掛了癣亚。
8.redis為什么要持久化
redis持久化的意義在于故障恢復(fù)
什么是故障恢復(fù):比如你部署了一個(gè)redis,作為cache緩存获印,當(dāng)然也可以保存一些較為重要的數(shù)據(jù)逃糟,如果沒(méi)有持久化的話,redis遇到災(zāi)難性故障的時(shí)候蓬豁,就會(huì)丟失所有的數(shù)據(jù)绰咽。
如果通過(guò)持久化將數(shù)據(jù)搞一份兒在磁盤上去,然后定期比如說(shuō)同步和備份到一些云存儲(chǔ)服務(wù)上去地粪,那么就可以保證數(shù)據(jù)不丟失全部取募,還是可以恢復(fù)一部分?jǐn)?shù)據(jù)回來(lái)的。
9.redis持久化有幾種方式蟆技,優(yōu)缺點(diǎn)玩敏,適合什么場(chǎng)景,你喜歡哪種质礼。具體的實(shí)現(xiàn)機(jī)制是什么旺聚?
redis持久化有兩種,RDB眶蕉,AOF
RDB:是每隔一段時(shí)間對(duì)redis中的數(shù)據(jù)做一份快照砰粹。
AOF:把每條寫(xiě)入redis的命令作為日志,以append-only的模式寫(xiě)入一個(gè)日志文件中造挽,在redis重啟的時(shí)候碱璃,可以通過(guò)回放AOF日志中的寫(xiě)入指令來(lái)重新構(gòu)建數(shù)據(jù)。
如果我們想要redis僅僅作為純內(nèi)存的緩存來(lái)用饭入,那么可以禁止RDB和AOF所有的持久化機(jī)制嵌器。
通過(guò)RDB或AOF,都可以將redis內(nèi)存中的數(shù)據(jù)給持久化到磁盤上面來(lái)谐丢,然后可以將這些數(shù)據(jù)備份到別的地方去爽航,比如說(shuō)阿里云,云服務(wù)乾忱。
如果同時(shí)使用RDB和AOF兩種持久化機(jī)制讥珍,那么在redis重啟的時(shí)候,會(huì)使用AOF來(lái)重新構(gòu)建數(shù)據(jù)饭耳,因?yàn)锳OF中的數(shù)據(jù)更加完整串述。
2、RDB持久化機(jī)制的優(yōu)點(diǎn)
(1)RDB會(huì)生成多個(gè)數(shù)據(jù)文件寞肖,每個(gè)數(shù)據(jù)文件都代表了某一個(gè)時(shí)刻中redis的數(shù)據(jù)纲酗,這種多個(gè)數(shù)據(jù)文件的方式,非常適合做冷備新蟆,可以將這種完整的數(shù)據(jù)文件發(fā)送到一些遠(yuǎn)程的安全存儲(chǔ)上去觅赊,以預(yù)定好的備份策略來(lái)定期備份redis中的數(shù)據(jù)。
(2)RDB對(duì)redis對(duì)外提供的讀寫(xiě)服務(wù)琼稻,影響非常小吮螺,可以讓redis保持高性能,因?yàn)閞edis主進(jìn)程只需要fork一個(gè)子進(jìn)程,讓子進(jìn)程執(zhí)行磁盤IO操作來(lái)進(jìn)行RDB持久化即可
(3)相對(duì)于AOF持久化機(jī)制來(lái)說(shuō)鸠补,直接基于RDB數(shù)據(jù)文件來(lái)重啟和恢復(fù)redis進(jìn)程萝风,更加快速。
3紫岩、RDB持久化機(jī)制的缺點(diǎn)
(1)如果想要在redis故障時(shí)规惰,盡可能少的丟失數(shù)據(jù),那么RDB沒(méi)有AOF好泉蝌。一般來(lái)說(shuō)歇万,RDB數(shù)據(jù)快照文件,都是每隔5分鐘勋陪,或者更長(zhǎng)時(shí)間生成一次贪磺,這個(gè)時(shí)候就得接受一旦redis進(jìn)程宕機(jī),那么會(huì)丟失最近5分鐘的數(shù)據(jù)诅愚,這個(gè)問(wèn)題寒锚,也是rdb最大的缺點(diǎn),就是不適合做第一優(yōu)先的恢復(fù)方案呻粹,如果你依賴RDB做第一優(yōu)先恢復(fù)方案壕曼,會(huì)導(dǎo)致數(shù)據(jù)丟失的比較多
(2)RDB每次在fork子進(jìn)程來(lái)執(zhí)行RDB快照數(shù)據(jù)文件生成的時(shí)候,如果數(shù)據(jù)文件特別大等浊,可能會(huì)導(dǎo)致對(duì)客戶端提供的服務(wù)暫停數(shù)毫秒腮郊,或者甚至數(shù)秒。
一般不要讓RDB的間隔太長(zhǎng)筹燕,否則每次生成的RDB文件太大了轧飞,對(duì)redis本身的性能可能會(huì)有影響的。
4撒踪、AOF持久化機(jī)制的優(yōu)點(diǎn)
(1)AOF可以更好的保護(hù)數(shù)據(jù)不丟失过咬,一般AOF會(huì)每隔1秒,通過(guò)一個(gè)后臺(tái)線程執(zhí)行一次fsync操作制妄,如果redis掛了掸绞,最多丟失1秒鐘的數(shù)據(jù)
(2)AOF日志文件以append-only模式寫(xiě)入,所以沒(méi)有任何磁盤尋址的開(kāi)銷耕捞,寫(xiě)入性能非常高衔掸,而且文件不容易破損,即使文件尾部破損俺抽,也很容易修復(fù)敞映。
(3)AOF日志文件即使過(guò)大的時(shí)候,出現(xiàn)后臺(tái)重寫(xiě)操作磷斧,也不會(huì)影響客戶端的讀寫(xiě)振愿。因?yàn)樵趓ewrite log的時(shí)候捷犹,會(huì)對(duì)其中的指導(dǎo)進(jìn)行壓縮,創(chuàng)建出一份需要恢復(fù)數(shù)據(jù)的最小日志出來(lái)冕末。再創(chuàng)建新日志文件的時(shí)候萍歉,老的日志文件還是照常寫(xiě)入。當(dāng)新的merge后的日志文件ready的時(shí)候栓霜,再交換新老日志文件即可翠桦。
(4)AOF日志文件的命令通過(guò)非常可讀的方式進(jìn)行記錄胳蛮,這個(gè)特性非常適合做災(zāi)難性的誤刪除的緊急恢復(fù)。比如某人不小心用flushall命令清空了所有數(shù)據(jù)丛晌,只要這個(gè)時(shí)候后臺(tái)rewrite還沒(méi)有發(fā)生仅炊,那么就可以立即拷貝AOF文件,將最后一條flushall命令給刪了澎蛛,然后再將該AOF文件放回去抚垄,就可以通過(guò)恢復(fù)機(jī)制,自動(dòng)恢復(fù)所有數(shù)據(jù)谋逻。
5呆馁、AOF持久化機(jī)制的缺點(diǎn)
(1)對(duì)于同一份數(shù)據(jù)來(lái)說(shuō),AOF日志文件通常比RDB數(shù)據(jù)快照文件更大
(2)AOF開(kāi)啟后毁兆,支持的寫(xiě)QPS會(huì)比RDB支持的寫(xiě)QPS低浙滤,因?yàn)锳OF一般會(huì)配置成每秒fsync一次日志文件,當(dāng)然气堕,每秒一次fsync(這個(gè)是配置的纺腊,一般是1s),性能也還是很高的
如果你要保證一條數(shù)據(jù)都不丟茎芭,也是可以的揖膜,AOF的fsync設(shè)置成沒(méi)寫(xiě)入一條數(shù)據(jù),fsync一次梅桩,那就完蛋了壹粟,redis的QPS大降。
(3)以前AOF發(fā)生過(guò)bug宿百,就是通過(guò)AOF記錄的日志趁仙,進(jìn)行數(shù)據(jù)恢復(fù)的時(shí)候,沒(méi)有恢復(fù)一模一樣的數(shù)據(jù)出來(lái)犀呼。所以說(shuō)幸撕,類似AOF這種較為復(fù)雜的基于命令日志/merge/回放的方式,比基于RDB每次持久化一份完整的數(shù)據(jù)快照文件的方式外臂,更加脆弱一些坐儿,容易有bug。不過(guò)AOF就是為了避免rewrite過(guò)程導(dǎo)致的bug,因此每次rewrite并不是基于舊的指令日志進(jìn)行merge的貌矿,而是基于當(dāng)時(shí)內(nèi)存中的數(shù)據(jù)進(jìn)行指令的重新構(gòu)建炭菌,這樣健壯性會(huì)好很多。
6逛漫、RDB和AOF到底該如何選擇
(1)不要僅僅使用RDB黑低,因?yàn)槟菢訒?huì)導(dǎo)致你丟失很多數(shù)據(jù)
(2)也不要僅僅使用AOF,因?yàn)槟菢佑袃蓚€(gè)問(wèn)題酌毡,第一克握,你通過(guò)AOF做冷備,沒(méi)有RDB做冷備來(lái)的恢復(fù)速度更快; 第二枷踏,RDB每次簡(jiǎn)單粗暴生成數(shù)據(jù)快照菩暗,更加健壯,可以避免AOF這種復(fù)雜的備份和恢復(fù)機(jī)制的bug
(3)綜合使用AOF和RDB兩種持久化機(jī)制旭蠕,用AOF來(lái)保證數(shù)據(jù)不丟失停团,作為數(shù)據(jù)恢復(fù)的第一選擇; 用RDB來(lái)做不同程度的冷備,在AOF文件都丟失或損壞不可用的時(shí)候掏熬,還可以使用RDB來(lái)進(jìn)行快速的數(shù)據(jù)恢復(fù)