1.默認路由規則
默認情況下通過_routing字段進行路由,這個字段的值默認等於文檔_id字段
shard_num = hash(_routing) % num_primary_shards
2.自定義路由字段
PUT my_index/_doc/1?routing=user1&refresh=true { "title": "This is a document" } GET my_index/_doc/1?routing=user1
3._routing字段可用於查詢
GET my_index/_search { "query": { "terms": { "_routing": [ "user1" ] } } }
查詢時指定路由
GET my_index/_search?routing=user1,user2 { "query": { "match": { "title": "document" } } }
4.強制CRUD操作攜帶routing參數
自定義路由后,CRUD操作最好都要帶上routing參數,要不可能導致一個文檔被保存到多個分片上,可以通過設置強制所有CRUD操作必須帶routing參數,一旦設置后,不帶routing的操作將會報錯(throws a routing_missing_exception
.)。設置如下:
PUT my_index2 { "mappings": { "_doc": { "_routing": { "required": true } } } } PUT my_index2/_doc/1 { "text": "No routing value provided" }
5.設置了自定義路由,索引中_id字段的唯一性將得不到保障,即在不同的分片上可能會存在_id相同的文檔,所以,自定義路由最好通過自定義_id的方式,保證_id的唯一性。
6.優化路由的單點查詢問題
自定義路由可能會導致索引分配不均,大量的索引路由到一個分片上,導致這個分片的索引和查詢性能降低。為了解決這個問題,可以設置 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_partition_size 后,join field將不能被創建了,同時索引中的所有mapping必須設置_routing為required的。
查看每個分片文檔數量
GET _cat/shards/test07 test07 2 p STARTED 0 261b 192.168.0.16 testshshs_core test07 1 p STARTED 1 3.2kb 192.168.0.15 testshshs_first test07 0 p STARTED 1 3.2kb 192.168.0.16 testshshs_core
注意:網上說自定義路由選取的字段特別重要,需要考慮是否達到預期效果,不要是數據過於集中,可能會適得其反,這需要根據場景實際測試。
具體怎么選,我也沒有太多經驗,各位有好的想法,歡迎指點一下,非常感謝。
參考文檔:
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-routing-field.html