elasticsearch文檔索引API(二)

上篇文章和讀者討論了Elasticsearch中文檔的索引API、自動創建索引、版本控制以及操作類型等問題,本文我們繼續上文的話題,來看看文檔索引的其他知識點。

本文是Elasticsearch系列的第九篇,閱讀前面的文章,有助於更好的理解本文:


ID自動生成

前面文章中,我們添加一個文檔執行的請求如下:

curl -X PUT "localhost:9200/twitter/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}
'

在type後面有一個1表示文檔的id,這個id也可以不寫,不寫默認會自動生成id,請求如下:

curl -X POST "localhost:9200/twitter/_doc?pretty" -H 'Content-Type: application/json' -d'
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}
'

在這個請求中,op_type會被自動設置爲create,執行結果如下:

可以看到,此時生成的id是一個字符串。

路由機制

Elasticsearch是一個分佈式系統,當一個文檔要被索引時,該文檔會被索引到系統中的某一個分片上,那麼到底是哪一個分片呢?在elasticsearch文檔讀寫模型一文中,我們簡單介紹過這個話題,但是沒有深入探究,這裏,就和讀者一起來探討下Elasticsearch中的路由機制。

分片位置的計算公式如下:

position=hash(routing) % numberofprimary_shards

在這裏,routing是一個任意字符串,Elasticsearch默認是將文檔的id作爲routing值,通過hash函數計算後,生成一個數字,這個數字再和主分片的總數取餘,得到一個處於 [0,number_of_primary_shards-1]區間內的數,該數字就是該文檔所在的分片。基於這樣的映射模式,Elasticsearch不支持索引創建成功後,修改分片數量,即分片數量要一開始就確定好,以後不能修改,否則會導致之前計算出來的position失效(即查找時找不到之前的文檔,因此numberofprimary_shards已經變了)。

默認情況下,這種路由機制會通過id將文檔平均分配在所有的分片上,這也導致了Elasticsearch無法確定一個文檔的具體位置,當有查詢請求時,它需要將查詢請求廣播到所有分片上去執行,這無疑降低的查詢的效率,對於這個問題,讀者可以使用自定義路由模式去解決,如下請求:

curl -X POST "localhost:9200/twitter/_doc/1?pretty&routing=sang" -H 'Content-Type: application/json' -d'
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}
'

開發者在添加文檔時指定路由,在查詢的時候也指定路由,這樣就可以避免Elasticsearch向所有的分片發送查詢請求,減少系統資源的消耗,查詢請求如下:

curl -X GET "localhost:9200/twitter/_search?pretty&routing=sang"

不過這種方式又會帶來另外一個問題,即路由相同的文檔總是被分在同一個分片上,無法做到將文檔平均分配在不同的分片上,因此,兩種不同的方式,需要讀者在開發中根據實際需求進行取捨。

分佈式

基於路由機制,索引操作將被定向到主分片上並執行,在主分片完成操作後,如果需要,再將更新操作分發到副本分片上。

Wait For Active Shardsedit

爲了提高寫入系統的 resiliency(彈性),索引操作可以配置爲在繼續索引之前等待一定數量的活動副本分片,如果所需的活動副本分片數沒有達到指定數量,那麼寫入操作必須等待並且重試,直到必需的副本分片數已啓動,或者發生了超時爲止。

在默認情況下,只需要主分片處於活動狀態,寫操作就會繼續,開發者可以通過設置 index.write.wait_for_active_shards來動態地在索引設置中覆蓋此默認值。要只是需要更改每個操作的此行爲,則可以使用 wait_for_active_shards請求參數,參數有效值是 all或任何不大於副本分片數的正整數,如果指定負值或者大於副本分片數的數字將拋出錯誤。

例如,假設我們有一個集羣,該集羣有三個節點A,B和C,我們創建一個索引,索引副本數設置爲3。默認情況下,索引操作將僅確保每個分片的主副本在操作之前可用。這意味着,即使B和C下線了,只要A託管了主副本分片,索引操作仍然執行。如果請求設置 wait_for_active_shards爲3(並且3個節點都已啓動),則索引操作將在執行之前需要3個活動副本分片,這是必須滿足的要求,因爲在集羣有3個活動節點,每個節點有一個分片的副本。但是,如果我們將 wait_for_active_shards設置爲 all(即4),索引操作將不會執行,因爲索引中的每個分片的4沒有四個副本,那麼該操作將超時,除非在集羣中啓動新節點以託管分片的第四個副本。

重要的是要注意,這個設置極大地減少了寫操作不寫入所需數量的副本分片的可能性,但是它不能完全消除這種可能性,因爲這種檢查在寫操作開始之前發生,一旦寫操作正在進行,複製仍然可能在任意數量的副本分片上失敗,但在主分片上成功。寫操作響應的 _shard字段顯示覆製成功/失敗的副本分片的數量。

Noop Updates

當使用索引API更新文檔時,即使文檔沒有更改,也始終創建新版本的文檔。如果這不可接受,請使用將 detectnoop設置爲true的update API 。此選項在索引API上不可用,因爲索引api無法提取舊的文檔,當然也無法和新的文檔進行比較,具體用法如下圖:

Timeout

執行索引操作時分配的主分片可能不可用,原因各種個樣,此時,索引操作將在主分片上等待最多1分鐘,然後失敗並響應錯誤。 timeout參數可以用於顯式指定等待時間。以下是將其設置爲5分鐘的示例:

curl -X PUT "localhost:9200/twitter/_doc/1?timeout=5m" -H 'Content-Type: application/json' -d'
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}
'

好了,本文就介紹到這裏,有問題歡迎留言討論。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章