ElastricSearch第二彈之分片原理
最近好多小伙伴后臺(tái)留言想看ES的后續(xù)內(nèi)容,今天它來(lái)了,廢話不多說(shuō),直接上干貨。
首先讓我們來(lái)了解一下 ES 中的分片概念:ES 支持 PB 級(jí)全文搜索,當(dāng)索引上的數(shù)據(jù)量太大的時(shí)候,ES 通過(guò)水平拆分的方式將一個(gè)索引上的數(shù)據(jù)拆分出來(lái)分配到不同的數(shù)據(jù)塊上,分布在多臺(tái)服務(wù)器上存儲(chǔ),拆分出來(lái)的數(shù)據(jù)庫(kù)塊稱之為一個(gè)分片。分片是一個(gè)功能完整的搜索引擎,它擁有使用一個(gè)節(jié)點(diǎn)上的所有資源的能力。這類似于 MySQL 的分庫(kù)分表,在一個(gè)多分片的索引中寫入數(shù)據(jù)時(shí),通過(guò)路由來(lái)確定具體寫入哪一個(gè)分片中,所以在創(chuàng)建索引的時(shí)候需要指定主分片的數(shù)量,并且主分片的數(shù)量一旦確定就不能修改(原因在下文中介紹),副本分片可以動(dòng)態(tài)修改。
shard(主分片):我們上邊所說(shuō)的分片其實(shí)就指的是主分片,主分片是數(shù)據(jù)的容器,文檔保存在主分片內(nèi),主分片又被分配到集群內(nèi)的各個(gè)節(jié)點(diǎn)里。每個(gè)shard都是一個(gè)lucene index。
replica(副本分片):副本就是對(duì)分片的 Copy ,同步存儲(chǔ)主分片的數(shù)據(jù)內(nèi)容。為了達(dá)到高可用,Master 節(jié)點(diǎn)會(huì)避免將主分片和副本分片放在同一個(gè)節(jié)點(diǎn)上,所以副本分片數(shù)的最大值是 N-1(其中 N 為節(jié)點(diǎn)數(shù))。
分片的數(shù)量和副本數(shù)量都是可以通過(guò)創(chuàng)建索引時(shí)的 Settings 來(lái)配置,ES 默認(rèn)為一個(gè)索引創(chuàng)建 5 個(gè)主分片, 并分別為每個(gè)分片創(chuàng)建一個(gè)副本分片。
PUT /myIndex { "settings" : { "number_of_shards" : 5, "number_of_replicas" : 1 } }
ES 通過(guò)分片的功能使得索引在規(guī)模上和性能上都得到提升,有了 shard 就可以橫向擴(kuò)展,存儲(chǔ)更多數(shù)據(jù),讓搜索和分析等操作分布到多臺(tái)服務(wù)器上去執(zhí)行,提升吞吐量和性能。
讀操作:搜索和返回?cái)?shù)據(jù)可以同時(shí)被主分片或副本分片所處理,所以當(dāng)你擁有越多的副本分片時(shí),也將擁有越高的吞吐量;
區(qū)分主副分片的原因:任何一個(gè)服務(wù)器隨時(shí)可能故障或宕機(jī),此時(shí)shard可能就會(huì)丟失,如果為每個(gè) shard 創(chuàng)建 replica 副本,當(dāng) shard 所在的服務(wù)器不可用時(shí),replica 可以提供備用服務(wù),這樣就保證了 ES 在失去某個(gè)節(jié)點(diǎn)的情況下不丟失任何數(shù)據(jù)。
舉例說(shuō)明
假設(shè)這時(shí)節(jié)點(diǎn) Node1 服務(wù)宕機(jī)了或者網(wǎng)絡(luò)不可用了,那么主節(jié)點(diǎn)上主分片 S0 也就不可用了。幸運(yùn)的是還存在另外兩個(gè)節(jié)點(diǎn)能正常工作,這時(shí) ES 會(huì)重新選舉新的主節(jié)點(diǎn),而且這兩個(gè)節(jié)點(diǎn)上存在我們所需要的 S0 的所有數(shù)據(jù)。我們會(huì)將 S0 的副本分片提升為主分片,這個(gè)提升主分片的過(guò)程是瞬間發(fā)生的。此時(shí)集群的狀態(tài)將會(huì)為 Yellow。為什么我們集群狀態(tài)是 Yellow 而不是 Green 呢?雖然我們擁有所有的 2 個(gè)主分片,但是同時(shí)設(shè)置了每個(gè)主分片需要對(duì)應(yīng)兩份副本分片,而此時(shí)只存在一份副本分片。所以集群不能為 Green 的狀態(tài)。如果我們同樣關(guān)閉了 Node2 ,我們的程序依然可以保持在不丟失任何數(shù)據(jù)的情況下運(yùn)行,因?yàn)?Node3 為每一個(gè)分片都保留著一份副本。如果我們重新啟動(dòng) Node1 ,集群可以將缺失的副本分片再次進(jìn)行分配,那么集群的狀態(tài)又將恢復(fù)到原來(lái)的正常狀態(tài)。如果 Node1 依然擁有著之前的分片,它將嘗試去重用它們,只不過(guò)這時(shí) Node1 節(jié)點(diǎn)上的分片不再是主分片而是副本分片了,如果期間有更改的數(shù)據(jù)只需要從主分片上復(fù)制修改的數(shù)據(jù)文件即可。
知識(shí)點(diǎn)補(bǔ)充:
集群狀態(tài)通過(guò) 綠,黃,紅 來(lái)標(biāo)識(shí):
綠色:集群健康完好,一切功能齊全正常,所有分片和副本都可以正常工作。
黃色:預(yù)警狀態(tài),所有主分片功能正常,但至少有一個(gè)副本是不能正常工作的。此時(shí)集群是可以正常工作的,但是高可用性在某種程度上會(huì)受影響。
紅色:集群不可正常使用。某個(gè)或某些分片及其副本異常不可用,這時(shí)集群的查詢操作還能執(zhí)行,但是返回的結(jié)果會(huì)不準(zhǔn)確。對(duì)于分配到這個(gè)分片的寫入請(qǐng)求將會(huì)報(bào)錯(cuò),最終會(huì)導(dǎo)致數(shù)據(jù)的丟失。
寫索引是只能寫在主分片上,然后同步到副本分片。
寫操作:對(duì)文檔的新建、索引和刪除請(qǐng)求,必須在主分片上面完成之后才能被復(fù)制到相關(guān)的副本分片。
如圖所示,上圖中有3個(gè)節(jié)點(diǎn),4個(gè)主分片,8個(gè)副本分片,一條數(shù)據(jù) ES 是根據(jù)什么規(guī)則寫到特定分片上的呢?首先這肯定不會(huì)是隨機(jī)的,否則將來(lái)要獲取文檔的時(shí)候我們就不知道從何處尋找了。實(shí)際上,這個(gè)過(guò)程是根據(jù)下面這個(gè)公式?jīng)Q定的:
shard = hash(routing) % number_of_primary_shards
Routing 是一個(gè)可變值,默認(rèn)是文檔的_id,也可以設(shè)置成一個(gè)自定義的值。Routing 通過(guò) Hash 函數(shù)生成一個(gè)數(shù)字,然后這個(gè)數(shù)字再除以 number_of_primary_shards (主分片的數(shù)量)后得到余數(shù)。這個(gè)在 0 到 number_of_primary_shards-1 之間的余數(shù),就是我們所尋求的文檔所在分片的位置。這就解釋了為什么我們要在創(chuàng)建索引的時(shí)候就確定好主分片的數(shù)量并且永遠(yuǎn)不會(huì)改變這個(gè)數(shù)量。因?yàn)槿绻麛?shù)量變化了,那么所有之前路由的值都會(huì)無(wú)效,文檔也再也找不到了。由于在 ES 集群中每個(gè)節(jié)點(diǎn)通過(guò)上面的計(jì)算公式都知道集群中的文檔的存放位置,所以每個(gè)節(jié)點(diǎn)都有處理讀寫請(qǐng)求的能力。在一個(gè)寫請(qǐng)求被發(fā)送到某個(gè)節(jié)點(diǎn)后,該節(jié)點(diǎn)即為前面說(shuō)過(guò)的協(xié)調(diào)節(jié)點(diǎn),協(xié)調(diào)節(jié)點(diǎn)會(huì)根據(jù)路由公式計(jì)算出需要寫到哪個(gè)分片上,再將請(qǐng)求轉(zhuǎn)發(fā)到該分片的主分片節(jié)點(diǎn)上。
ES 為了提高寫入的能力這個(gè)過(guò)程是并發(fā)寫的,同時(shí)為了解決并發(fā)寫的過(guò)程中數(shù)據(jù)沖突的問(wèn)題,ES 通過(guò)樂(lè)觀鎖的方式控制,每個(gè)文檔都有一個(gè) _version (版本)號(hào),當(dāng)文檔被修改時(shí)版本號(hào)遞增。一旦所有的副本分片都報(bào)告寫成功才會(huì)向協(xié)調(diào)節(jié)點(diǎn)報(bào)告成功,協(xié)調(diào)節(jié)點(diǎn)向客戶端報(bào)告成功。
舉例說(shuō)明
假如此時(shí)數(shù)據(jù)通過(guò)路由計(jì)算公式取余后得到的值是 shard=hash(routing)%4=0。
則具體流程如下:
客戶端向 ES1 節(jié)點(diǎn)(協(xié)調(diào)節(jié)點(diǎn))發(fā)送寫請(qǐng)求,通過(guò)路由計(jì)算公式得到值為 0,則當(dāng)前數(shù)據(jù)應(yīng)被寫到主分片 S0 上。
ES1 節(jié)點(diǎn)將請(qǐng)求轉(zhuǎn)發(fā)到 S0 主分片所在的節(jié)點(diǎn) ES3,ES3 接受請(qǐng)求并寫入到磁盤。
并發(fā)將數(shù)據(jù)復(fù)制到兩個(gè)副本分片 R0 上,其中通過(guò)樂(lè)觀并發(fā)控制數(shù)據(jù)的沖突。一旦所有的副本分片都報(bào)告成功,則節(jié)點(diǎn) ES3 將向協(xié)調(diào)節(jié)點(diǎn)報(bào)告成功,協(xié)調(diào)節(jié)點(diǎn)(ES1)向客戶端報(bào)告成功。
答案當(dāng)然是 no ,原因有以下兩點(diǎn):
(1)多個(gè) replica 可以提升搜索操作的吞吐量和性能,但是如果只是在相同節(jié)點(diǎn)數(shù)目的集群上增加更多的副本分片并不能提高性能,因?yàn)槊總€(gè)分片從節(jié)點(diǎn)上獲得的資源會(huì)變少,這個(gè)時(shí)候你就需要增加更多的硬件資源來(lái)提升吞吐量。
(2)更多的副本分片數(shù)提高了數(shù)據(jù)冗余量,保證了數(shù)據(jù)的完整性,但是根據(jù)上邊主副分片之間的交互原理可知,分片間的數(shù)據(jù)同步會(huì)占用一定的網(wǎng)絡(luò)帶寬,影響效率,所以索引的分片數(shù)和副本數(shù)也不是越多越好。
總結(jié):
將數(shù)據(jù)分片是為了提高可處理數(shù)據(jù)的容量和易于進(jìn)行水平擴(kuò)展,為分片做副本是為了提高集群的穩(wěn)定性和提高并發(fā)量。
副本是乘法,越多消耗越大,但也越保險(xiǎn)。分片是除法,分片越多,單分片數(shù)據(jù)就越少也越分散。
副本越多,集群的可用性就越高,但是由于每個(gè)分片都相當(dāng)于一個(gè) Lucene 的索引文件,會(huì)占用一定的文件句柄、內(nèi)存及 CPU。
阿Q正在將ES的知識(shí)做一個(gè)系統(tǒng)的學(xué)習(xí)與講解,后續(xù)還會(huì)持續(xù)輸出ES的相關(guān)知識(shí),如果你感興趣的話,可以關(guān)注“阿Q說(shuō)代碼”!你也可以后臺(tái)留言說(shuō)出你的疑惑,阿Q將會(huì)在后期的文章中為你解答。
Elasticsearch 實(shí)時(shí)流計(jì)算服務(wù) CS
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。