介紹
ES里面的每一個(gè)索引(Index)由多個(gè)shard組成门扇,每一個(gè)shard有多個(gè)副本。這些副本被稱為"同步組"偿渡。當(dāng)增加或者刪除文檔時(shí)臼寄,這些副本之間必須保持同步,以便讓所有副本都能包含相同的文檔溜宽。如果同步失敗吉拳,有可能會(huì)導(dǎo)致從一個(gè)副本讀的結(jié)果和從另外一個(gè)副本上讀的結(jié)果不一致。在shard的所有副本之間保持?jǐn)?shù)據(jù)同步并同時(shí)對(duì)外提供一致的讀服務(wù)适揉,我們這樣的處理過程稱之為“數(shù)據(jù)復(fù)制模型"留攒。
ES的“數(shù)據(jù)復(fù)制模型”是一種“主-備”式的模型煤惩,這種模型在微軟的研究論文中有專門的介紹×堆基于這種模型魄揉,“同步組" 的所有副本中間會(huì)有一個(gè)專門的“Primary shard”角色,除了”Primary shard“之外的其余副本都被稱為”replica shard“拭宁。 Primary shard是所有文檔的索引操作(文檔寫操作)的入口點(diǎn), 其負(fù)責(zé)索引操作的校驗(yàn)洛退,確保這些索引操作是正確且合法的。當(dāng)索引操作校驗(yàn)通過后, primary shard會(huì)負(fù)責(zé)把索引操作復(fù)制并傳遞給replica shard杰标,讓“同步組”里面所有副本會(huì)進(jìn)行相同的寫操作兵怯,進(jìn)而保持所有副本上包含的文檔是一致的。
基本寫模型
根據(jù)文檔的doc ID腔剂,ES首先會(huì)識(shí)別出來(lái)一個(gè)文檔的索引操作應(yīng)該由哪個(gè)“同步組”來(lái)執(zhí)行媒区,這個(gè)“同步組”也就是存儲(chǔ)該文檔的目的容器。在“同步組"被識(shí)別出來(lái)后掸犬,該文檔的索引操作就被傳遞給“同步組”中的當(dāng)前primary shard袜漩。Primary shard 負(fù)責(zé)校驗(yàn)并傳遞同樣的文檔索引操作給其他的relica shard。因?yàn)閞eplica shard有可能會(huì)因?yàn)楦鞣N可能原因造成離線登渣,所以ES并不要求primary shard一定要復(fù)制操作給所有的replica shard噪服。事實(shí)上,primary shard維護(hù)了一個(gè)可以接收索引操作的replica shard列表胜茧。這個(gè)列表被稱為“in-sync 副本列表”, 列表數(shù)據(jù)由master node來(lái)維護(hù)粘优。 primary shard需要把文檔的索引操作復(fù)制傳遞給in-sync列表中每一個(gè)relica shard。
下面是primary shard處理的基本流程:
1.校驗(yàn)操作請(qǐng)求呻顽,如果有結(jié)構(gòu)類的錯(cuò)誤(例如雹顺,object filed 卻存儲(chǔ)了一個(gè)數(shù)字),就拒絕此請(qǐng)求
2.如果校驗(yàn)通過廊遍,本地先執(zhí)行索引操作嬉愧,例如索引或者刪除文檔。在本地操作過程中喉前,也會(huì)做一些校驗(yàn)没酣,如果校驗(yàn)失敗(例如keyword字段的值太長(zhǎng)卵迂,超過Lucene索引長(zhǎng)度限制)裕便,也會(huì)拒絕請(qǐng)求。
3.轉(zhuǎn)發(fā)索引操作給當(dāng)前in-sync里面的所有replica shard见咒。如果有多個(gè)replica shard偿衰,轉(zhuǎn)發(fā)操作會(huì)并行來(lái)執(zhí)行
4.當(dāng)所有replica 都成功執(zhí)行了和本地一樣的索引操作,并且給primary shard 發(fā)回了成功確認(rèn),primary shard 就會(huì)發(fā)成功確認(rèn)給客戶端下翎。
異常處理
在執(zhí)行索引操作的過程中缤言,每一步都可能會(huì)出現(xiàn)問題,比如磁盤壞了视事、node down掉了胆萧、node之間網(wǎng)絡(luò)不通了、或者配置錯(cuò)誤了等等郑口,也許會(huì)導(dǎo)致索引操作在primary shard執(zhí)行成功鸳碧,在一個(gè)或者多個(gè)replica shard 卻執(zhí)行失敗了。這些都是失敗的情況犬性,雖然并不是經(jīng)常出現(xiàn)瞻离,但是primary shard必須處理各種異常的情況。
一種場(chǎng)景是primary shard自己出問題了乒裆,在這種情況下 套利,primary shard 所在的node會(huì)發(fā)消息給master node告知這種異常情況出現(xiàn)了 。索引操作會(huì)等待master node選出新的primary shard并把索引操作轉(zhuǎn)發(fā)給新的primary shard鹤耍。當(dāng)然這種等待不是無(wú)限期的肉迫,缺省會(huì)等待1分鐘。當(dāng)然master node也不是被動(dòng)等待通知稿黄,master node會(huì)主動(dòng)持續(xù)監(jiān)測(cè)node的健康狀態(tài)季眷,并根據(jù)健康狀態(tài)來(lái)決定是否選出新的primary shard削葱。一種典型的情況就是當(dāng)primary shard所在node 網(wǎng)絡(luò)不通的時(shí)候,master node會(huì)認(rèn)為 primary shard所在node可能down死掉了,就會(huì)選出新的primary shard尤仍,并更新in-sync 列表氢妈。
另外一種場(chǎng)景就是索引操作在primary shard上執(zhí)行成功非竿,但是在replica shard執(zhí)行卻失敗了型豁。當(dāng)然被定義失敗的各種情況有很多,比如索引操作在replica上的確失敗了(比如replica shard所在硬盤出問題了)互纯、primary shard和replica shard之間網(wǎng)絡(luò)原因?qū)е滤饕僮髡?qǐng)求沒有到達(dá)replica shard瑟幕、或者primary shard沒有收到replica shard的成功確認(rèn)等等。這些復(fù)雜的情況導(dǎo)致的共同結(jié)果就是:primary shard 沒有收到in-sync列表里面的所有replica shard的索引操作成功確認(rèn)留潦。為了解決這樣的問題只盹,primary shard 會(huì)發(fā)消息給master node ,請(qǐng)求master node 刪除出問題的replica shard兔院。當(dāng)primary shard 收到master node 成功刪除問題replica shard的確認(rèn)消息時(shí)殖卑,primary shard會(huì)發(fā)索引操作成功確認(rèn)給客戶端。要注意的是秆乳,master node同時(shí)會(huì)通知另外一個(gè)node會(huì)構(gòu)建一個(gè)新的replica shard懦鼠,以保證系統(tǒng)處在一個(gè)健康狀態(tài)。
當(dāng)轉(zhuǎn)發(fā)操作請(qǐng)求給replica shards的時(shí)候屹堰,primary shard會(huì)根據(jù)replica shard的響應(yīng)情況來(lái)確認(rèn)自己仍然是活躍的primary shard肛冶。某些情況下,因?yàn)榫W(wǎng)絡(luò)原因扯键,primary shard 也許已經(jīng)被master node給降級(jí)了睦袖,但是primary shard還沒收到這種降級(jí)通知,所以會(huì)繼續(xù)處理進(jìn)來(lái)的索引操作請(qǐng)求荣刑。當(dāng)老的primary shard把索引操作請(qǐng)求轉(zhuǎn)發(fā)給其他replica shard時(shí)馅笙,replica shard發(fā)現(xiàn)請(qǐng)求來(lái)自于一個(gè)已經(jīng)不合法的primary shard,就會(huì)拒絕請(qǐng)求并發(fā)響應(yīng)給這個(gè)不合法的primary shard厉亏。當(dāng)這個(gè)不合法的primary shard收到拒絕的響應(yīng)時(shí)候董习,就會(huì)和master node聯(lián)系,獲取最新的狀態(tài)信息爱只。在從master node發(fā)回的信息中皿淋,老的primary shard發(fā)現(xiàn)自己已經(jīng)被“推翻統(tǒng)治”,就會(huì)把索引操作請(qǐng)求轉(zhuǎn)發(fā)給新的primary shard恬试。
沒有replica shard時(shí)窝趣,情況會(huì)怎么樣?
因?yàn)楦鞣N原因训柴,所有的replica shards可能都會(huì)失效哑舒。在這種情況下,primary 會(huì)自己處理索引操作幻馁,而不會(huì)等待任何外部的確認(rèn)(因?yàn)闆]有replica shards了)洗鸵。看起來(lái)似乎有點(diǎn)怪怪的宣赔,這主要是因?yàn)閜rimary shards不能自己定義而只能依賴master nodereplica shards是否失敗预麸。這就意味著,master node知道primary shards 是唯一的正常工作的副本儒将。我們要保證master node不會(huì)把其他任何過期的shard 副本定義成新的primary吏祸,也保證發(fā)到primary shard的索引操作請(qǐng)求不會(huì)丟失。但是不可否認(rèn)钩蚊,primary shard上的物理硬件出問題了贡翘,肯定也會(huì)導(dǎo)致數(shù)據(jù)丟失。
基本讀模型
ES中的讀可以是通過ID的輕量級(jí)查找砰逻,也可以是重量級(jí)的非常消耗CPU的復(fù)雜聚合計(jì)算鸣驱。ES的“主-備”模型的優(yōu)雅之處在于它保持所有副本的數(shù)據(jù)一致的,這樣“同步組”中的任何單個(gè)副本都可以對(duì)外提供讀服務(wù)蝠咆。
當(dāng)集群中的一個(gè)node收到讀請(qǐng)求時(shí)踊东,該node負(fù)責(zé)轉(zhuǎn)發(fā)讀請(qǐng)求給相關(guān)的shards北滥、聚合shards的響應(yīng)并把響應(yīng)發(fā)送給客戶端。我們這樣的node稱之為本次請(qǐng)求的協(xié)調(diào)node闸翅。協(xié)調(diào)node上的基本讀的處理流程如下:
1.根據(jù)請(qǐng)求再芋,解析出來(lái)要轉(zhuǎn)發(fā)的“同步組”。多數(shù)搜索需要查詢多個(gè)“同步組"坚冀,每個(gè)"同步組”是可能包含了搜索結(jié)果的一部分?jǐn)?shù)據(jù)济赎。但是如果是根據(jù)id檢索一個(gè)文檔,可以根據(jù)routing算法记某,計(jì)算出一個(gè)包含該文檔的“同步組”司训。
2.從每一個(gè)要轉(zhuǎn)發(fā)“同步組”里面選出一個(gè)活躍的shard。這個(gè)shard可以是primary液南,也可以是replica壳猜。缺省情況下,ES使用round robin的策略在“同步組"里面選擇shard滑凉。把請(qǐng)求轉(zhuǎn)發(fā)給選出來(lái)的shards
3.合并各個(gè)shard的響應(yīng)并發(fā)響應(yīng)給客戶端蓖谢。要注意的是,如果根據(jù)id檢索文檔譬涡,因?yàn)檗D(zhuǎn)發(fā)shard是一個(gè)闪幽,所以就不存在合并的過程了。
異常處理
當(dāng)一個(gè)shard沒有成功執(zhí)行讀請(qǐng)求涡匀、轉(zhuǎn)發(fā)響應(yīng)給協(xié)調(diào)node時(shí)盯腌,協(xié)調(diào)node會(huì)從該shard所在的”同步組“中選擇另外一個(gè)shard,然后把讀請(qǐng)求轉(zhuǎn)發(fā)給它陨瘩。重復(fù)性的“失敗-選擇”可能會(huì)導(dǎo)致最后“同步組"里面沒有shard 可用腕够。在某些情況下,ES更青睞快速響應(yīng)舌劳,而不是搜索結(jié)果的完整性帚湘,例如_search。即使缺失了部分查詢結(jié)果甚淡,ES也希望能快速響應(yīng)給客戶端大诸,而不是等待問題解決(搜索結(jié)果是否完整會(huì)在響應(yīng)頭有體現(xiàn))。
一些優(yōu)雅的點(diǎn)
基本讀贯卦、基本寫流程定義了ES作為一個(gè)系統(tǒng)资柔,是如何支持讀和寫操作的。但是實(shí)踐中撵割,讀寫操作可能是同時(shí)并發(fā)執(zhí)行的贿堰,所以讀、寫流程是相互影響的啡彬。此模型有一些優(yōu)雅的點(diǎn)羹与,如下:
1.高效讀
正常情況下故硅,每次讀請(qǐng)求操作只會(huì)被“同步組”里面shard執(zhí)行一次。在異常情況下纵搁,有可能會(huì)出現(xiàn)“同步組”里面的多個(gè)shard執(zhí)行了多次讀操作契吉,例如協(xié)調(diào)node在shard沒有響應(yīng)的情況下,會(huì)重新選擇另外一個(gè)shard诡渴,再次發(fā)出讀請(qǐng)求操作。
2.未確認(rèn)讀
因?yàn)閜rimary shard首先在本地執(zhí)行索引操作菲语,然后才轉(zhuǎn)發(fā)索引操作給replica shard妄辩。在索引操作完全確認(rèn)之前,primary shard執(zhí)行了一個(gè)讀請(qǐng)求操作山上,就能讀到還沒確認(rèn)的數(shù)據(jù)眼耀。
3.缺省兩個(gè)副本
在一些基于投票的系統(tǒng)中,要實(shí)現(xiàn)容錯(cuò)佩憾,有可能最少需要的副本數(shù)是3. 但是基于ES的模型哮伟,僅維護(hù)兩個(gè)副本,就可以實(shí)現(xiàn)容錯(cuò)妄帘。
失敗
失敗的時(shí)候楞黄,可能會(huì)出現(xiàn)下面的情況:
1.單個(gè)shard有可能會(huì)讓索引操作執(zhí)行的更慢
因?yàn)閜rimary shard需要等待in-sync里面所有replica shard執(zhí)行完并響應(yīng)才能發(fā)確認(rèn)給客戶端,所以任何一個(gè)處理慢的shard都會(huì)拉低本次索引操作的處理速度抡驼。這是為了實(shí)現(xiàn)前面提到的高效讀而付出的成本代價(jià)鬼廓。當(dāng)然,單個(gè)慢的shard也會(huì)拉低路由到此shard上的讀請(qǐng)求操作處理速度致盟,進(jìn)而影響那次search(因?yàn)閟earch是由多個(gè)shard的讀請(qǐng)求組成)碎税。
2.臟讀
一個(gè)孤立的primary shard可能會(huì)暴露將不會(huì)被確認(rèn)的但是已經(jīng)被寫到本地的數(shù)據(jù)。這是因?yàn)楣铝⒌膒rimary只有在發(fā)索引操作請(qǐng)求給replica或者跟master node時(shí)才能知道自己已經(jīng)被孤立了馏锡。因?yàn)閿?shù)據(jù)已經(jīng)被寫入本地了雷蹂,如果此時(shí)有讀請(qǐng)求過來(lái),讀請(qǐng)求就可能會(huì)讀到剛剛已經(jīng)寫進(jìn)去的數(shù)據(jù)杯道。為了降低這種風(fēng)險(xiǎn)匪煌,primary 會(huì)定期(缺省每1秒)ping master node,如果發(fā)現(xiàn)已經(jīng)找不到master了党巾,就會(huì)拒絕索引操作虐杯。