自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

面試官拷打: Redis 高可用篇章中面試最常見的六個(gè)問題!

數(shù)據(jù)庫 Redis
Redis 有兩個(gè)方式實(shí)現(xiàn)了數(shù)據(jù)持久化,他們分別是 RDB 快照和 AOF(Append Only File)。RDB 內(nèi)存快照是全量持久化,AOF 做增量持久化。

大家好,我是碼哥,今天跟大家分享幾個(gè) Redis 高可用篇章中面試最常見的 6 個(gè)問題。

  1. Redis 如何實(shí)現(xiàn)持久化?
  2. Redis 高可用方案有哪些?
  3. 主從異步復(fù)制同步實(shí)現(xiàn)原理?
  4. sentinel 哨兵集群?
  5. Redis Cluster 是什么?
  6. 為什么集群的 slots 是 16384?

Redis 如何實(shí)現(xiàn)持久化?

Chaya 轉(zhuǎn)行做程序員,去大廠面試被面試官問到:“Redis 如何實(shí)現(xiàn)持久化?”

Chaya 心想:“好家伙,我學(xué)了碼哥的 Redis 高手心法,這不要起飛么,是時(shí)候展示真正的技術(shù)了?!?/p>

Redis 有兩個(gè)方式實(shí)現(xiàn)了數(shù)據(jù)持久化,他們分別是 RDB 快照和 AOF(Append Only File)。RDB 內(nèi)存快照是全量持久化,AOF 做增量持久化。

RDB 內(nèi)存快照

RDB內(nèi)存快照

bgsave 指令會(huì)調(diào)用 glibc 的函數(shù)fork產(chǎn)生一個(gè)子進(jìn)程用于寫入臨時(shí) RDB 文件,快照持久化完全交給子進(jìn)程來處理,完成后自動(dòng)結(jié)束,父進(jìn)程可以繼續(xù)處理客戶端請(qǐng)求,阻塞只發(fā)生在 fork 階段,時(shí)間很短,當(dāng)子進(jìn)程寫完新的 RDB 文件后,它會(huì)替換舊的 RDB 文件。

RDB 文件實(shí)時(shí)性不夠,宕機(jī)的時(shí)候可能會(huì)導(dǎo)致大量數(shù)據(jù)丟失。此外,fork 子進(jìn)程屬于重量級(jí)操作,執(zhí)行成本比較高,頻繁生成 RDB 文件,磁盤壓力也會(huì)過大。

AOF

AOF (Append Only File)持久化記錄的是服務(wù)器接收的每個(gè)寫操作,在服務(wù)器啟動(dòng)執(zhí)行重放還原數(shù)據(jù)集。由于 AOF 記錄的是一個(gè)個(gè)指令內(nèi)容,故障恢復(fù)的時(shí)候需要執(zhí)行每一個(gè)指令,如果日志文件太大,整個(gè)恢復(fù)過程就會(huì)非常緩慢。

AOF寫后日志

所以,還需配合 AOF 來使用。簡單來說,RDB 內(nèi)存快照以一定的頻率執(zhí)行,在兩次快照之間,使用 AOF 日志記錄這期間的所有寫操作。

如此一來,快照就不需要頻繁執(zhí)行,避免了 fork 對(duì)主線程的性能影響,AOF 不再是全量日志,而是生成 RDB 快照時(shí)間的增量 AOF 日志

面試官:“如果機(jī)器突然掉電會(huì)怎樣?”

Chaya 假裝思考一下,說道:“取決于 AOF 配置項(xiàng)appendfsync寫回策略。always同步寫回可以做到數(shù)據(jù)不丟失,但是每個(gè)寫指令都需要寫入磁盤,性能最差。

everysec每秒寫回,避免了同步寫回的性能開銷,發(fā)生宕機(jī)可能有一秒位寫入磁盤的數(shù)據(jù)丟失,在性能和可靠性之間做了折中?!?/p>

這時(shí)候,面試官心想這候選人,有點(diǎn)東西。

Chaya 繼續(xù)補(bǔ)充道:“為了避免 AOF 文件體積膨脹的問題,還有一個(gè) AOF 重寫機(jī)制對(duì)文件瘦身。在 7.0 版本還做了優(yōu)化,提出了 Multi-Part AOF 機(jī)制,因?yàn)樵?7.0 之前的版本中 AOF Rewrite 過程中,主進(jìn)程除了把寫指令寫到 AOF 緩沖區(qū)以外,還要寫到 AOF 重寫緩沖區(qū)中。一份數(shù)據(jù)要寫兩個(gè)緩沖區(qū),還要寫到兩個(gè) AOF 文件,產(chǎn)生兩次磁盤 I/O ,太浪費(fèi)了?!?/p>

Redis 高可用方案有哪些?

高可用有兩個(gè)含義:一是數(shù)據(jù)盡量不丟失,二是服務(wù)盡可能提供服務(wù)。 Redis 高可用方案嚴(yán)格意義上來說有 3 種。

  • 主從復(fù)制架構(gòu),這是后兩個(gè)方案的基石。
  • sentinel 哨兵集群。
  • Redis Cluster 集群,極力推薦該方式。

1. 主從異步復(fù)制同步

主從異步復(fù)制架構(gòu)是高可用的基石,主要分為 RDB 內(nèi)存快照文件全量同步和增量同步。

全量同步

Redis master 執(zhí)行 bgsave 命令生成 RDB 內(nèi)存快照文件,slave 收到 RDB 內(nèi)存快照文件保存到磁盤,并清空當(dāng)前數(shù)據(jù)庫的數(shù)據(jù),再加載 RDB 文件數(shù)據(jù)到內(nèi)存中。最后,master 再把發(fā)送生成 RDB 文件至同步 slave 加載 RDB 期間接受到的新寫命令同步到到 slave。

Redis全量同步

增量同步

只要主從連接不中斷,就會(huì)持續(xù)進(jìn)行基于長連接的命令傳播復(fù)制。在 Redis 2.8 之前,如果主從復(fù)制在命令傳播時(shí)出現(xiàn)了網(wǎng)絡(luò)閃斷,那么,slave 就會(huì)和 mater 重新進(jìn)行一次全量復(fù)制,開銷非常大。

從 Redis 2.8 開始,網(wǎng)絡(luò)斷了重連之后,slave 會(huì)嘗試采用增量復(fù)制的方式繼續(xù)同步。

增量復(fù)制:用于網(wǎng)絡(luò)中斷等情況后的復(fù)制,只將中斷期間 mater 執(zhí)行的寫命令發(fā)送給 slave,與全量復(fù)制相比更加高效。

圖 3-4

其中還涉及到 replication buffer 和 repl_backlog 的緩沖區(qū)的作用,說到這一塊就已經(jīng)讓你脫穎而出了。

接著,你再補(bǔ)充在 Redis 7.0 之后,采用了共享緩沖區(qū)的設(shè)計(jì)。

Chaya 自信的補(bǔ)充說:“因?yàn)椴还苁侨繌?fù)制還是增量復(fù)制,當(dāng)寫請(qǐng)求到達(dá) master 時(shí),指令會(huì)分別寫入所有 slave 的 replication buffer 以及 repl_backlog_buffer。重復(fù)保存,太浪費(fèi)內(nèi)存了。

既然存儲(chǔ)內(nèi)容是一樣,直接的做法就是主從復(fù)制在命令傳播時(shí),將這些寫命令放在一個(gè)全局的復(fù)制緩沖區(qū)中,多個(gè) slave 共享這份數(shù)據(jù),不同 slave 引用緩沖區(qū)的不同內(nèi)容,這就是共享緩沖區(qū)的核心思想?!?/p>

2. sentinel 集群

Sentinel 是 Redis 的一種運(yùn)行模式,它專注于對(duì) Redis 實(shí)例(主節(jié)點(diǎn)、從節(jié)點(diǎn))運(yùn)行狀態(tài)的監(jiān)控,并能夠在主節(jié)點(diǎn)發(fā)生故障時(shí)通過一系列的機(jī)制實(shí)現(xiàn)選主及主從切換,實(shí)現(xiàn)自動(dòng)故障轉(zhuǎn)移,確保整個(gè) Redis 系統(tǒng)的可用性。

sentinel 主要做四件事情。

3-18

監(jiān)控 master 和 slave 狀態(tài),判斷是否下線。

  • 每秒一次的頻率向 master 和 slave 以及其他 sentinel 發(fā)送 PING 命令,如果該節(jié)點(diǎn)距離最后一次響應(yīng) PING 的時(shí)間超過 down-after-milliseconds 選項(xiàng)所指定的值, 則這個(gè)實(shí)例會(huì)被 Sentinel 標(biāo)記為主觀下線,當(dāng) master 被標(biāo)記主觀下線。
  • 其他正在監(jiān)視這個(gè) master 的所有 sentinel 會(huì)按照每秒一次的頻率確認(rèn) master 是否主觀下線。
  • 當(dāng)足夠多的 sentinel 丟認(rèn)為 master 主觀下線,則標(biāo)記這個(gè) master 客觀下線。

選舉新 master,如果 master 出現(xiàn)故障,sentine 需要選舉一個(gè) slave 晉升為新 master。晉升為新 master 的 slave 是有條件的,先過濾不滿足條件的,再打分排優(yōu)先級(jí)。

篩選打分

slave 優(yōu)先級(jí),通過 replica-priority 100 配置,值越低,優(yōu)先級(jí)越高。

復(fù)制偏移量(processed replication offset),已復(fù)制的數(shù)據(jù)量越多越好,slave_repl_offset與 master_repl_offset 差值越小。

slave runID,在優(yōu)先級(jí)和復(fù)制進(jìn)度都相同的情況下,runID 最小的 slave 得分最高,會(huì)被選為新主庫。

過濾掉下線、網(wǎng)絡(luò)異常的 slave。

過濾掉經(jīng)常與 master 斷開的 slave。

執(zhí)行主從切換,從 sentinel 集群中選舉一個(gè) leader 執(zhí)行故障自動(dòng)切換。成為 leader 的條件是收到的贊成票大于等于 `quorum 的值且贊半數(shù)以上。

第一個(gè)判定 master 主觀下線的 sentinel 收到其他 sentinel 節(jié)點(diǎn)的回復(fù)并確定 master 客觀下線后,就會(huì)給其他 sentinel 節(jié)點(diǎn)發(fā)送命令申請(qǐng)成為 leader。

通知,通知其他 slave 執(zhí)行 replicaof 與新的 master 同步數(shù)據(jù),并通知客戶端與新 master 建立連接。

3-17

3. Redis Cluster

Redis Cluster 在 Redis 3.0 及以上版本提供,是一種分布式數(shù)據(jù)庫方案,通過分片(sharding)來進(jìn)行數(shù)據(jù)管理(分治思想的一種實(shí)踐),并提供復(fù)制和故障轉(zhuǎn)移功能。

Redis Cluster 并沒有使用一致性哈希算法,而是將數(shù)據(jù)劃分為 16384 的 slots ,每個(gè)節(jié)點(diǎn)負(fù)責(zé)一部分 slots,slot 的信息存儲(chǔ)在每個(gè)節(jié)點(diǎn)中。

圖 3-25

集群 mater 節(jié)點(diǎn)最大上限是 16384(官方建議最大節(jié)點(diǎn)數(shù)為 1000 個(gè)),數(shù)據(jù)庫的每個(gè) key 會(huì)映射到這 16384 個(gè)槽中的其中一個(gè),每個(gè)節(jié)點(diǎn)可以處理 1 個(gè)或者最多 16384 個(gè)槽。

面試官:“集群各個(gè)節(jié)點(diǎn)之間是如何通信呢?”

通過 Gossip 協(xié)議進(jìn)行通信,節(jié)點(diǎn)之間不斷交換信息,交換的信息包括節(jié)點(diǎn)出現(xiàn)故障、新節(jié)點(diǎn)加入、主從節(jié)點(diǎn)變更, slots 信息變更等。常用的 Gossip 消息分為 4 種,分別是:ping、pong、meet、fail。

  • meet 消息:通知新節(jié)點(diǎn)加入。消息發(fā)送者通知接受者加入當(dāng)前集群。
  • ping消息:每個(gè)節(jié)點(diǎn)每秒向其他節(jié)點(diǎn)發(fā)送 ping 消息,用于檢測節(jié)點(diǎn)在線和交換刺激狀態(tài)信息。
  • pong消息:節(jié)點(diǎn)接受到 ping 消息后,作為響應(yīng)消息回復(fù)發(fā)送方確認(rèn)正常,同時(shí) pong 還包含了自身的狀態(tài)數(shù)據(jù),想集群廣播 pong 消息來通知集群自身狀態(tài)進(jìn)行更新。
  • fail消息:節(jié)點(diǎn) ping 不通謀節(jié)點(diǎn)后,則向集群所有節(jié)點(diǎn)廣播該節(jié)點(diǎn)掛掉的消息。

面試官:“Redis Cluster 如何實(shí)現(xiàn)自動(dòng)故障轉(zhuǎn)移呢?”

  • 故障檢測:集群中每個(gè)節(jié)點(diǎn)都會(huì)定期通過 Gossip 協(xié)議向其他節(jié)點(diǎn)發(fā)送 PING 消息,檢測各個(gè)節(jié)點(diǎn)的狀態(tài)(在線狀態(tài)、疑似下線狀態(tài) PFAIL、已下線狀態(tài) FAIL)。并通過 Gossip 協(xié)議來廣播自己的狀態(tài)以及自己對(duì)整個(gè)集群認(rèn)知的改變。
  • master 選舉:使用從當(dāng)前故障 master 的所有 slave 選舉一個(gè)提升為 master。
  • 故障轉(zhuǎn)移:取消與舊 master 的主從復(fù)制關(guān)系,將舊 master 負(fù)責(zé)的槽位信息指派到當(dāng)前 master,更新 Cluster 狀態(tài)并寫入數(shù)據(jù)文件,通過 gossip 協(xié)議向集群廣播發(fā)送 CLUSTERMSG_TYPE_PONG消息,把最新的信息傳播給其他節(jié)點(diǎn),其他節(jié)點(diǎn)收到該消息后更新自身的狀態(tài)信息或與新 master 建立主從復(fù)制關(guān)系。

面試官:“新增節(jié)點(diǎn)或者重新分配 slots 導(dǎo)致 slots 與節(jié)點(diǎn)之間的映射關(guān)系改變了,客戶端如何知道把請(qǐng)求發(fā)到哪里?”

Redis Cluster 提供了請(qǐng)求重定向機(jī)制解決:客戶端將請(qǐng)求發(fā)送到某個(gè)節(jié)點(diǎn)上,這個(gè)節(jié)點(diǎn)沒有相應(yīng)的數(shù)據(jù),該 Redis 節(jié)點(diǎn)會(huì)告訴客戶端將請(qǐng)求發(fā)送到其他的節(jié)點(diǎn)。

MOVED 重定向

當(dāng)重新分配或者負(fù)載均衡,slots 數(shù)據(jù)已經(jīng)遷移到其他節(jié)點(diǎn),節(jié)點(diǎn)會(huì)響應(yīng)一個(gè) MOVED 錯(cuò)誤指引客戶端重定向到正確的節(jié)點(diǎn),并且客戶端會(huì)更新本地 slots 與節(jié)點(diǎn)映射關(guān)系,以便下次可以正確訪問。

GET 公眾號(hào):碼哥字節(jié)
-MOVED 16330 172.17.18.2:6379

該響應(yīng)的含義是客戶端請(qǐng)求的鍵值對(duì)所在的 slot 16300 已經(jīng)遷移到了 172.17.18.2 這個(gè)節(jié)點(diǎn)上,端口是 6379。

同時(shí),客戶端還會(huì)更新本地緩存,將該 slot 與 Redis 實(shí)例對(duì)應(yīng)關(guān)系更新正確。

3-30

ASK 重定向

如果某個(gè) slot 的數(shù)據(jù)只有部分遷移過去,沒有遷移完成,節(jié)點(diǎn)收到客戶端請(qǐng)求如果能根據(jù) key -> slot -> node 映射關(guān)系定位到的節(jié)點(diǎn)存在該 key,則直接執(zhí)行命令,否則就向客戶端響應(yīng) ASK 錯(cuò)誤,表示該 key 所在的 slot 正在遷移到其他節(jié)點(diǎn),客戶端先給目標(biāo)節(jié)點(diǎn)發(fā)送 ASKING 命令詢問節(jié)點(diǎn)是否可以處理,接著才會(huì)發(fā)送操作指令。

比如客戶端請(qǐng)求定位到 key = “公眾號(hào):碼哥字節(jié)” 的 slot 是 16330 由實(shí)例 172.17.18.1 負(fù)責(zé),節(jié)點(diǎn) 1 如果找得到就直接執(zhí)行命令,否則響應(yīng) ASK 錯(cuò)誤信息,指引客戶端轉(zhuǎn)向正在遷移的目標(biāo)節(jié)點(diǎn) 172.17.18.2,端口是 6379。

GET 公眾號(hào):碼哥字節(jié)
-ASK 16330 172.17.18.2:6379

3-31

注意:ASK 錯(cuò)誤指令并不會(huì)更新客戶端緩存的 slot 分配信息。

為什么集群的 slots 是 16384?

面試官:“CRC16 算法,產(chǎn)生的 hash 值有 16 bit 位,可以產(chǎn)生 65536(2^16)個(gè)值 ,也就是說值分布在 0 ~ 65535 之間。”

  • 正常的 ping 數(shù)據(jù)包攜帶節(jié)點(diǎn)的完整配置,用的是一個(gè) bitmap 數(shù)據(jù)結(jié)構(gòu),它能以冪等方式來更新配置。如果采用 16384 個(gè)插槽,占空間 2KB (16384/8);如果采用 65536 個(gè)插槽,占空間 8KB (65536/8)。
  • Redis Cluster 不太可能擴(kuò)展到超過 1000 個(gè)主節(jié)點(diǎn),太多可能導(dǎo)致網(wǎng)絡(luò)擁堵。
  • 16384 個(gè) slot 范圍比較合適,當(dāng)集群擴(kuò)展到 1000 個(gè)節(jié)點(diǎn)時(shí),也能確保每個(gè) master 節(jié)點(diǎn)有足夠的 slot。

8KB 的心跳包看似不大,但是這個(gè)是心跳包每秒都要將本節(jié)點(diǎn)的信息同步給集群其他節(jié)點(diǎn)。比起 16384 個(gè) slot ,header 大小增加了 4 倍,ping 消息的消息頭太大了,浪費(fèi)帶寬。

責(zé)任編輯:姜華 來源: 碼哥跳動(dòng)
相關(guān)推薦

2024-02-28 10:14:47

Redis數(shù)據(jù)硬盤

2015-07-28 10:52:36

DevOps

2018-09-05 12:20:09

數(shù)據(jù)庫Redis面試題

2025-03-10 11:48:22

項(xiàng)目服務(wù)設(shè)計(jì)

2024-09-24 10:28:22

2015-08-13 10:29:12

面試面試官

2024-04-19 00:00:00

計(jì)數(shù)器算法限流算法

2021-05-17 07:08:28

大數(shù)據(jù)采集MySQL

2020-04-20 08:35:48

HTTP HTTPS網(wǎng)絡(luò)協(xié)議

2021-11-02 09:05:25

Redis

2023-10-28 09:13:32

系統(tǒng)面試官架構(gòu)

2024-04-03 00:00:00

Redis集群代碼

2017-02-22 08:52:32

開源谷歌大數(shù)據(jù)

2018-04-13 14:53:13

PythonMySQL爬蟲

2010-10-29 10:57:35

面試

2020-11-06 07:11:40

內(nèi)存虛擬Redis

2020-07-02 07:52:11

RedisHash映射

2024-04-09 10:40:04

2022-07-06 13:48:24

RedisSentinel機(jī)制

2024-10-22 16:39:07

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)