欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

2021年最新Redis面試題匯總(2)

 更新時(shí)間:2021年07月15日 17:31:08   作者:java李楊勇  
在程序員面試過程中redis相關(guān)的知識(shí)是常被問到的話題。這篇文章主要介紹了幾道Redis面試題,整理一下分享給大家,感興趣的小伙伴們可以參考一下

1、漸進(jìn)式 rehash 的優(yōu)點(diǎn)

漸進(jìn)式 rehash 的好處在于它采取分而治之的方式,將 rehash 鍵值對(duì)所需的計(jì)算工作均攤到對(duì)字典的每個(gè)添加、刪除、查找和更新操作上,從而避免了集中式 rehash 而帶來的龐大計(jì)算量。

在進(jìn)行漸進(jìn)式 rehash 的過程中,字典會(huì)同時(shí)使用 ht[0] 和 ht[1] 兩個(gè)哈希表, 所以在漸進(jìn)式 rehash 進(jìn)行期間,字典的刪除、査找、更新等操作會(huì)在兩個(gè)哈希表上進(jìn)行。例如,要在字典里面査找一個(gè)鍵的話,程序會(huì)先在 ht[0] 里面進(jìn)行査找,如果沒找到的話,就會(huì)繼續(xù)到 ht[1] 里面進(jìn)行査找,諸如此類。

另外,在漸進(jìn)式 rehash 執(zhí)行期間,新增的鍵值對(duì)會(huì)被直接保存到 ht[1], ht[0] 不再進(jìn)行任何添加操作,這樣就保證了 ht[0] 包含的鍵值對(duì)數(shù)量會(huì)只減不增,并隨著 rehash 操作的執(zhí)行而最終變成空表。

2、rehash 流程在數(shù)據(jù)量大的時(shí)候會(huì)有什么問題嗎(Hash 對(duì)象的擴(kuò)容流程在數(shù)據(jù)量大的時(shí)候會(huì)有什么問題嗎)

1)擴(kuò)容期開始時(shí),會(huì)先給 ht[1] 申請(qǐng)空間,所以在整個(gè)擴(kuò)容期間,會(huì)同時(shí)存在 ht[0] 和 ht[1],會(huì)占用額外的空間。

2)擴(kuò)容期間同時(shí)存在 ht[0] 和 ht[1],查找、刪除、更新等操作有概率需要操作兩張表,耗時(shí)會(huì)增加。

3)redis 在內(nèi)存使用接近 maxmemory 并且有設(shè)置驅(qū)逐策略的情況下,出現(xiàn) rehash 會(huì)使得內(nèi)存占用超過 maxmemory,觸發(fā)驅(qū)逐淘汰操作,導(dǎo)致 master/slave 均有有大量的 key 被驅(qū)逐淘汰,從而出現(xiàn) master/slave 主從不一致。

3、Redis 的網(wǎng)絡(luò)事件處理器(Reactor 模式)

redis 基于 reactor 模式開發(fā)了自己的網(wǎng)絡(luò)事件處理器,由4個(gè)部分組成:套接字、I/O 多路復(fù)用程序、文件事件分派器(dispatcher)、以及事件處理器。

​套接字:socket 連接,也就是客戶端連接。當(dāng)一個(gè)套接字準(zhǔn)備好執(zhí)行連接、寫入、讀取、關(guān)閉等操作時(shí), 就會(huì)產(chǎn)生一個(gè)相應(yīng)的文件事件。因?yàn)橐粋€(gè)服務(wù)器通常會(huì)連接多個(gè)套接字, 所以多個(gè)文件事件有可能會(huì)并發(fā)地出現(xiàn)。

I/O 多路復(fù)用程序:提供 select、epoll、evport、kqueue 的實(shí)現(xiàn),會(huì)根據(jù)當(dāng)前系統(tǒng)自動(dòng)選擇最佳的方式。負(fù)責(zé)監(jiān)聽多個(gè)套接字,當(dāng)套接字產(chǎn)生事件時(shí),會(huì)向文件事件分派器傳送那些產(chǎn)生了事件的套接字。當(dāng)多個(gè)文件事件并發(fā)出現(xiàn)時(shí), I/O 多路復(fù)用程序會(huì)將所有產(chǎn)生事件的套接字都放到一個(gè)隊(duì)列里面,然后通過這個(gè)隊(duì)列,以有序、同步、每次一個(gè)套接字的方式向文件事件分派器傳送套接字:當(dāng)上一個(gè)套接字產(chǎn)生的事件被處理完畢之后,才會(huì)繼續(xù)傳送下一個(gè)套接字。

文件事件分派器:接收 I/O 多路復(fù)用程序傳來的套接字, 并根據(jù)套接字產(chǎn)生的事件的類型, 調(diào)用相應(yīng)的事件處理器。

事件處理器:事件處理器就是一個(gè)個(gè)函數(shù), 定義了某個(gè)事件發(fā)生時(shí), 服務(wù)器應(yīng)該執(zhí)行的動(dòng)作。例如:建立連接、命令查詢、命令寫入、連接關(guān)閉等等。

4、Redis 刪除過期鍵的策略(緩存失效策略、數(shù)據(jù)過期策略)

定時(shí)刪除:在設(shè)置鍵的過期時(shí)間的同時(shí),創(chuàng)建一個(gè)定時(shí)器,讓定時(shí)器在鍵的過期時(shí)間來臨時(shí),立即執(zhí)行對(duì)鍵的刪除操作。對(duì)內(nèi)存最友好,對(duì) CPU 時(shí)間最不友好。

惰性刪除:放任鍵過期不管,但是每次獲取鍵時(shí),都檢査鍵是否過期,如果過期的話,就刪除該鍵;如果沒有過期,就返回該鍵。對(duì) CPU 時(shí)間最優(yōu)化,對(duì)內(nèi)存最不友好。

定期刪除:每隔一段時(shí)間,默認(rèn)100ms,程序就對(duì)數(shù)據(jù)庫進(jìn)行一次檢査,刪除里面的過期鍵。至 于要?jiǎng)h除多少過期鍵,以及要檢査多少個(gè)數(shù)據(jù)庫,則由算法決定。前兩種策略的折中,對(duì) CPU 時(shí)間和內(nèi)存的友好程度較平衡。

Redis 使用惰性刪除和定期刪除。

5、Redis 的內(nèi)存淘汰(驅(qū)逐)策略

當(dāng) redis 的內(nèi)存空間(maxmemory 參數(shù)配置)已經(jīng)用滿時(shí),redis 將根據(jù)配置的驅(qū)逐策略(maxmemory-policy 參數(shù)配置),進(jìn)行相應(yīng)的動(dòng)作。

網(wǎng)上很多資料都是寫 6 種,但是其實(shí)當(dāng)前 redis 的淘汰策略已經(jīng)有 8 種了,多余的兩種是 Redis 4.0 新增的,基于 LFU(Least Frequently Used)算法實(shí)現(xiàn)的。

  • noeviction:默認(rèn)策略,不淘汰任何 key,直接返回錯(cuò)誤
  • allkeys-lru:在所有的 key 中,使用 LRU 算法淘汰部分 key
  • allkeys-lfu:在所有的 key 中,使用 LFU 算法淘汰部分 key,該算法于 Redis 4.0 新增
  • allkeys-random:在所有的 key 中,隨機(jī)淘汰部分 key
  • volatile-lru:在設(shè)置了過期時(shí)間的 key 中,使用 LRU 算法淘汰部分 key
  • volatile-lfu:在設(shè)置了過期時(shí)間的 key 中,使用 LFU 算法淘汰部分 key,該算法于 Redis 4.0 新增
  • volatile-random:在設(shè)置了過期時(shí)間的 key 中,隨機(jī)淘汰部分 key
  • volatile-ttl:在設(shè)置了過期時(shí)間的 key 中,挑選 TTL(time to live,剩余時(shí)間)短的 key 淘汰

6、Redis 的 LRU 算法怎么實(shí)現(xiàn)的?

Redis 在 redisObject 結(jié)構(gòu)體中定義了一個(gè)長度 24 bit 的 unsigned 類型的字段(unsigned lru:LRU_BITS),在 LRU 算法中用來存儲(chǔ)對(duì)象最后一次被命令程序訪問的時(shí)間。

具體的 LRU 算法經(jīng)歷了兩個(gè)版本。

版本1:隨機(jī)選取 N 個(gè)淘汰法。

最初 Redis 是這樣實(shí)現(xiàn)的:隨機(jī)選 N(默認(rèn)5) 個(gè) key,把空閑時(shí)間(idle time)最大的那個(gè) key 移除。這邊的 N 可通過 maxmemory-samples 配置項(xiàng)修改。

就是這么簡單,簡單得讓人不敢相信了,而且十分有效。

但是這個(gè)算法有個(gè)明顯的缺點(diǎn):每次都是隨機(jī)從 N 個(gè)里選擇 1 個(gè),并沒有利用前一輪的歷史信息。其實(shí)在上一輪移除 key 的過程中,其實(shí)是知道了 N 個(gè) key 的 idle time 的情況的,那在下一輪移除 key 時(shí),其實(shí)可以利用上一輪的這些信息。這也是 Redis 3.0 的優(yōu)化思想。

版本2:Redis 3.0 對(duì) LRU 算法進(jìn)行改進(jìn),引入了緩沖池(pool,默認(rèn)16)的概念。

當(dāng)每一輪移除 key 時(shí),拿到了 N(默認(rèn)5)個(gè) key 的 idle time,遍歷處理這 N 個(gè) key,如果 key 的 idle time 比 pool 里面的 key 的 idle time 還要大,就把它添加到 pool 里面去。

當(dāng) pool 放滿之后,每次如果有新的 key 需要放入,需要將 pool 中 idle time 最小的一個(gè) key 移除。這樣相當(dāng)于 pool 里面始終維護(hù)著還未被淘汰的 idle time 最大的 16 個(gè) key。

當(dāng)我們每輪要淘汰的時(shí)候,直接從 pool 里面取出 idle time 最大的 key(只取1個(gè)),將之淘汰掉。

整個(gè)流程相當(dāng)于隨機(jī)取 5 個(gè) key 放入 pool,然后淘汰 pool 中空閑時(shí)間最大的 key,然后再隨機(jī)取 5 個(gè) key放入 pool,繼續(xù)淘汰 pool 中空閑時(shí)間最大的 key,一直持續(xù)下去。

在進(jìn)入淘汰前會(huì)計(jì)算出需要釋放的內(nèi)存大小,然后就一直循環(huán)上述流程,直至釋放足夠的內(nèi)存。

7、Redis 的持久化機(jī)制有哪幾種,各自的實(shí)現(xiàn)原理和優(yōu)缺點(diǎn)?

Redis 的持久化機(jī)制有:RDB、AOF、混合持久化(RDB+AOF,Redis 4.0引入)。

1)RDB

描述:類似于快照。在某個(gè)時(shí)間點(diǎn),將 Redis 在內(nèi)存中的數(shù)據(jù)庫狀態(tài)(數(shù)據(jù)庫的鍵值對(duì)等信息)保存到磁盤里面。RDB 持久化功能生成的 RDB 文件是經(jīng)過壓縮的二進(jìn)制文件。

命令:有兩個(gè) Redis 命令可以用于生成 RDB 文件,一個(gè)是 SAVE,另一個(gè)是 BGSAVE。

開啟:使用 save point 配置,滿足 save point 條件后會(huì)觸發(fā) BGSAVE 來存儲(chǔ)一次快照,這邊的 save point 檢查就是在上文提到的 serverCron 中進(jìn)行。

save point 格式:save <seconds> <changes>,含義是 Redis 如果在 seconds 秒內(nèi)數(shù)據(jù)發(fā)生了 changes 次改變,就保存快照文件。例如 Redis 默認(rèn)就配置了以下3個(gè):

save 900 1 #900秒內(nèi)有1個(gè)key發(fā)生了變化,則觸發(fā)保存RDB文件 save 300 10 #300秒內(nèi)有10個(gè)key發(fā)生了變化,則觸發(fā)保存RDB文件 save 60 10000 #60秒內(nèi)有10000個(gè)key發(fā)生了變化,則觸發(fā)保存RDB文件

關(guān)閉:1)注釋掉所有save point 配置可以關(guān)閉 RDB 持久化。2)在所有 save point 配置后增加:save "",該配置可以刪除所有之前配置的 save point。

save ""

SAVE:生成 RDB 快照文件,但是會(huì)阻塞主進(jìn)程,服務(wù)器將無法處理客戶端發(fā)來的命令請(qǐng)求,所以通常不會(huì)直接使用該命令。

BGSAVE:fork 子進(jìn)程來生成 RDB 快照文件,阻塞只會(huì)發(fā)生在 fork 子進(jìn)程的時(shí)候,之后主進(jìn)程可以正常處理請(qǐng)求,詳細(xì)過程如下圖:

​fork:在 Linux 系統(tǒng)中,調(diào)用 fork() 時(shí),會(huì)創(chuàng)建出一個(gè)新進(jìn)程,稱為子進(jìn)程,子進(jìn)程會(huì)拷貝父進(jìn)程的 page table。如果進(jìn)程占用的內(nèi)存越大,進(jìn)程的 page table 也會(huì)越大,那么 fork 也會(huì)占用更多的時(shí)間。如果 Redis 占用的內(nèi)存很大,那么在 fork 子進(jìn)程時(shí),則會(huì)出現(xiàn)明顯的停頓現(xiàn)象。

RDB 的優(yōu)點(diǎn)

1)RDB 文件是是經(jīng)過壓縮的二進(jìn)制文件,占用空間很小,它保存了 Redis 某個(gè)時(shí)間點(diǎn)的數(shù)據(jù)集,很適合用于做備份。 比如說,你可以在最近的 24 小時(shí)內(nèi),每小時(shí)備份一次 RDB 文件,并且在每個(gè)月的每一天,也備份一個(gè) RDB 文件。這樣的話,即使遇上問題,也可以隨時(shí)將數(shù)據(jù)集還原到不同的版本。

2)RDB 非常適用于災(zāi)難恢復(fù)(disaster recovery):它只有一個(gè)文件,并且內(nèi)容都非常緊湊,可以(在加密后)將它傳送到別的數(shù)據(jù)中心。

3)RDB 可以最大化 redis 的性能。父進(jìn)程在保存 RDB 文件時(shí)唯一要做的就是 fork 出一個(gè)子進(jìn)程,然后這個(gè)子進(jìn)程就會(huì)處理接下來的所有保存工作,父進(jìn)程無須執(zhí)行任何磁盤 I/O 操作。

4)RDB 在恢復(fù)大數(shù)據(jù)集時(shí)的速度比 AOF 的恢復(fù)速度要快。

RDB 的缺點(diǎn)

1)RDB 在服務(wù)器故障時(shí)容易造成數(shù)據(jù)的丟失。RDB 允許我們通過修改 save point 配置來控制持久化的頻率。但是,因?yàn)?RDB 文件需要保存整個(gè)數(shù)據(jù)集的狀態(tài), 所以它是一個(gè)比較重的操作,如果頻率太頻繁,可能會(huì)對(duì) Redis 性能產(chǎn)生影響。所以通??赡茉O(shè)置至少5分鐘才保存一次快照,這時(shí)如果 Redis 出現(xiàn)宕機(jī)等情況,則意味著最多可能丟失5分鐘數(shù)據(jù)。

2)RDB 保存時(shí)使用 fork 子進(jìn)程進(jìn)行數(shù)據(jù)的持久化,如果數(shù)據(jù)比較大的話,fork 可能會(huì)非常耗時(shí),造成 Redis 停止處理服務(wù)N毫秒。如果數(shù)據(jù)集很大且 CPU 比較繁忙的時(shí)候,停止服務(wù)的時(shí)間甚至?xí)揭幻搿?/p>

3)Linux fork 子進(jìn)程采用的是 copy-on-write 的方式。在 Redis 執(zhí)行 RDB 持久化期間,如果 client 寫入數(shù)據(jù)很頻繁,那么將增加 Redis 占用的內(nèi)存,最壞情況下,內(nèi)存的占用將達(dá)到原先的2倍。剛 fork 時(shí),主進(jìn)程和子進(jìn)程共享內(nèi)存,但是隨著主進(jìn)程需要處理寫操作,主進(jìn)程需要將修改的頁面拷貝一份出來,然后進(jìn)行修改。極端情況下,如果所有的頁面都被修改,則此時(shí)的內(nèi)存占用是原先的2倍。

2)AOF

描述:保存 Redis 服務(wù)器所執(zhí)行的所有寫操作命令來記錄數(shù)據(jù)庫狀態(tài),并在服務(wù)器啟動(dòng)時(shí),通過重新執(zhí)行這些命令來還原數(shù)據(jù)集。

開啟:AOF 持久化默認(rèn)是關(guān)閉的,可以通過配置:appendonly yes 開啟。

關(guān)閉:使用配置 appendonly no 可以關(guān)閉 AOF 持久化。

AOF 持久化功能的實(shí)現(xiàn)可以分為三個(gè)步驟:命令追加、文件寫入、文件同步。

命令追加:當(dāng) AOF 持久化功能打開時(shí),服務(wù)器在執(zhí)行完一個(gè)寫命令之后,會(huì)將被執(zhí)行的寫命令追加到服務(wù)器狀態(tài)的 aof 緩沖區(qū)(aof_buf)的末尾。

文件寫入與文件同步:可能有人不明白為什么將 aof_buf 的內(nèi)容寫到磁盤上需要兩步操作,這邊簡單解釋一下。

Linux 操作系統(tǒng)中為了提升性能,使用了頁緩存(page cache)。當(dāng)我們將 aof_buf 的內(nèi)容寫到磁盤上時(shí),此時(shí)數(shù)據(jù)并沒有真正的落盤,而是在 page cache 中,為了將 page cache 中的數(shù)據(jù)真正落盤,需要執(zhí)行 fsync / fdatasync 命令來強(qiáng)制刷盤。這邊的文件同步做的就是刷盤操作,或者叫文件刷盤可能更容易理解一些。

在文章開頭,我們提過 serverCron 時(shí)間事件中會(huì)觸發(fā) flushAppendOnlyFile 函數(shù),該函數(shù)會(huì)根據(jù)服務(wù)器配置的 appendfsync 參數(shù)值,來決定是否將 aof_buf 緩沖區(qū)的內(nèi)容寫入和保存到 AOF 文件。

appendfsync 參數(shù)有三個(gè)選項(xiàng):

  • always:每處理一個(gè)命令都將 aof_buf 緩沖區(qū)中的所有內(nèi)容寫入并同步到AOF 文件,即每個(gè)命令都刷盤。
  • everysec:將 aof_buf 緩沖區(qū)中的所有內(nèi)容寫入到 AOF 文件,如果上次同步 AOF 文件的時(shí)間距離現(xiàn)在超過一秒鐘, 那么再次對(duì) AOF 文件進(jìn)行同步, 并且這個(gè)同步操作是異步的,由一個(gè)后臺(tái)線程專門負(fù)責(zé)執(zhí)行,即每秒刷盤1次。
  • no:將 aof_buf 緩沖區(qū)中的所有內(nèi)容寫入到 AOF 文件, 但并不對(duì) AOF 文件進(jìn)行同步, 何時(shí)同步由操作系統(tǒng)來決定。即不執(zhí)行刷盤,讓操作系統(tǒng)自己執(zhí)行刷盤。

AOF 的優(yōu)點(diǎn)

  • AOF 比 RDB可靠。你可以設(shè)置不同的 fsync 策略:no、everysec 和 always。默認(rèn)是 everysec,在這種配置下,redis 仍然可以保持良好的性能,并且就算發(fā)生故障停機(jī),也最多只會(huì)丟失一秒鐘的數(shù)據(jù)。
  • AOF文件是一個(gè)純追加的日志文件。即使日志因?yàn)槟承┰蚨宋磳懭胪暾拿睿ū热鐚懭霑r(shí)磁盤已滿,寫入中途停機(jī)等等), 我們也可以使用 redis-check-aof 工具也可以輕易地修復(fù)這種問題。
  • 當(dāng) AOF文件太大時(shí),Redis 會(huì)自動(dòng)在后臺(tái)進(jìn)行重寫:重寫后的新 AOF 文件包含了恢復(fù)當(dāng)前數(shù)據(jù)集所需的最小命令集合。整個(gè)重寫是絕對(duì)安全,因?yàn)橹貙懯窃谝粋€(gè)新的文件上進(jìn)行,同時(shí) Redis 會(huì)繼續(xù)往舊的文件追加數(shù)據(jù)。當(dāng)新文件重寫完畢,Redis 會(huì)把新舊文件進(jìn)行切換,然后開始把數(shù)據(jù)寫到新文件上。
  • AOF 文件有序地保存了對(duì)數(shù)據(jù)庫執(zhí)行的所有寫入操作以 Redis 協(xié)議的格式保存, 因此 AOF 文件的內(nèi)容非常容易被人讀懂, 對(duì)文件進(jìn)行分析(parse)也很輕松。如果你不小心執(zhí)行了 FLUSHALL 命令把所有數(shù)據(jù)刷掉了,但只要 AOF 文件沒有被重寫,那么只要停止服務(wù)器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重啟 Redis , 就可以將數(shù)據(jù)集恢復(fù)到 FLUSHALL 執(zhí)行之前的狀態(tài)。

AOF 的缺點(diǎn)

  • 對(duì)于相同的數(shù)據(jù)集,AOF 文件的大小一般會(huì)比 RDB 文件大。
  • 根據(jù)所使用的 fsync 策略,AOF 的速度可能會(huì)比 RDB 慢。通常 fsync 設(shè)置為每秒一次就能獲得比較高的性能,而關(guān)閉 fsync 可以讓 AOF 的速度和 RDB 一樣快。
  • AOF 在過去曾經(jīng)發(fā)生過這樣的 bug :因?yàn)閭€(gè)別命令的原因,導(dǎo)致 AOF 文件在重新載入時(shí),無法將數(shù)據(jù)集恢復(fù)成保存時(shí)的原樣。(舉個(gè)例子,阻塞命令 BRPOPLPUSH 就曾經(jīng)引起過這樣的 bug ) 。雖然這種 bug 在 AOF 文件中并不常見, 但是相較而言, RDB 幾乎是不可能出現(xiàn)這種 bug 的。

3)混合持久化

描述:混合持久化并不是一種全新的持久化方式,而是對(duì)已有方式的優(yōu)化?;旌铣志没话l(fā)生于 AOF 重寫過程。使用了混合持久化,重寫后的新 AOF 文件前半段是 RDB 格式的全量數(shù)據(jù),后半段是 AOF 格式的增量數(shù)據(jù)。

整體格式為:[RDB file][AOF tail]

開啟:混合持久化的配置參數(shù)為 aof-use-rdb-preamble,配置為 yes 時(shí)開啟混合持久化,在 redis 4 剛引入時(shí),默認(rèn)是關(guān)閉混合持久化的,但是在 redis 5 中默認(rèn)已經(jīng)打開了。

關(guān)閉:使用 aof-use-rdb-preamble no 配置即可關(guān)閉混合持久化。

混合持久化本質(zhì)是通過 AOF 后臺(tái)重寫(bgrewriteaof 命令)完成的,不同的是當(dāng)開啟混合持久化時(shí),fork 出的子進(jìn)程先將當(dāng)前全量數(shù)據(jù)以 RDB 方式寫入新的 AOF 文件,然后再將 AOF 重寫緩沖區(qū)(aof_rewrite_buf_blocks)的增量命令以 AOF 方式寫入到文件,寫入完成后通知主進(jìn)程將新的含有 RDB 格式和 AOF 格式的 AOF 文件替換舊的的 AOF 文件。

優(yōu)點(diǎn):結(jié)合 RDB 和 AOF 的優(yōu)點(diǎn), 更快的重寫和恢復(fù)。

缺點(diǎn):AOF 文件里面的 RDB 部分不再是 AOF 格式,可讀性差。

8、為什么需要 AOF 重寫

AOF 持久化是通過保存被執(zhí)行的寫命令來記錄數(shù)據(jù)庫狀態(tài)的,隨著寫入命令的不斷增加,AOF 文件中的內(nèi)容會(huì)越來越多,文件的體積也會(huì)越來越大。

如果不加以控制,體積過大的 AOF 文件可能會(huì)對(duì) Redis 服務(wù)器、甚至整個(gè)宿主機(jī)造成影響,并且 AOF 文件的體積越大,使用 AOF 文件來進(jìn)行數(shù)據(jù)還原所需的時(shí)間就越多。

舉個(gè)例子, 如果你對(duì)一個(gè)計(jì)數(shù)器調(diào)用了 100 次 INCR , 那么僅僅是為了保存這個(gè)計(jì)數(shù)器的當(dāng)前值, AOF 文件就需要使用 100 條記錄。

然而在實(shí)際上, 只使用一條 SET 命令已經(jīng)足以保存計(jì)數(shù)器的當(dāng)前值了, 其余 99 條記錄實(shí)際上都是多余的。

為了處理這種情況, Redis 引入了 AOF 重寫:可以在不打斷服務(wù)端處理請(qǐng)求的情況下, 對(duì) AOF 文件進(jìn)行重建(rebuild)。

9、介紹下 AOF 重寫的過程、AOF 后臺(tái)重寫存在的問題、如何解決 AOF 后臺(tái)重寫存在的數(shù)據(jù)不一致問題

描述:Redis 生成新的 AOF 文件來代替舊 AOF 文件,這個(gè)新的 AOF 文件包含重建當(dāng)前數(shù)據(jù)集所需的最少命令。具體過程是遍歷所有數(shù)據(jù)庫的所有鍵,從數(shù)據(jù)庫讀取鍵現(xiàn)在的值,然后用一條命令去記錄鍵值對(duì),代替之前記錄這個(gè)鍵值對(duì)的多條命令。

命令:有兩個(gè) Redis 命令可以用于觸發(fā) AOF 重寫,一個(gè)是 BGREWRITEAOF 、另一個(gè)是 REWRITEAOF 命令;

開啟:AOF 重寫由兩個(gè)參數(shù)共同控制,auto-aof-rewrite-percentage 和 auto-aof-rewrite-min-size,同時(shí)滿足這兩個(gè)條件,則觸發(fā) AOF 后臺(tái)重寫 BGREWRITEAOF。

// 當(dāng)前AOF文件比上次重寫后的AOF文件大小的增長比例超過100 auto-aof-rewrite-percentage 100 // 當(dāng)前AOF文件的文件大小大于64MB auto-aof-rewrite-min-size 64mb

關(guān)閉:auto-aof-rewrite-percentage 0,指定0的百分比,以禁用自動(dòng)AOF重寫功能。

auto-aof-rewrite-percentage 0

REWRITEAOF:進(jìn)行 AOF 重寫,但是會(huì)阻塞主進(jìn)程,服務(wù)器將無法處理客戶端發(fā)來的命令請(qǐng)求,通常不會(huì)直接使用該命令。

BGREWRITEAOF:fork 子進(jìn)程來進(jìn)行 AOF 重寫,阻塞只會(huì)發(fā)生在 fork 子進(jìn)程的時(shí)候,之后主進(jìn)程可以正常處理請(qǐng)求。

REWRITEAOF 和 BGREWRITEAOF 的關(guān)系與 SAVE 和 BGSAVE 的關(guān)系類似。

AOF 后臺(tái)重寫存在的問題

AOF 后臺(tái)重寫使用子進(jìn)程進(jìn)行從寫,解決了主進(jìn)程阻塞的問題,但是仍然存在另一個(gè)問題:子進(jìn)程在進(jìn)行 AOF 重寫期間,服務(wù)器主進(jìn)程還需要繼續(xù)處理命令請(qǐng)求,新的命令可能會(huì)對(duì)現(xiàn)有的數(shù)據(jù)庫狀態(tài)進(jìn)行修改,從而使得當(dāng)前的數(shù)據(jù)庫狀態(tài)和重寫后的 AOF 文件保存的數(shù)據(jù)庫狀態(tài)不一致。

如何解決 AOF 后臺(tái)重寫存在的數(shù)據(jù)不一致問題

為了解決上述問題,Redis 引入了 AOF 重寫緩沖區(qū)(aof_rewrite_buf_blocks),這個(gè)緩沖區(qū)在服務(wù)器創(chuàng)建子進(jìn)程之后開始使用,當(dāng) Redis 服務(wù)器執(zhí)行完一個(gè)寫命令之后,它會(huì)同時(shí)將這個(gè)寫命令追加到 AOF 緩沖區(qū)和 AOF 重寫緩沖區(qū)。

這樣一來可以保證:

1、現(xiàn)有 AOF 文件的處理工作會(huì)如常進(jìn)行。這樣即使在重寫的中途發(fā)生停機(jī),現(xiàn)有的 AOF 文件也還是安全的。

2、從創(chuàng)建子進(jìn)程開始,也就是 AOF 重寫開始,服務(wù)器執(zhí)行的所有寫命令會(huì)被記錄到 AOF 重寫緩沖區(qū)里面。

這樣,當(dāng)子進(jìn)程完成 AOF 重寫工作后,父進(jìn)程會(huì)在 serverCron 中檢測(cè)到子進(jìn)程已經(jīng)重寫結(jié)束,則會(huì)執(zhí)行以下工作:

1、將 AOF 重寫緩沖區(qū)中的所有內(nèi)容寫入到新 AOF 文件中,這時(shí)新 AOF 文件所保存的數(shù)據(jù)庫狀態(tài)將和服務(wù)器當(dāng)前的數(shù)據(jù)庫狀態(tài)一致。

2、對(duì)新的 AOF 文件進(jìn)行改名,原子的覆蓋現(xiàn)有的 AOF 文件,完成新舊兩個(gè) AOF 文件的替換。

之后,父進(jìn)程就可以繼續(xù)像往常一樣接受命令請(qǐng)求了。

10、RDB、AOF、混合持久,我應(yīng)該用哪一個(gè)?

一般來說, 如果想盡量保證數(shù)據(jù)安全性, 你應(yīng)該同時(shí)使用 RDB 和 AOF 持久化功能,同時(shí)可以開啟混合持久化。

如果你非常關(guān)心你的數(shù)據(jù), 但仍然可以承受數(shù)分鐘以內(nèi)的數(shù)據(jù)丟失, 那么你可以只使用 RDB 持久化。

如果你的數(shù)據(jù)是可以丟失的,則可以關(guān)閉持久化功能,在這種情況下,Redis 的性能是最高的。

使用 Redis 通常都是為了提升性能,而如果為了不丟失數(shù)據(jù)而將 appendfsync 設(shè)置為 always 級(jí)別時(shí),對(duì) Redis 的性能影響是很大的,在這種不能接受數(shù)據(jù)丟失的場(chǎng)景,其實(shí)可以考慮直接選擇 MySQL 等類似的數(shù)據(jù)庫。

11、同時(shí)開啟RDB和AOF,服務(wù)重啟時(shí)如何加載

簡單來說,如果同時(shí)啟用了 AOF 和 RDB,Redis 重新啟動(dòng)時(shí),會(huì)使用 AOF 文件來重建數(shù)據(jù)集,因?yàn)橥ǔ碚f, AOF 的數(shù)據(jù)會(huì)更完整。

而在引入了混合持久化之后,使用 AOF 重建數(shù)據(jù)集時(shí),會(huì)通過文件開頭是否為“REDIS”來判斷是否為混合持久化。

完整流程如下圖所示:

總結(jié)

本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

2021年最新Redis面試題匯總(1)

2021年最新Redis面試題匯總(3)

2021年最新Redis面試題匯總(4)

相關(guān)文章

  • SpringBoot集成Caffeine緩存的實(shí)現(xiàn)步驟

    SpringBoot集成Caffeine緩存的實(shí)現(xiàn)步驟

    Caffeine cache是一個(gè)針對(duì)Java的高性能緩存庫。在本文中,我們將介紹它與Spring Boot如何一起使用。
    2021-05-05
  • SpringBoot JPA出現(xiàn)錯(cuò)誤:No identifier specified for en解決方案

    SpringBoot JPA出現(xiàn)錯(cuò)誤:No identifier specified&nb

    這篇文章主要介紹了SpringBoot JPA出現(xiàn)錯(cuò)誤:No identifier specified for en解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • MybatisPlus EntityWrapper如何自定義SQL

    MybatisPlus EntityWrapper如何自定義SQL

    這篇文章主要介紹了MybatisPlus EntityWrapper如何自定義SQL,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Spring Boot與ActiveMQ整合的步驟

    Spring Boot與ActiveMQ整合的步驟

    今天小編就為大家分享一篇關(guān)于Spring Boot與ActiveMQ整合的步驟,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • 使用Java實(shí)現(xiàn)創(chuàng)建Excel表單控件

    使用Java實(shí)現(xiàn)創(chuàng)建Excel表單控件

    在數(shù)據(jù)填報(bào)時(shí),創(chuàng)建Excel表單控件是一項(xiàng)常見的任務(wù),它可以極大地簡化數(shù)據(jù)收集和處理的過程,本文主要介紹了如何使用Java實(shí)現(xiàn)創(chuàng)建Excel表單控件,感興趣的可以了解下
    2024-03-03
  • 微信企業(yè)號(hào) 根據(jù)錯(cuò)誤碼返回錯(cuò)誤信息類封裝

    微信企業(yè)號(hào) 根據(jù)錯(cuò)誤碼返回錯(cuò)誤信息類封裝

    這篇文章主要介紹了微信企業(yè)號(hào) 根據(jù)錯(cuò)誤碼返回錯(cuò)誤信息類封裝的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • Spring框架 引入@Resource注解報(bào)空指針的解決

    Spring框架 引入@Resource注解報(bào)空指針的解決

    這篇文章主要介紹了Spring框架 引入@Resource注解報(bào)空指針的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • java 中 阻塞隊(duì)列BlockingQueue詳解及實(shí)例

    java 中 阻塞隊(duì)列BlockingQueue詳解及實(shí)例

    這篇文章主要介紹了java 中 阻塞隊(duì)列BlockingQueue詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • eclipse連接不到genymotion問題的解決方案

    eclipse連接不到genymotion問題的解決方案

    今天小編就為大家分享一篇關(guān)于eclipse連接不到genymotion問題的解決方案,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • ava實(shí)現(xiàn)一致性Hash算法

    ava實(shí)現(xiàn)一致性Hash算法

    本文主要詳細(xì)介紹了Java如何實(shí)現(xiàn)一致性Hash算法,其實(shí)現(xiàn)原理將key映射到?2^32?-?1?的空間中,將這個(gè)數(shù)字的首尾相連,形成一個(gè)環(huán)。想了解更多的同學(xué),可以參考本文
    2023-03-03

最新評(píng)論