重慶網(wǎng)站建設(shè) cqhtwl臨沂百度代理公司有幾個(gè)
?“年輕人,就要勇敢追夢(mèng)”🌹
參考資料:圖解redis
目錄
談?wù)勀銓?duì)AOF持久化的理解?
redis的三種寫回策略是什么?
談?wù)勀銓?duì)AOF重寫機(jī)制的理解?AOF重寫機(jī)制的具體過(guò)程?
談?wù)勀銓?duì)RDB快照的理解?怎么觸發(fā)RDB?
redis大key對(duì)持久化有什么影響?
如何用redis實(shí)現(xiàn)分布式鎖?基于 Redis 實(shí)現(xiàn)分布式鎖的優(yōu)點(diǎn)與缺點(diǎn)?
數(shù)據(jù)庫(kù)和緩存如何保持一致性?
談?wù)勀銓?duì)AOF持久化的理解?
- Redis每執(zhí)行一次寫操作命令,就會(huì)以追加的方式寫入到一個(gè)文件里,這個(gè)文件就叫做AOF日志,當(dāng)redis重啟時(shí),再去執(zhí)行這個(gè)文件中的命令,就相當(dāng)于做了數(shù)據(jù)恢復(fù)。將寫操作命令寫入到日志文件的過(guò)程就是redis的AOF持久化過(guò)程。
值得注意的是,redis只會(huì)記錄寫操作,讀操作不會(huì)記錄;另外,redis是先執(zhí)行完寫操作命令,再將這個(gè)命令記錄到日志中,這么做有兩點(diǎn)好處:
- 避免了額外的檢查開(kāi)銷,如果命令是錯(cuò)誤的,那么在執(zhí)行的時(shí)候就可以檢查出來(lái)了,不會(huì)往日志中記錄一條錯(cuò)誤命令
- 不會(huì)阻塞當(dāng)前命令的執(zhí)行
但是也有兩點(diǎn)壞處:
- 如果redis在執(zhí)行這條寫命令的時(shí)候,redis發(fā)生故障宕機(jī),也就是還沒(méi)來(lái)得及將這條命令寫入到日志中,所以就會(huì)造成數(shù)據(jù)丟失
- 可能會(huì)阻塞下一條命令的執(zhí)行
redis的三種寫回策略是什么?
AOF日志中的命令還并沒(méi)有被同步到硬盤,此時(shí)這些命令還存在于server.aof_buf緩沖區(qū)中
AOF具體有三種寫回策略:
- always:命令寫入aof_buf之后就立即調(diào)用fsync函數(shù),將AOF數(shù)據(jù)同步到硬盤。可靠性高,最大程度保證數(shù)據(jù)不會(huì)丟失,但是性能開(kāi)銷比較大
- no:命令寫入aof_buf之后先將命令寫入到AOF文件的內(nèi)核緩沖區(qū),不對(duì)AOF文件做fsync同步,同步硬盤操作由操作系統(tǒng)負(fù)責(zé)。性能好,但是如果宕機(jī)會(huì)丟失很多數(shù)據(jù)
- everysec:命令寫入aof_buf之后,先將命令寫入到AOF文件的內(nèi)核緩沖區(qū),然后每隔一秒調(diào)用一次fsync函數(shù),將內(nèi)核緩沖區(qū)中的數(shù)據(jù)同步到硬盤。性能適中,redis宕機(jī)會(huì)丟失一秒內(nèi)的數(shù)據(jù)
談?wù)勀銓?duì)AOF重寫機(jī)制的理解?AOF重寫機(jī)制的具體過(guò)程?
隨著執(zhí)行命令的增多,AOF文件中的命令也越來(lái)越多,AOF文件的體積也會(huì)越來(lái)越大,AOF重寫機(jī)制的目的就是為了壓縮AOF文件的體積。
AOF重寫機(jī)制的妙處就在于,它會(huì)讀取數(shù)據(jù)庫(kù)中的最新數(shù)據(jù),然后僅用一條命令來(lái)記錄這條數(shù)據(jù);也就是說(shuō),如果在之前,這條記錄被多次修改過(guò),也就意味著有多條修改命令,那么只需要記錄最后一條修改不就行了嗎?這樣就減少了命令的數(shù)量,AOF重寫機(jī)制會(huì)把這些最新的命令寫入到一個(gè)新的AOF文件中,然后覆蓋掉原有的AOF文件。
因?yàn)锳OF重寫過(guò)程比較耗時(shí),所以一般不會(huì)在主進(jìn)程中執(zhí)行
開(kāi)啟AOF重寫機(jī)制之后,主進(jìn)程會(huì)fork出一個(gè)子進(jìn)程,由子進(jìn)程來(lái)執(zhí)行AOF重寫。
這樣做的好處有兩點(diǎn):
- 重寫過(guò)程由子進(jìn)程來(lái)執(zhí)行,主進(jìn)程依舊可以相應(yīng)客戶端命令
- 主進(jìn)程和子進(jìn)程共用一份頁(yè)表,即主進(jìn)程和子進(jìn)程共用一塊物理內(nèi)存
缺點(diǎn):
- 主進(jìn)程在fork子進(jìn)程的時(shí)候,由于要復(fù)制一份頁(yè)表給子進(jìn)程,所以會(huì)造成主進(jìn)程阻塞
- 另外,當(dāng)主進(jìn)程或者子進(jìn)程修改共享數(shù)據(jù)時(shí),會(huì)發(fā)生寫時(shí)復(fù)制,內(nèi)核會(huì)將物理內(nèi)存再拷貝一份,也會(huì)造成主進(jìn)程的阻塞
談?wù)勀銓?duì)RDB快照的理解?怎么觸發(fā)RDB?
RDB快照記錄了某一瞬間內(nèi)存中的數(shù)據(jù),所以RDB文件記錄的是實(shí)際的數(shù)據(jù),而AOF日志記錄的是一條條命令。使用RDB來(lái)進(jìn)行數(shù)據(jù)恢復(fù)的效率要高于AOF,所以RDB是redis的默認(rèn)持久化方式。
觸發(fā)機(jī)制:兩條命令,save和bgsave
- save:阻塞當(dāng)前redis服務(wù)器,直到RDB過(guò)程結(jié)束
- bgsave:主進(jìn)程fork出一個(gè)子進(jìn)程,阻塞只發(fā)生在fork階段,一般時(shí)間很短
redis大key對(duì)持久化有什么影響?
大key對(duì)AOF日志的影響:
- 使用always策略:主線程在執(zhí)行fsync函數(shù)時(shí),阻塞的時(shí)間比較久
- 使用no策略:由于永遠(yuǎn)不會(huì)執(zhí)行fsync函數(shù),所以不會(huì)影響主線程
- 使用everysec策略:由于是異步執(zhí)行fsync函數(shù),所以大key持久化的過(guò)程不會(huì)影響主線程
大key對(duì)AOF重寫和RDB的影響:
- 創(chuàng)建子進(jìn)程的過(guò)程中父進(jìn)程會(huì)發(fā)生阻塞,因?yàn)樽舆M(jìn)程要復(fù)制父進(jìn)程的頁(yè)表等數(shù)據(jù)結(jié)構(gòu)
- 創(chuàng)建完子進(jìn)程之后父進(jìn)程也會(huì)發(fā)生阻塞,如果父進(jìn)程對(duì)大key做了修改,那么內(nèi)核就會(huì)發(fā)生寫時(shí)復(fù)制,會(huì)把物理內(nèi)存復(fù)制一份,由于大key占用的物理內(nèi)存比較大,那么在復(fù)制物理內(nèi)存的時(shí)候就會(huì)很耗時(shí),就會(huì)阻塞父進(jìn)程
如何用redis實(shí)現(xiàn)分布式鎖?基于 Redis 實(shí)現(xiàn)分布式鎖的優(yōu)點(diǎn)與缺點(diǎn)?
分布式鎖主要應(yīng)用于并發(fā)環(huán)境下,保證某個(gè)資源在同一時(shí)刻只能被某一個(gè)用戶所使用
使用 redis 中的 SET NX命令實(shí)現(xiàn)分布式鎖
SET lock_key unique_value NX PX 10000?
在設(shè)置鎖的時(shí)候,需要滿足兩個(gè)條件:
- 需要對(duì)鎖設(shè)置過(guò)期時(shí)間,避免鎖被獲取之后發(fā)生異常,導(dǎo)致客戶端無(wú)法釋放鎖
- 鎖變量的值需要能夠區(qū)分出不同的用戶
優(yōu)點(diǎn):
- 性能高效、實(shí)現(xiàn)方便(使用SET NX命令)
缺點(diǎn):
- 超時(shí)時(shí)間不好設(shè)置:如果設(shè)置的時(shí)間太長(zhǎng),那么會(huì)影響性能;如果設(shè)置的時(shí)間太短,起不到互斥的作用
- 可能存在不可靠性:redis基于集群分布的,且主從復(fù)制的過(guò)程是異步的,可能在redis主節(jié)點(diǎn)獲取到鎖之后,主節(jié)點(diǎn)宕機(jī),還沒(méi)來(lái)得及同步,所以在新的redis主節(jié)點(diǎn)上依舊可以重新獲取鎖
數(shù)據(jù)庫(kù)和緩存如何保持一致性?
如果先更新數(shù)據(jù)庫(kù),再更新緩存:
此時(shí),數(shù)據(jù)庫(kù)中的值是2,而緩存中的值是1,出現(xiàn)了數(shù)據(jù)庫(kù)和緩存中的數(shù)據(jù)不一致的現(xiàn)象!?
如果先更新緩存,再更新數(shù)據(jù)庫(kù):
此時(shí),緩存中的值是2,數(shù)據(jù)庫(kù)中的值是1,依舊出現(xiàn)了數(shù)據(jù)庫(kù)和緩存中的數(shù)據(jù)不一致的現(xiàn)象!?
如果先刪除緩存,再更新數(shù)據(jù)庫(kù):
?這種情況下,讀請(qǐng)求和寫請(qǐng)求并發(fā)的情況下,出現(xiàn)了數(shù)據(jù)庫(kù)和緩存中的數(shù)據(jù)不一致的問(wèn)題!
如果先更新數(shù)據(jù)庫(kù),再刪除緩存:
?如果但從理論上分析,上述情況依舊導(dǎo)致了數(shù)據(jù)不一致的問(wèn)題,但是,值得注意的是,在實(shí)際中,這種情況出現(xiàn)的概率并不高,因?yàn)閷懢彺娴乃俣纫煊趯憯?shù)據(jù)庫(kù)的速度
所以,先更新數(shù)據(jù)庫(kù),再刪除緩存這種方案是可行的。
但是,繼續(xù)分析,更新數(shù)據(jù)庫(kù)和刪除緩存,這是兩種操作,如果更新數(shù)據(jù)庫(kù)成功了,但是刪除緩存的時(shí)候失敗了,那么緩存中緩存的就是舊值,數(shù)據(jù)庫(kù)中存放的是新值。怎么保證這兩個(gè)操作都能順利執(zhí)行呢?
解決方案有兩種:
重試機(jī)制:將要操作的數(shù)據(jù)加入到消息隊(duì)列,如果刪除緩存失敗,那么就重新讀取消息,重新執(zhí)行刪除緩存操作;如果刪除緩存成功了,就將消息從消息隊(duì)列中移除。
訂閱MySQL binlog:在更新數(shù)據(jù)庫(kù)時(shí),會(huì)產(chǎn)生一條bin log日志,如果刪除緩存失敗,就從bin log中拿到具體操作的數(shù)據(jù),進(jìn)行重新刪除
?整理面經(jīng)不易,覺(jué)得有幫助的小伙伴點(diǎn)個(gè)贊吧~感謝收看!