摘要:面試官聊下的分片集群,先聊好咯面試官是才有的官方集群方案,這塊你了解多少候選者嗯,要不還是從基礎(chǔ)講起唄候選者在前面聊的時(shí)候,提到的都是單實(shí)例存儲(chǔ)所有的數(shù)據(jù)。
面試官:聊下Redis的分片集群,先聊 Redis Cluster好咯?
面試官:Redis Cluser是Redis 3.x才有的官方集群方案,這塊你了解多少?
候選者:嗯,要不還是從基礎(chǔ)講起唄?
候選者:在前面聊Redis的時(shí)候,提到的Redis都是「單實(shí)例」存儲(chǔ)所有的數(shù)據(jù)。
候選者:1. 主從模式下實(shí)現(xiàn)讀寫分離的架構(gòu),可以讓多個(gè)從服務(wù)器承載「讀流量」,但面對(duì)「寫流量」時(shí),始終是只有主服務(wù)器在抗。
候選者:2. 「縱向擴(kuò)展」升級(jí)Redis服務(wù)器硬件能力,但升級(jí)至一定程度下,就不劃算了。
候選者:縱向擴(kuò)展意味著「大內(nèi)存」,Redis持久化時(shí)的"成本"會(huì)加大(Redis做RDB持久化,是全量的,fork子進(jìn)程時(shí)有可能由于使用內(nèi)存過大,導(dǎo)致主線程阻塞時(shí)間過長(zhǎng))
候選者:所以,「單實(shí)例」是有瓶頸的
候選者:「縱向擴(kuò)展」不行,就「橫向擴(kuò)展」唄。
候選者:用多個(gè)Redis實(shí)例來組成一個(gè)集群,按照一定的規(guī)則把數(shù)據(jù)「分發(fā)」到不同的Redis實(shí)例上。當(dāng)集群所有的Redis實(shí)例的數(shù)據(jù)加起來,那這份數(shù)據(jù)就是全的
候選者:其實(shí)就是「分布式」的概念(:只不過,在Redis里,好像叫「分片集群」的人比較多?
候選者:從前面就得知了,要「分布式存儲(chǔ)」,就肯定避免不了對(duì)數(shù)據(jù)進(jìn)行「分發(fā)」(也是路由的意思)
候選者:從Redis Cluster講起吧,它的「路由」是做在客戶端的(SDK已經(jīng)集成了路由轉(zhuǎn)發(fā)的功能)
候選者:Redis Cluster對(duì)數(shù)據(jù)的分發(fā)的邏輯中,涉及到「哈希槽」(Hash Solt)的概念
候選者:Redis Cluster默認(rèn)一個(gè)集群有16384個(gè)哈希槽,這些哈希槽會(huì)分配到不同的Redis實(shí)例中
候選者:至于怎么「瓜分」,可以直接均分,也可以「手動(dòng)」設(shè)置每個(gè)Redis實(shí)例的哈希槽,全由我們來決定
候選者:重要的是,我們要把這16384個(gè)都得瓜分完,不能有剩余!
候選者:當(dāng)客戶端有數(shù)據(jù)進(jìn)行寫入的時(shí)候,首先會(huì)對(duì)key按照CRC16算法計(jì)算出16bit的值(可以理解為就是做hash),然后得到的值對(duì)16384進(jìn)行取模
候選者:取模之后,自然就得到其中一個(gè)哈希槽,然后就可以將數(shù)據(jù)插入到分配至該哈希槽的Redis實(shí)例中
面試官:那問題就來了,現(xiàn)在客戶端通過hash算法算出了哈希槽的位置,那客戶端怎么知道這個(gè)哈希槽在哪臺(tái)Redis實(shí)例上呢?
候選者:是這樣的,在集群的中每個(gè)Redis實(shí)例都會(huì)向其他實(shí)例「?jìng)鞑ァ棺约核?fù)責(zé)的哈希槽有哪些。這樣一來,每臺(tái)Redis實(shí)例就可以記錄著「所有哈希槽與實(shí)例」的關(guān)系了(:
候選者:有了這個(gè)映射關(guān)系以后,客戶端也會(huì)「緩存」一份到自己的本地上,那自然客戶端就知道去哪個(gè)Redis實(shí)例上操作了
面試官:那我又有問題了,在集群里也可以新增或者刪除Redis實(shí)例啊,這個(gè)怎么整?
候選者:當(dāng)集群刪除或者新增Redis實(shí)例時(shí),那總會(huì)有某Redis實(shí)例所負(fù)責(zé)的哈希槽關(guān)系會(huì)發(fā)生變化
候選者:發(fā)生變化的信息會(huì)通過消息發(fā)送至整個(gè)集群中,所有的Redis實(shí)例都會(huì)知道該變化,然后更新自己所保存的映射關(guān)系
候選者:但這時(shí)候,客戶端其實(shí)是不感知的(:
候選者:所以,當(dāng)客戶端請(qǐng)求時(shí)某Key時(shí),還是會(huì)請(qǐng)求到「原來」的Redis實(shí)例上。而原來的Redis實(shí)例會(huì)返回「moved」命令,告訴客戶端應(yīng)該要去新的Redis實(shí)例上去請(qǐng)求啦
候選者:客戶端接收到「moved」命令之后,就知道去新的Redis實(shí)例請(qǐng)求了,并且更新「緩存哈希槽與實(shí)例之間的映射關(guān)系」
候選者:總結(jié)起來就是:數(shù)據(jù)遷移完畢后被響應(yīng),客戶端會(huì)收到「moved」命令,并且會(huì)更新本地緩存
面試官:那數(shù)據(jù)還沒完全遷移完呢?
候選者:如果數(shù)據(jù)還沒完全遷移完,那這時(shí)候會(huì)返回客戶端「ask」命令。也是讓客戶端去請(qǐng)求新的Redis實(shí)例,但客戶端這時(shí)候不會(huì)更新本地緩存
面試官:了解了
面試官:說白了就是,如果集群Redis實(shí)例存在變動(dòng),由于Redis實(shí)例之間會(huì)「通訊」
面試官:所以等到客戶端請(qǐng)求時(shí),Redis實(shí)例總會(huì)知道客戶端所要請(qǐng)求的數(shù)據(jù)在哪個(gè)Redis實(shí)例上
面試官:如果已經(jīng)遷移完畢了,那就返回「move」命令告訴客戶端應(yīng)該去找哪個(gè)Redis實(shí)例要數(shù)據(jù),并且客戶端應(yīng)該更新自己的緩存(映射關(guān)系)
面試官:如果正在遷移中,那就返回「ack」命令告訴客戶端應(yīng)該去找哪個(gè)Redis實(shí)例要數(shù)據(jù)
候選者:不愧是你...
面試官:那你知道為什么哈希槽是16384個(gè)嗎?
候選者:嗯,這個(gè)。是這樣的,Redis實(shí)例之間「通訊」會(huì)相互交換「槽信息」,那如果槽過多(意味著網(wǎng)絡(luò)包會(huì)變大),網(wǎng)絡(luò)包變大,那是不是就意味著會(huì)「過度占用」網(wǎng)絡(luò)的帶寬
候選者:另外一塊是,Redis作者認(rèn)為集群在一般情況下是不會(huì)超過1000個(gè)實(shí)例
候選者:那就取了16384個(gè),即可以將數(shù)據(jù)合理打散至Redis集群中的不同實(shí)例,又不會(huì)在交換數(shù)據(jù)時(shí)導(dǎo)致帶寬占用過多
面試官:了解了
面試官:那你知道為什么對(duì)數(shù)據(jù)進(jìn)行分區(qū)在Redis中用的是「哈希槽」這種方式嗎?而不是一致性哈希算法
候選者:在我理解下,一致性哈希算法就是有個(gè)「哈希環(huán)」,當(dāng)客戶端請(qǐng)求時(shí),會(huì)對(duì)Key進(jìn)行hash,確定在哈希環(huán)上的位置,然后順時(shí)針往后找,找到的第一個(gè)真實(shí)節(jié)點(diǎn)
候選者:一致性哈希算法比「?jìng)鹘y(tǒng)固定取模」的好處就是:如果集群中需要新增或刪除某實(shí)例,只會(huì)影響一小部分的數(shù)據(jù)
候選者:但如果在集群中新增或者刪除實(shí)例,在一致性哈希算法下,就得知道是「哪一部分?jǐn)?shù)據(jù)」受到影響了,需要進(jìn)行對(duì)受影響的數(shù)據(jù)進(jìn)行遷移
面試官:嗯...
候選者:而哈希槽的方式,我們通過上面已經(jīng)可以發(fā)現(xiàn):在集群中的每個(gè)實(shí)例都能拿到槽位相關(guān)的信息
候選者:當(dāng)客戶端對(duì)key進(jìn)行hash運(yùn)算之后,如果發(fā)現(xiàn)請(qǐng)求的實(shí)例沒有相關(guān)的數(shù)據(jù),實(shí)例會(huì)返回「重定向」命令告訴客戶端應(yīng)該去哪兒請(qǐng)求
候選者:集群的擴(kuò)容、縮容都是以「哈希槽」作為基本單位進(jìn)行操作,總的來說就是「實(shí)現(xiàn)」會(huì)更加簡(jiǎn)單(簡(jiǎn)潔,高效,有彈性)。過程大概就是把部分槽進(jìn)行重新分配,然后遷移槽中的數(shù)據(jù)即可,不會(huì)影響到集群中某個(gè)實(shí)例的所有數(shù)據(jù)。
面試官:那你了解「服務(wù)端 路由」的大致原理嗎?
候選者:嗯,服務(wù)端路由一般指的就是,有個(gè)代理層專門對(duì)接客戶端的請(qǐng)求,然后再轉(zhuǎn)發(fā)到Redis集群進(jìn)行處理
候選者:上次最后面試的時(shí)候,也提到了,現(xiàn)在比較流行的是Codis
候選者:它與Redis Cluster最大的區(qū)別就是,Redis Cluster是直連Redis實(shí)例的,而Codis則客戶端直連Proxy,再由Proxy進(jìn)行分發(fā)到不同的Redis實(shí)例進(jìn)行處理
候選者:在Codis對(duì)Key路由的方案跟Redis Cluster很類似,Codis初始化出1024個(gè)哈希槽,然后分配到不同的Redis服務(wù)器中
候選者:哈希槽與Redis實(shí)例的映射關(guān)系由Zookeeper進(jìn)行存儲(chǔ)和管理,Proxy會(huì)通過Codis DashBoard得到最新的映射關(guān)系,并緩存在本地上
面試官:那如果我要擴(kuò)容Codis Redis實(shí)例的流程是怎么樣的?
候選者:簡(jiǎn)單來說就是:把新的Redis實(shí)例加入到集群中,然后把部分?jǐn)?shù)據(jù)遷移到新的實(shí)例上
候選者:大概的過程就是:1.「原實(shí)例」某一個(gè)Solt的部分?jǐn)?shù)據(jù)發(fā)送給「目標(biāo)實(shí)例」。2.「目標(biāo)實(shí)例」收到數(shù)據(jù)后,給「原實(shí)例」返回ack。3.「原實(shí)例」收到ack之后,在本地刪除掉剛剛給「目標(biāo)實(shí)例」的數(shù)據(jù)。4.不斷循環(huán)1、2、3步驟,直至整個(gè)solt遷移完畢
候選者:Codis也是支持「異步遷移」的,針對(duì)上面的步驟2,「原實(shí)例」發(fā)送數(shù)據(jù)后,不等待「目標(biāo)實(shí)例」返回ack,就繼續(xù)接收客戶端的請(qǐng)求。
候選者:未遷移完的數(shù)據(jù)標(biāo)記為「只讀」,不會(huì)影響到數(shù)據(jù)的一致性。如果對(duì)遷移中的數(shù)據(jù)存在「寫操作」,那會(huì)讓客戶端進(jìn)行「重試」,最后會(huì)寫到「目標(biāo)實(shí)例」上
候選者:還有就是,針對(duì) bigkey,異步遷移采用了「拆分指令」的方式進(jìn)行遷移,比如有個(gè)set元素有10000個(gè),那「原實(shí)例」可能就發(fā)送10000條命令給「目標(biāo)實(shí)例」,而不是一整個(gè)bigkey一次性遷移(因?yàn)榇髮?duì)象容易造成阻塞)
面試官:了解了。
本文總結(jié):
分片集群誕生理由:寫性能在高并發(fā)下會(huì)遇到瓶頸&&無法無限地縱向擴(kuò)展(不劃算)
分片集群:需要解決「數(shù)據(jù)路由」和「數(shù)據(jù)遷移」的問題
Redis Cluster數(shù)據(jù)路由:
為什么16384個(gè)哈希槽:16384個(gè)既能讓Redis實(shí)例分配到的數(shù)據(jù)相對(duì)均勻,又不會(huì)影響Redis實(shí)例之間交互槽信息產(chǎn)生嚴(yán)重的網(wǎng)絡(luò)性能開銷問題
Redis Cluster 為什么使用哈希槽,而非一致性哈希算法:哈希槽實(shí)現(xiàn)相對(duì)簡(jiǎn)單高效,每次擴(kuò)縮容只需要?jiǎng)訉?duì)應(yīng)Solt(槽)的數(shù)據(jù),一般不會(huì)動(dòng)整個(gè)Redis實(shí)例
Codis數(shù)據(jù)路由:默認(rèn)分配1024個(gè)哈希槽,映射相關(guān)信息會(huì)被保存至Zookeeper集群。Proxy會(huì)緩存一份至本地,Redis集群實(shí)例發(fā)生變化時(shí),DashBoard更新Zookeeper和Proxy的映射信息
Redis Cluster和Codis數(shù)據(jù)遷移:Redis Cluster支持同步遷移,Codis支持同步遷移&&異步遷移
歡迎關(guān)注我的微信公眾號(hào)【Java3y】來聊聊Java面試,對(duì)線面試官系列持續(xù)更新中!
【對(duì)線面試官-移動(dòng)端】系列 一周兩篇持續(xù)更新中!
【對(duì)線面試官-電腦端】系列 一周兩篇持續(xù)更新中!
原創(chuàng)不易!!求三連!!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/123989.html
摘要:正確做法是給加索引,還有聯(lián)合索引,并不能避免全表掃描。 前言:有收獲的話請(qǐng)加顆小星星,沒有收獲的話可以 反對(duì) 沒有幫助 舉報(bào)三連 有心的同學(xué)應(yīng)該會(huì)看到我這個(gè)noteBook下面的其它知識(shí),希望對(duì)你們有些許幫助。 本文地址 時(shí)間點(diǎn):2017-11 一個(gè)16年畢業(yè)生所經(jīng)歷的php面試 一、什么是面試 二、面試準(zhǔn)備 1. 問:什么時(shí)候開始準(zhǔn)備? 2. 問:怎么準(zhǔn)備? 三、面試...
摘要:雖然有了十全的計(jì)劃,但如何高效率去記住上面那么多東西是一個(gè)大問題,看看我是怎么做的。 前言 前一篇文章講述了我在三月份毫無準(zhǔn)備就去面試的后果,一開始心態(tài)真的爆炸,但是又不服氣,一想到每次回來后家人朋友問我面試結(jié)果的期待臉,越覺得必須付出的行動(dòng)來證明自己了。 面經(jīng)傳送門:一個(gè)1年工作經(jīng)驗(yàn)的PHP程序員是如何被面試官虐的? 下面是我花費(fèi)兩個(gè)星期做的準(zhǔn)備,主要分三部分: 有計(jì)劃——計(jì)劃好...
摘要:正因?yàn)槿绱耍F(xiàn)在很多簡(jiǎn)歷上的項(xiàng)目經(jīng)歷的質(zhì)量都是參差不齊,同時(shí)有的項(xiàng)目經(jīng)歷又非常相似,面試官一眼就能知道你的項(xiàng)目到底是真是假。雖然以上三點(diǎn)原則不能包治百病,但是對(duì)很多同學(xué)來說應(yīng)該是蠻有益處的。閱讀本文大概需要 5 分鐘。作者:黃小斜showImg(https://user-gold-cdn.xitu.io/2019/3/30/169cdb4bd2cac24c);?作為一個(gè)程序員,想必大家曾經(jīng)都...
摘要:作為面試官,我是如何甄別應(yīng)聘者的包裝程度語(yǔ)言和等其他語(yǔ)言的對(duì)比分析和主從復(fù)制的原理詳解和持久化的原理是什么面試中經(jīng)常被問到的持久化與恢復(fù)實(shí)現(xiàn)故障恢復(fù)自動(dòng)化詳解哨兵技術(shù)查漏補(bǔ)缺最易錯(cuò)過的技術(shù)要點(diǎn)大掃盲意外宕機(jī)不難解決,但你真的懂?dāng)?shù)據(jù)恢復(fù)嗎每秒 作為面試官,我是如何甄別應(yīng)聘者的包裝程度Go語(yǔ)言和Java、python等其他語(yǔ)言的對(duì)比分析 Redis和MySQL Redis:主從復(fù)制的原理詳...
閱讀 994·2021-11-24 10:42
閱讀 3540·2021-11-19 11:34
閱讀 2681·2021-09-29 09:35
閱讀 2574·2021-09-09 09:33
閱讀 708·2021-07-26 23:38
閱讀 2554·2019-08-30 10:48
閱讀 1419·2019-08-28 18:07
閱讀 454·2019-08-26 13:44