_routing字段介绍
一个document通过以下公式被路由到该索引下一个特定的分片:
shard_num = hash(_routing) % num_primary_shards
_routing的默认值是文档的_id或者文档的_parent ID。
自定义路由可以通过指定每个文档的routing值来实现。
例如:
curl -X PUT "http://localhost:9200/my_index/my_type/1?routing=user1&refresh=true" -H 'Content-Type: application/json' -d' { "title": "This is a document" } '
curl -X GET "http://localhost:9200/my_index/my_type/1?routing=user1"
1. 这个文档通过使用user1作为路由值,代替了ID
2. 相同的路由值需要在getting、deleting或者updating时提供。
这个_routing 域在查询时使用的例子:
curl -X GET "http://localhost:9200/my_index/_search" -H 'Content-Type: application/json' -d' { "query": { "terms": { "_routing": [ "user1" ] } } }'
使用自定义路由搜索
自定义路由可以降低搜索的冲击。一个请求被直接匹配路由值的分片上,而不是分散在索引的所有分片中。
curl -X GET "http://localhost:9200/my_index/_search?routing=user1,user2" -H 'Content-Type: application/json' -d' { "query": { "match": { "title": "document" } } } '
这个搜索将被在关联user1、user2路由值的分片上执行。
如果使用自定路由,这个路由值在索引、查新、删除、更新时提供时非常重要的。如果忘记这个路由值将会导致这个文档在更多的分片上查找。作为一个保障,这个_routing域可以配置在mapping中,以保障在CRUD操作中必须提供该值。
curl -X PUT "http://localhost:9200/my_index2" -H 'Content-Type: application/json' -d' { "mappings": { "my_type": { "_routing": { "required": true } } } } ' curl -X PUT "http://localhost:9200/my_index2/my_type/1" -H 'Content-Type: application/json' -d' { "text": "No routing value provided" } '
1. 路由必须在my_type文档中
2. 这个索引请求将会抛出routing_missing_exception异常。
当自定了索引文档的_routing,则_id的唯一性将不能保证其在索引下所有分片中的唯一性。事实上,即使一个拥有相同_id的文档同样可能被分配在不通的分片中通过不同的_routing值。这就要求用户来保证这个IDS在全索引下的唯一性。
路由索引分区
一个索引可以配置自定义路由到一个分片子集的路由值而不是单一的分片。这个将减小集群不均衡的风险,同时,也可以减小搜索的压力。
这个可以在创建索引时,配置index.routing_partition_size参数完成。随着分区值的增加,分布更加均匀的数据将导致搜索在更多分片完成(这个其实是增加了搜索成本的)。
当提供了这个参数,则计算公式将变成:
shard_num = (hash(_routing) + hash(_id) % routing_partition_size) % num_primary_shards
这样,通过_routing域计算出一个分片集合,然后通过_id来选择分片集合中的一个分片。
为了保证这个特性,index.routing_partition_size值必须是大于1同时小雨index.number_of_shards的值。
一旦应用,这个索引将有以下限制:
- Mapping中不能配置父子关系
- 在索引的映射中必须有_routing字段。
参考链接:https://www.elastic.co/guide/en/elasticsearch/reference/5.6/mapping-routing-field.html