網(wǎng)站的建設(shè)域名空間軟文范例200字
目錄
?Redis面試常見(jiàn)問(wèn)題?
如果發(fā)生了緩存穿透、擊穿、雪崩,該如何解決?
緩存穿透
什么是布隆過(guò)濾器?
緩存擊穿
緩存雪崩
雙寫(xiě)一致性(redis做為緩存,mysql的數(shù)據(jù)如何與redis進(jìn)行同步呢?)
1.若一致性要求高:強(qiáng)一致方案(分布式鎖)
2.延時(shí)雙刪
數(shù)據(jù)的持久化
Redis持久化
RDB的執(zhí)行原理
AOF執(zhí)行原理
RDB與AOF對(duì)比
?編輯
Redis的數(shù)據(jù)過(guò)期策略有哪些
Redis數(shù)據(jù)刪除策略-惰性刪除
Redis數(shù)據(jù)刪除策略-定期刪除
Redis的數(shù)據(jù)淘汰策略有哪些
數(shù)據(jù)淘汰策略
數(shù)據(jù)淘汰策略-使用建議
?Redis面試常見(jiàn)問(wèn)題?
?????????Redis面試八股主要分為:使用場(chǎng)景問(wèn)題和如何保障高并發(fā)問(wèn)題。其中使用場(chǎng)景問(wèn)題包括:
- Redis的數(shù)據(jù)持久化策略有哪些
- 什么是緩存穿透,怎么解決
- 什么是布隆過(guò)濾器
- 什么是緩存擊穿,怎么解決
- 什么是緩存雪崩,怎么解決
- redis雙寫(xiě)問(wèn)題
- Redis分布式鎖如何實(shí)現(xiàn)
- Redis實(shí)現(xiàn)分布式鎖如何合理的控制鎖的有效時(shí)長(zhǎng)
- Redis的數(shù)據(jù)過(guò)期策略有哪些
- Redis的數(shù)據(jù)淘汰策略有哪些
?高并發(fā)問(wèn)題包括:
- Redis集群有哪些方案
- 什么是 Redis 主從同步
- 場(chǎng)景使用Redis是單點(diǎn)還是集群 ? 哪種集群
- Redis分片集群中數(shù)據(jù)是怎么存儲(chǔ)和讀取的
- redis集群腦裂
- 怎么保證redis的高并發(fā)高可用
- 事務(wù)的命令有哪些
- Redis是單線程的,但是為什么還那么快??
如果發(fā)生了緩存穿透、擊穿、雪崩,該如何解決?
緩存穿透
????????緩存穿透是指查詢一個(gè)一定不存在的數(shù)據(jù),由于存儲(chǔ)層查不到數(shù)據(jù)因此不寫(xiě)入緩存,這將導(dǎo)致這個(gè)不存在的數(shù)據(jù)每次請(qǐng)求都要到 DB 去查詢,可能導(dǎo)致 DB 掛掉。這種情況大概率是遭到了攻擊。解決方案的話,我們通常都會(huì)用布隆過(guò)濾器來(lái)解決它。
解決方案一:緩存空數(shù)據(jù),查詢返回的數(shù)據(jù)為空,仍把這個(gè)空結(jié)果進(jìn)行緩存(但可能會(huì)發(fā)生數(shù)據(jù)庫(kù)和Redis不一致的問(wèn)題)
解決方案二:布隆過(guò)濾器
什么是布隆過(guò)濾器?
????????布隆過(guò)濾器主要是用于檢索一個(gè)元素是否在一個(gè)集合中。我們當(dāng)時(shí)使用的是Redisson實(shí)現(xiàn)的布隆過(guò)濾器。它的底層原理是,先初始化一個(gè)比較大的數(shù)組,里面存放的是二進(jìn)制0或1。一開(kāi)始都是0,當(dāng)一個(gè)key來(lái)了之后,經(jīng)過(guò)3次hash計(jì)算,模數(shù)組長(zhǎng)度找到數(shù)據(jù)的下標(biāo),然后把數(shù)組中原來(lái)的0改為1。這樣,三個(gè)數(shù)組的位置就能標(biāo)明一個(gè)key的存在。查找的過(guò)程也是一樣的。
????????布隆過(guò)濾器有可能會(huì)產(chǎn)生一定的誤判,我們一般可以設(shè)置這個(gè)誤判率,大概不會(huì)超過(guò)5%。其實(shí)這個(gè)誤判是必然存在的,要不就得增加數(shù)組的長(zhǎng)度。5%以內(nèi)的誤判率一般的項(xiàng)目也能接受,不至于高并發(fā)下壓倒數(shù)據(jù)庫(kù)。
緩存擊穿
????????緩存擊穿的意思是:redis某個(gè)熱點(diǎn)key過(guò)期或者剛開(kāi)始,但是此時(shí)有大量的用戶訪問(wèn)該過(guò)期key(或者大并發(fā)場(chǎng)景下剛開(kāi)始這個(gè)數(shù)據(jù)只在數(shù)據(jù)庫(kù)里不在緩存里),這個(gè)時(shí)候大并發(fā)的請(qǐng)求可能會(huì)瞬間把 DB 壓垮。
??解決方案有兩種方式:
- 第一,可以使用互斥鎖:當(dāng)緩存失效時(shí),不立即去load db,先使用如 Redis 的
SETNX
去設(shè)置一個(gè)互斥鎖。當(dāng)操作成功返回時(shí),再進(jìn)行 load db的操作并回設(shè)緩存,否則重試get緩存的方法。
- 第二種方案是設(shè)置當(dāng)前key邏輯過(guò)期,大概思路如下:
1) 在設(shè)置key的時(shí)候,設(shè)置一個(gè)過(guò)期時(shí)間字段一塊存入緩存中,不給當(dāng)前key設(shè)置過(guò)期時(shí)間;
2) 當(dāng)查詢的時(shí)候,從redis取出數(shù)據(jù)后判斷時(shí)間是否過(guò)期;
3) 如果過(guò)期,則開(kāi)通另外一個(gè)線程進(jìn)行數(shù)據(jù)同步,當(dāng)前線程正常返回?cái)?shù)據(jù),這個(gè)數(shù)據(jù)可能不是最新的。
總結(jié),兩種方案各有利弊:如果選擇數(shù)據(jù)的強(qiáng)一致性,建議使用分布式鎖的方案,但性能上可能沒(méi)那么高,且有可能產(chǎn)生死鎖的問(wèn)題。如果選擇key的邏輯刪除,則優(yōu)先考慮高可用性,性能比較高,但數(shù)據(jù)同步這塊做不到強(qiáng)一致。
緩存雪崩
????????緩存雪崩是,設(shè)置緩存時(shí)采用了相同的過(guò)期時(shí)間,導(dǎo)致緩存在某一時(shí)刻同時(shí)失效,請(qǐng)求全部轉(zhuǎn)發(fā)到DB,DB瞬時(shí)壓力過(guò)重而雪崩。與緩存擊穿的區(qū)別是:雪崩是很多key,而擊穿是某一個(gè)key緩存。
????????解決方案主要是,給緩存業(yè)務(wù)添加降級(jí)限流策略或者給業(yè)務(wù)添加多級(jí)緩存??梢詫⒕彺媸r(shí)間分散開(kāi)。比如,可以在原有的失效時(shí)間基礎(chǔ)上增加一個(gè)隨機(jī)值,比如1-5分鐘隨機(jī)。這樣,每一個(gè)緩存的過(guò)期時(shí)間的重復(fù)率就會(huì)降低,就很難引發(fā)集體失效的事件。
雙寫(xiě)一致性(redis做為緩存,mysql的數(shù)據(jù)如何與redis進(jìn)行同步呢?)
不同的業(yè)務(wù)場(chǎng)景有不同的策略,面試時(shí)一定要根據(jù)業(yè)務(wù)實(shí)際情況回答。
雙寫(xiě)一致性:當(dāng)修改了數(shù)據(jù)庫(kù)的數(shù)據(jù)也要同時(shí)更新緩存的數(shù)據(jù),緩存和數(shù)據(jù)庫(kù)的數(shù)據(jù)要保持一致
1.若一致性要求高:強(qiáng)一致方案(分布式鎖)
采用redisson實(shí)現(xiàn)的讀寫(xiě)鎖。
????????在讀的時(shí)候添加共享鎖,可以保證讀讀不互斥,讀寫(xiě)互斥(其他線程可以一起讀,但是不能寫(xiě))。當(dāng)我們更新數(shù)據(jù)的時(shí)候,添加排他鎖,它是讀寫(xiě),讀讀都互斥(其他線程不能讀也不能寫(xiě)),這樣就能保證在寫(xiě)數(shù)據(jù)的同時(shí)是不會(huì)讓其他線程讀數(shù)據(jù)的,避免了臟數(shù)據(jù)。排他鎖底層使用也是setnx,保證了同時(shí)只能有一個(gè)線程操作鎖住的方法。
共享鎖:讀鎖readLock,加鎖之后,其他線程可以共享讀操作。? ? ??
排他鎖:獨(dú)占鎖writeLock也叫,加鎖之后,阻塞其他線程讀寫(xiě)操作。
2.延時(shí)雙刪
- 策略原理:延時(shí)雙刪策略的核心是在寫(xiě)庫(kù)操作的前后分別進(jìn)行刪除緩存操作,并設(shè)定合理的超時(shí)時(shí)間來(lái)確保讀請(qǐng)求結(jié)束,寫(xiě)請(qǐng)求可以刪除可能產(chǎn)生的緩存臟數(shù)據(jù)。
- 具體步驟:先刪除緩存,再寫(xiě)數(shù)據(jù)庫(kù),然后線程休眠一段時(shí)間(比如500毫秒),最后再次刪除緩存。休眠時(shí)間的確定需要評(píng)估項(xiàng)目讀數(shù)據(jù)業(yè)務(wù)邏輯的耗時(shí),并考慮Redis和數(shù)據(jù)庫(kù)主從同步的耗時(shí)。
- 優(yōu)缺點(diǎn):這種策略能在一定程度上解決數(shù)據(jù)不一致的問(wèn)題,但增加了寫(xiě)請(qǐng)求的耗時(shí),并且在最差的超時(shí)時(shí)間內(nèi),數(shù)據(jù)仍可能存在不一致性。
延時(shí)刪除的具體方案,異步通知保證數(shù)據(jù)的最終一致性
基于Canal的異步通知:
總結(jié):
允許延時(shí)一致的業(yè)務(wù),采用異步通知 使用MQ中間中間件,更新數(shù)據(jù)之后,通知緩存刪除 利用canal中間件,不需要修改業(yè)務(wù)代碼,偽裝為mysql的一個(gè)從節(jié)點(diǎn),canal通過(guò)讀取binlog數(shù)據(jù)更新緩存。強(qiáng)一致性的,采用Redisson提供的讀寫(xiě)鎖 共享鎖:讀鎖readLock,加鎖之后,其他線程可以共享讀操作 ? ? ? 排他鎖:獨(dú)占鎖writeLock也叫,加鎖之后,阻塞其他線程讀寫(xiě)操作
數(shù)據(jù)的持久化
在Redis中提供了兩種數(shù)據(jù)持久化的方式:1、RDB ? 2、AOF
Redis持久化
????????RDB全稱Redis Database Backup file(Redis數(shù)據(jù)備份文件),也被叫做Redis數(shù)據(jù)快照。簡(jiǎn)單來(lái)說(shuō)就是把內(nèi)存中的所有數(shù)據(jù)都記錄到磁盤(pán)中。當(dāng)Redis實(shí)例故障重啟后,從磁盤(pán)讀取快照文件,恢復(fù)數(shù)據(jù)。
RDB的執(zhí)行原理
????????bgsave開(kāi)始時(shí)會(huì)fork主進(jìn)程得到子進(jìn)程,子進(jìn)程共享主進(jìn)程的內(nèi)存數(shù)據(jù)。完成fork后讀取內(nèi)存數(shù)據(jù)并寫(xiě)入 RDB 文件。 fork采用的是copy-on-write技術(shù): 當(dāng)主進(jìn)程執(zhí)行讀操作時(shí),訪問(wèn)共享內(nèi)存; 當(dāng)主進(jìn)程執(zhí)行寫(xiě)操作時(shí),則會(huì)拷貝一份數(shù)據(jù),執(zhí)行寫(xiě)操作。
AOF執(zhí)行原理
????????AOF全稱為Append Only File(追加文件)。Redis處理的每一個(gè)寫(xiě)命令都會(huì)記錄在AOF文件,可以看做是命令日志文件。
????????因?yàn)槭怯涗浢?#xff0c;AOF文件會(huì)比RDB文件大的多。而且AOF會(huì)記錄對(duì)同一個(gè)key的多次寫(xiě)操作,但只有最后一次寫(xiě)操作才有意義。通過(guò)執(zhí)行bgrewriteaof命令,可以讓AOF文件執(zhí)行重寫(xiě)功能,用最少的命令達(dá)到相同效果。Redis也會(huì)在觸發(fā)閾值時(shí)自動(dòng)去重寫(xiě)AOF文件。閾值也可以在redis.conf中配置。
RDB與AOF對(duì)比
Redis的數(shù)據(jù)過(guò)期策略有哪些
Redis數(shù)據(jù)刪除策略-惰性刪除
????????惰性刪除:設(shè)置該key過(guò)期時(shí)間后,我們不去管它,當(dāng)需要該key時(shí),我們?cè)跈z查其是否過(guò)期,如果過(guò)期,我們就刪掉它,反之返回該key。
優(yōu)點(diǎn) :對(duì)CPU友好,只會(huì)在使用該key時(shí)才會(huì)進(jìn)行過(guò)期檢查,對(duì)于很多用不到的key不用浪費(fèi)時(shí)間進(jìn)行過(guò)期檢查。
缺點(diǎn) :對(duì)內(nèi)存不友好,如果一個(gè)key已經(jīng)過(guò)期,但是一直沒(méi)有使用,那么該key就會(huì)一直存在內(nèi)存中,內(nèi)存永遠(yuǎn)不會(huì)釋放。
Redis數(shù)據(jù)刪除策略-定期刪除
????????定期刪除:每隔一段時(shí)間,我們就對(duì)一些key進(jìn)行檢查,刪除里面過(guò)期的key(從一定數(shù)量的數(shù)據(jù)庫(kù)中取出一定數(shù)量的隨機(jī)key進(jìn)行檢查,并刪除其中的過(guò)期key)。
定期清理有兩種模式:
- SLOW模式是定時(shí)任務(wù),執(zhí)行頻率默認(rèn)為10hz,每次不超過(guò)25ms,以通過(guò)修改配置文件redis.conf 的hz 選項(xiàng)來(lái)調(diào)整這個(gè)次數(shù)
- FAST模式執(zhí)行頻率不固定,但兩次間隔不低于2ms,每次耗時(shí)不超過(guò)1ms
優(yōu)點(diǎn):可以通過(guò)限制刪除操作執(zhí)行的時(shí)長(zhǎng)和頻率來(lái)減少刪除操作對(duì) CPU 的影響。另外定期刪除,也能有效釋放過(guò)期鍵占用的內(nèi)存。 缺點(diǎn):難以確定刪除操作執(zhí)行的時(shí)長(zhǎng)和頻率。
Redis的過(guò)期刪除策略:惰性刪除 + 定期刪除兩種策略進(jìn)行配合使用。
Redis的數(shù)據(jù)淘汰策略有哪些
數(shù)據(jù)淘汰策略
????????數(shù)據(jù)的淘汰策略:當(dāng)Redis中的內(nèi)存不夠用時(shí),此時(shí)在向Redis中添加新的key,那么Redis就會(huì)按照某一種規(guī)則將內(nèi)存中的數(shù)據(jù)刪除掉,這種數(shù)據(jù)的刪除規(guī)則被稱之為內(nèi)存的淘汰策略。
Redis支持8種不同策略來(lái)選擇要?jiǎng)h除的key:
- noeviction: 不淘汰任何key,但是內(nèi)存滿時(shí)不允許寫(xiě)入新數(shù)據(jù),默認(rèn)就是這種策略。
- volatile-ttl: 對(duì)設(shè)置了TTL的key,比較key的剩余TTL值,TTL越小越先被淘汰
- allkeys-random:對(duì)全體key ,隨機(jī)進(jìn)行淘汰。
- volatile-random:對(duì)設(shè)置了TTL的key ,隨機(jī)進(jìn)行淘汰。
- allkeys-lru: 對(duì)全體key,基于LRU算法進(jìn)行淘汰
- volatile-lru: 對(duì)設(shè)置了TTL的key,基于LRU算法進(jìn)行淘汰
- allkeys-lfu: 對(duì)全體key,基于LFU算法進(jìn)行淘汰
- volatile-lfu: 對(duì)設(shè)置了TTL的key,基于LFU算法進(jìn)行淘汰
LRU(Least Recently Used)最近最少使用。用當(dāng)前時(shí)間減去最后一次訪問(wèn)時(shí)間,這個(gè)值越大則淘汰優(yōu)先級(jí)越高。 LFU(Least Frequently Used)最少頻率使用。會(huì)統(tǒng)計(jì)每個(gè)key的訪問(wèn)頻率,值越小淘汰優(yōu)先級(jí)越高。
數(shù)據(jù)淘汰策略-使用建議
- ?優(yōu)先使用 allkeys-lru 策略。充分利用 LRU 算法的優(yōu)勢(shì),把最近最常訪問(wèn)的數(shù)據(jù)留在緩存中。
- 如果業(yè)務(wù)有明顯的冷熱數(shù)據(jù)區(qū)分,建議使用。
- 如果業(yè)務(wù)中數(shù)據(jù)訪問(wèn)頻率差別不大,沒(méi)有明顯冷熱數(shù)據(jù)區(qū)分,建議使用 allkeys-random,隨機(jī)選擇淘汰。
- 如果業(yè)務(wù)中有置頂?shù)男枨?#xff0c;可以使用 volatile-lru 策略,同時(shí)置頂數(shù)據(jù)不設(shè)置過(guò)期時(shí)間,這些數(shù)據(jù)就一直不被刪除,會(huì)淘汰其他設(shè)置過(guò)期時(shí)間的數(shù)據(jù)。
- 如果業(yè)務(wù)中有短時(shí)高頻訪問(wèn)的數(shù)據(jù),可以使用 allkeys-lfu 或 volatile-lfu 策略。
選用Redis八股:Docs