更新時(shí)間:2022-12-28 15:15:31 來(lái)源:動(dòng)力節(jié)點(diǎn) 瀏覽1648次
1.談?wù)凴edis集群數(shù)據(jù)hash分片算法
Redis 集群將所有數(shù)據(jù)劃分16384個(gè)slots,每個(gè)節(jié)點(diǎn)負(fù)責(zé)其中一部分槽位。當(dāng)Redis 集群的客戶端來(lái)連接集群時(shí),它也會(huì)得到一份集群的槽位信息并將其緩存到客戶端本地,這樣當(dāng)客戶端要查找某個(gè)key時(shí),可以根據(jù)槽位定位算法定位到目標(biāo)節(jié)點(diǎn)。
槽位定位算法
集群默認(rèn)會(huì)對(duì)key值使用crc16算法進(jìn)行hash,得到一個(gè)整數(shù)值,然后這個(gè)整數(shù)值對(duì)16384進(jìn)行取模運(yùn)算來(lái)得到具體的槽位。
Hash_slot = CRC16(key)mod13684
再根據(jù)槽位和節(jié)點(diǎn)的對(duì)應(yīng)關(guān)系就可以定位到key具體是在那個(gè)Redis節(jié)點(diǎn)上。

2.Redis執(zhí)行命令竟然有死循環(huán)阻塞Bug
Redis有個(gè)RANDOMKEY命令可以從Redis中隨機(jī)取出一個(gè)key,這個(gè)命令可能導(dǎo)致Redis死循環(huán)阻塞。
RANDOMKEY在隨機(jī)拿出一個(gè)key之后,首先會(huì)檢驗(yàn)這個(gè)key是否過(guò)期,如果該key過(guò)期,那么Redis會(huì)刪除它,這個(gè)過(guò)程就是惰性刪除,但是清理完了之后還不能結(jié)束,Redis會(huì)再找出一個(gè)沒(méi)過(guò)期的key返回給客戶端。
此時(shí),Redis則會(huì)繼續(xù)隨機(jī)拿出一個(gè)key,然后再判斷它是否過(guò)期,直到找到一個(gè)沒(méi)過(guò)期的key返回給客戶端。
這里就有一個(gè)問(wèn)題,如果此時(shí)Redis中有大量的key過(guò)期,但還未來(lái)得及被清理掉,這個(gè)循環(huán)就會(huì)持續(xù)很久才能結(jié)束,這樣就會(huì)導(dǎo)致RANDOMKEY命令執(zhí)行耗時(shí)變長(zhǎng),影響Redis性能。
以上流程,其實(shí)是master上執(zhí)行的。如果在slave上執(zhí)行RANDOMKEY,那么問(wèn)題更嚴(yán)重。
slave是不會(huì)自己清理過(guò)期的key,當(dāng)一個(gè)key要過(guò)期時(shí),master會(huì)先清理刪除它,之后master向slave發(fā)送一個(gè)DEL命令,告知slave也刪除這個(gè)key,以此達(dá)到主從一致。
假設(shè)Redis中存在大量已過(guò)期還未來(lái)得及清理的key,那么在slave上執(zhí)行RANDOMKEY時(shí),就會(huì)發(fā)生一下問(wèn)題:
1、slave隨機(jī)取出一個(gè)key,判斷是否已經(jīng)過(guò)期。
2、key已經(jīng)過(guò)期,但是slave不會(huì)刪除它,而是繼續(xù)隨機(jī)尋找不過(guò)期的key
3、由于大量key都已過(guò)期,那slave就會(huì)找不到符合條件的key,就會(huì)進(jìn)入死循環(huán)。
這個(gè)Bug直到5.0才被修復(fù),修復(fù)方法就是在slave中設(shè)置一個(gè)最大查找次數(shù),無(wú)論找到與否,到了這個(gè)最大次數(shù)就退出循環(huán)。
3.一次線上事故,Redis主從切換導(dǎo)致了緩存雪崩
我們假設(shè),slave的機(jī)器時(shí)鐘比master走的快很多。
此時(shí),Redis master 里設(shè)置了過(guò)期時(shí)間的key,從slave角度來(lái)看,可能會(huì)有很多在master里沒(méi)過(guò)期,在slave里面已經(jīng)過(guò)期了的數(shù)據(jù)。
如果此時(shí)操作主從切換,把slave提升為新的master,新的master就會(huì)開(kāi)始大量清理過(guò)期的key,此時(shí)就會(huì)導(dǎo)致以下結(jié)果:
1、master大量清理過(guò)期key,主線程可能會(huì)發(fā)生阻塞,無(wú)法及時(shí)處理客戶端請(qǐng)求。
2、Redis中數(shù)據(jù)大量過(guò)期,引發(fā)緩存雪崩。
所以,我們一定要保證主從庫(kù)的機(jī)器時(shí)鐘一致,避免發(fā)生這些問(wèn)題。
4.Redis持久化RDB、AOF、混合持久化
Redis持久化分為:RDB、AOF、混合持久化(redis4.0引入)
RDB的實(shí)現(xiàn)原理、優(yōu)缺點(diǎn)
描述:類似于快照。在某個(gè)時(shí)間點(diǎn),將 Redis 在內(nèi)存中的數(shù)據(jù)庫(kù)狀態(tài)(數(shù)據(jù)庫(kù)的鍵值對(duì)等信息)保存到磁盤里面。RDB 持久化功能生成的 RDB 文件是經(jīng)過(guò)壓縮的二進(jìn)制文件。
有兩個(gè) Redis 命令可以用于生成 RDB 文件,一個(gè)是 SAVE,另一個(gè)是 BGSAVE。
開(kāi)啟:使用 save point 配置
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:生成 RDB 快照文件,但是會(huì)阻塞主進(jìn)程,服務(wù)器將無(wú)法處理客戶端發(fā)來(lái)的命令請(qǐng)求,所以通常不會(huì)直接使用該命令。
BGSAVE:fork 子進(jìn)程來(lái)生成 RDB 快照文件,阻塞只會(huì)發(fā)生在 fork 子進(jìn)程的時(shí)候,之后主進(jìn)程可以正常處理請(qǐng)求.
RDB 的優(yōu)點(diǎn):1)RDB 文件是是經(jīng)過(guò)壓縮的二進(jìn)制文件,占用空間很小,它保存了 Redis 某個(gè)時(shí)間點(diǎn)的數(shù)據(jù)集,很適合用于做備份。 比如說(shuō),你可以在最近的 24 小時(shí)內(nèi),每小時(shí)備份一次 RDB 文件,并且在每個(gè)月的每一天,也備份一個(gè) RDB 文件。這樣的話,即使遇上問(wèn)題,也可以隨時(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ì)處理接下來(lái)的所有保存工作,父進(jìn)程無(wú)須執(zhí)行任何磁盤 I/O 操作。
4)RDB 在恢復(fù)大數(shù)據(jù)集時(shí)的速度比 AOF 的恢復(fù)速度要快。
RDB 的缺點(diǎn):1)RDB 在服務(wù)器故障時(shí)容易造成數(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)程需要將修改的頁(yè)面拷貝一份出來(lái),然后進(jìn)行修改。極端情況下,如果所有的頁(yè)面都被修改,則此時(shí)的內(nèi)存占用是原先的2倍。
AOF的實(shí)現(xiàn)原理、優(yōu)缺點(diǎn)
描述:保存 Redis 服務(wù)器所執(zhí)行的所有寫操作命令來(lái)記錄數(shù)據(jù)庫(kù)狀態(tài),并在服務(wù)器啟動(dòng)時(shí),通過(guò)重新執(zhí)行這些命令來(lái)還原數(shù)據(jù)集。
可以通過(guò)配置:appendonly yes 開(kāi)啟,使用配置 appendonly no 可以關(guān)閉 AOF 持久化
AOF 持久化功能的實(shí)現(xiàn)可以分為三個(gè)步驟:命令追加、文件寫入、文件同步。
appendfsync 參數(shù)有三個(gè)選項(xiàng):
1)always:每處理一個(gè)命令都將 aof_buf 緩沖區(qū)中的所有內(nèi)容寫入并同步到AOF 文件,即每個(gè)命令都刷盤。
2)everysec:將 aof_buf 緩沖區(qū)中的所有內(nèi)容寫入到 AOF 文件,如果上次同步 AOF 文件的時(shí)間距離現(xiàn)在超過(guò)一秒鐘, 那么再次對(duì) AOF 文件進(jìn)行同步, 并且這個(gè)同步操作是異步的,由一個(gè)后臺(tái)線程專門負(fù)責(zé)執(zhí)行,即每秒刷盤1次。
3)no:將 aof_buf 緩沖區(qū)中的所有內(nèi)容寫入到 AOF 文件, 但并不對(duì) AOF 文件進(jìn)行同步, 何時(shí)同步由操作系統(tǒng)來(lái)決定。即不執(zhí)行刷盤,讓操作系統(tǒng)自己執(zhí)行刷盤。
2)AOF文件是一個(gè)純追加的日志文件。即使日志因?yàn)槟承┰蚨宋磳懭胪暾拿?比如寫入時(shí)磁盤已滿,寫入中途停機(jī)等等), 我們也可以使用 redis-check-aof 工具也可以輕易地修復(fù)這種問(wèn)題。
3)當(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)行切換,然后開(kāi)始把數(shù)據(jù)寫到新文件上
4)AOF 文件有序地保存了對(duì)數(shù)據(jù)庫(kù)執(zhí)行的所有寫入操作以 Redis 協(xié)議的格式保存, 因此 AOF 文件的內(nèi)容非常容易被人讀懂, 對(duì)文件進(jìn)行分析(parse)也很輕松。如果你不小心執(zhí)行了 FLUSHALL 命令把所有數(shù)據(jù)刷掉了,但只要 AOF 文件沒(méi)有被重寫,那么只要停止服務(wù)器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重啟 Redis , 就可以將數(shù)據(jù)集恢復(fù)到 FLUSHALL 執(zhí)行之前的狀態(tài)。
1)對(duì)于相同的數(shù)據(jù)集,AOF 文件的大小一般會(huì)比 RDB 文件大。
2)根據(jù)所使用的 fsync 策略,AOF 的速度可能會(huì)比 RDB 慢。通常 fsync 設(shè)置為每秒一次就能獲得比較高的性能,而關(guān)閉 fsync 可以讓 AOF 的速度和 RDB 一樣快。
生產(chǎn)環(huán)境都可以啟用,redis啟動(dòng)時(shí)如果既有rdb文件,又有aof文件則優(yōu)先選擇aof文件恢復(fù)數(shù)據(jù),因?yàn)閍of一般來(lái)說(shuō)數(shù)據(jù)更安全一點(diǎn)。
混合持久化
通過(guò)如下配置開(kāi)啟混合持久化(必須先開(kāi)啟aof)
aof-use-rdb-preamble yes
混合持久化本質(zhì)是通過(guò) AOF 后臺(tái)重寫(bgrewriteaof 命令)完成的,不同的是當(dāng)開(kāi)啟混合持久化時(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 格式,可讀性差。
以上就是“距離進(jìn)入大廠就只差redis集群面試題”,你能回答上來(lái)嗎?如果想要了解更多的Java面試題相關(guān)內(nèi)容,可以關(guān)注動(dòng)力節(jié)點(diǎn)Java官網(wǎng)。
相關(guān)閱讀
Java實(shí)驗(yàn)班
0基礎(chǔ) 0學(xué)費(fèi) 15天面授
Java就業(yè)班
有基礎(chǔ) 直達(dá)就業(yè)
Java夜校直播班
業(yè)余時(shí)間 高薪轉(zhuǎn)行
Java在職加薪班
工作1~3年,加薪神器
Java架構(gòu)師班
工作3~5年,晉升架構(gòu)
提交申請(qǐng)后,顧問(wèn)老師會(huì)電話與您溝通安排學(xué)習(xí)