當索引一個文檔的時候,文檔會被存儲到一個主分片中。 Elasticsearch 如何知道一個文檔應該存放到哪個分片中呢?當我們創建文檔時,它如何決定這個文檔應當被存儲在分片 1 還是分片 2 中呢?
首先這肯定不會是隨機的,否則將來要獲取文檔的時候我們就不知道從何處尋找了。實際上,這個過程是根據下面這個公式決定的:
shard_num = hash(routing) % number_of_primary_shards
routing 是一個可變值,默認是文檔的 _id ,也可以設置成一個自定義的值。 routing 通過 hash 函數生成一個數字,然后這個數字再除以 number_of_primary_shards (主分片的數量)后得到 余數 。這個分布在 0 到 number_of_primary_shards-1 之間的余數,就是我們所尋求的文檔所在分片的位置。
這就解釋了為什么我們要在創建索引的時候就確定好主分片的數量 並且永遠不會改變這個數量:因為如果數量變化了,那么所有之前路由的值都會無效,文檔也再也找不到了。
自定義routing: 表示文檔根據'kimchy'進行路由
POST twitter/mytype?routing=kimchy
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
根據routing值查詢
GET twitter/mytype/1?routing=kimchy
或者
GET my_index/mytype/_search
{
"query": {
"terms": {
"_routing": [ "kimchy" ]
}
}
}
將請求發送到主動的routing上
GET my_index/_search?routing=user1,user2
{
"query": {
"match": {
"title": "document"
}
}
}
指定CRUD操作必須指定routing值
put 10.127.0.1:9200/myrouting/_mapping
{
"myrouting": {
"mappings": {
"my_type": {
"_routing": { "required": true },
"properties": {
"name": { "type": "keyword" }
}
}
}
}
}
請求時不指定routing值錯誤演示
post 10.127.0.1:9200/myrouting/my_type/1
{
"error": {
"root_cause": [
{
"type": "routing_missing_exception",
"reason": "routing is required for [myrouting]/[my_type]/[1]",
"index_uuid": "_na_",
"index": "myrouting"
}
],
"type": "routing_missing_exception",
"reason": "routing is required for [myrouting]/[my_type]/[1]",
"index_uuid": "_na_",
"index": "myrouting"
},
"status": 400
}
所有的文檔 API( get 、 index 、 delete 、 bulk 、 update 以及 mget )都接受一個叫做 routing 的路由參數 ,通過這個參數我們可以自定義文檔到分片的映射。一個自定義的路由參數可以用來確保所有相關的文檔——例如所有屬於同一個用戶的文檔——都被存儲到同一個分片中。
而我們為什么會需要自定義的Routing模式呢?首先默認的Routing模式在很多情況下都是能滿足我們的需求的——平均的數據分布、對我們來說是透明的、多數時候性能也不是問題。但是在我們更深入地理解我們的數據的特征之后,使用自定義的Routing模式可能會給我們帶來更好的性能。
自定義路由可能會導致索引分配不均,大量的索引路由到一個分片上,導致這個分片的索引和查詢性能降低。為了解決這個問題,可以設置 routing_partition_size 參數。(注意這是一個索引級別的設置,只能在創建索引的時候設置。隨着分區大小的增加,數據分布越均勻,代價是每個請求必須搜索更多分片)這樣routing將路由到一組分片,然后_id字段在決定文檔保存到那一個分片上。由於這個原因。routing_partition_size的值必須是一個大於1但是小於number_of_shards設置的分片數量的一個整數。具體公式如下:
shard_num = (hash(_routing) + hash(_id) % routing_partition_size) % num_primary_shards
請求發到某個節點之后,該節點成為協調節點,計算好routing值之后轉發到指定的節點(增刪改需求發送到primary shard,查詢需求主分片和副本分片都可以,對於查詢需求發送到主分片還是副本分片是通過輪詢查詢中所有的分片),然后將數據返回到協調節點,協調節點將數據返回給客戶端