ElasticSearch 數據路由原理+增刪改查內部原理+寫一致性原理以及quorum機制

一.document數據路由原理java

(1)document路由到shard上是什麼意思?node

 

(2)路由算法:shard = hash(routing) % number_of_primary_shards算法

舉個例子,一個index有3個primary shard,P0,P1,P2json

每次增刪改查一個document的時候,都會帶過來一個routing number,默認就是這個document的_id(多是手動指定,也多是自動生成)
routing = _id,假設_id=1api

會將這個routing值,傳入一個hash函數中,產出一個routing值的hash值,hash(routing) = 21
而後將hash函數產出的值對這個index的primary shard的數量求餘數,21 % 3 = 0
就決定了,這個document就放在P0上。數組

決定一個document在哪一個shard上,最重要的一個值就是routing值,默認是_id,也能夠手動指定,相同的routing值,每次過來,從hash函數中,產出的hash值必定是相同的性能優化

不管hash值是幾,不管是什麼數字,對number_of_primary_shards求餘數,結果必定是在0~number_of_primary_shards-1之間這個範圍內的。0,1,2。數據結構

(3)_id or custom routing value負載均衡

默認的routing就是_id
也能夠在發送請求的時候,手動指定一個routing value,好比說put /index/type/id?routing=user_idjvm

手動指定routing value是頗有用的,能夠保證說,某一類document必定被路由到一個shard上去,那麼在後續進行應用級別的負載均衡,以及提高批量讀取的性能的時候,是頗有幫助的

(4)primary shard數量不可變的謎底

二.document增刪改查內部原理

1.增刪改

 

(1)客戶端選擇一個node發送請求過去,這個node就是coordinating node(協調節點)
(2)coordinating node,對document進行路由,將請求轉發給對應的node(有primary shard)
(3)實際的node上的primary shard處理請求,而後將數據同步到replica node
(4)coordinating node,若是發現primary node和全部replica node都搞定以後,就返回響應結果給客戶端

 

 2.查

 

(1)客戶端發送請求到任意一個node,成爲coordinate node
(2)coordinate node對document進行路由,將請求轉發到對應的node,此時會使用round-robin隨機輪詢算法,在primary shard以及其全部replica中隨機選擇一個,讓讀請求負載均衡
(3)接收請求的node返回document給coordinate node
(4)coordinate node返回document給客戶端
(5)特殊狀況:document若是還在創建索引過程當中,可能只有primary shard有,任何一個replica shard都沒有,此時可能會致使沒法讀取到document,可是document完成索引創建以後,primary shard和replica shard就都有了

 

 

三.寫一致性原理以及quorum機制

 

(1)consistency,one(primary shard),all(all shard),quorum(default)

 

咱們在發送任何一個增刪改操做的時候,好比說put /index/type/id,均可以帶上一個consistency參數,指明咱們想要的寫一致性是什麼?
put /index/type/id?consistency=quorum

 

one:要求咱們這個寫操做,只要有一個primary shard是active活躍可用的,就能夠執行
all:要求咱們這個寫操做,必須全部的primary shard和replica shard都是活躍的,才能夠執行這個寫操做
quorum:默認的值,要求全部的shard中,必須是大部分的shard都是活躍的,可用的,才能夠執行這個寫操做

 

(2)quorum機制,寫以前必須確保大多數shard均可用,int( (primary + number_of_replicas) / 2 ) + 1,當number_of_replicas>1時才生效

 

quroum = int( (primary + number_of_replicas) / 2 ) + 1
舉個例子,3個primary shard,number_of_replicas=1,總共有3 + 3 * 1 = 6個shard
quorum = int( (3 + 1) / 2 ) + 1 = 3
因此,要求6個shard中至少有3個shard是active狀態的,才能夠執行這個寫操做

 

(3)若是節點數少於quorum數量,可能致使quorum不齊全,進而致使沒法執行任何寫操做

 

3個primary shard,replica=1,要求至少3個shard是active,3個shard按照以前學習的shard&replica機制,必須在不一樣的節點上,若是說只有2臺機器的話,是否是有可能出現說,3個shard都無法分配齊全,此時就可能會出現寫操做沒法執行的狀況

 

es提供了一種特殊的處理場景,就是說當number_of_replicas>1時才生效,由於假如說,你就一個primary shard,replica=1,此時就2個shard

 

(1 + 1 / 2) + 1 = 2,要求必須有2個shard是活躍的,可是可能就1個node,此時就1個shard是活躍的,若是你不特殊處理的話,致使咱們的單節點集羣就沒法工做

 

(4)quorum不齊全時,wait,默認1分鐘,timeout,100,30s

 

等待期間,指望活躍的shard數量能夠增長,最後實在不行,就會timeout
咱們其實能夠在寫操做的時候,加一個timeout參數,好比說put /index/type/id?timeout=30,這個就是說本身去設定quorum不齊全的時候,es的timeout時長,能夠縮短,也能夠增加

 

 

 

 

 四.bulk api的奇特json格式與底層性能優化關係

 

bulk api奇特的json格式


{"action": {"meta"}}\n
{"data"}\n
{"action": {"meta"}}\n
{"data"}\n

[{
"action": {

},
"data": {

}
}]


 


 

一、bulk中的每一個操做均可能要轉發到不一樣的node的shard去執行

二、若是採用比較良好的json數組格式

容許任意的換行,整個可讀性很是棒,讀起來很爽,es拿到那種標準格式的json串之後,要按照下述流程去進行處理

(1)將json數組解析爲JSONArray對象,這個時候,整個數據,就會在內存中出現一份如出一轍的拷貝,一份數據是json文本,一份數據是JSONArray對象
(2)解析json數組裏的每一個json,對每一個請求中的document進行路由
(3)爲路由到同一個shard上的多個請求,建立一個請求數組
(4)將這個請求數組序列化
(5)將序列化後的請求數組發送到對應的節點上去

三、耗費更多內存,更多的jvm gc開銷

咱們以前提到過bulk size最佳大小的那個問題,通常建議說在幾千條那樣,而後大小在10MB左右,因此說,可怕的事情來了。假設說如今100個bulk請求發送到了一個節點上去,而後每一個請求是10MB,100個請求,就是1000MB = 1GB,而後每一個請求的json都copy一份爲jsonarray對象,此時內存中的佔用就會翻倍,就會佔用2GB的內存,甚至還不止。由於弄成jsonarray以後,還可能會多搞一些其餘的數據結構,2GB+的內存佔用。

佔用更多的內存可能就會積壓其餘請求的內存使用量,好比說最重要的搜索請求,分析請求,等等,此時就可能會致使其餘請求的性能急速降低
另外的話,佔用內存更多,就會致使java虛擬機的垃圾回收次數更多,跟頻繁,每次要回收的垃圾對象更多,耗費的時間更多,致使es的java虛擬機中止工做線程的時間更多

四、如今的奇特格式

{"action": {"meta"}}\n
{"data"}\n
{"action": {"meta"}}\n
{"data"}\n

(1)不用將其轉換爲json對象,不會出現內存中的相同數據的拷貝,直接按照換行符切割json
(2)對每兩個一組的json,讀取meta,進行document路由
(3)直接將對應的json發送到node上去

五、最大的優點在於,不須要將json數組解析爲一個JSONArray對象,造成一份大數據的拷貝,浪費內存空間,儘量地保證性能

相關文章
相關標籤/搜索