咱们知道,一个index的数据会被分红多个分片shard,因此说一个document只能存在与一个shard中。当客户端建立document的时候,elasticsearch此时就须要决定这个document是放在这个index的哪一个分片shard中,这个过程就称之为document routing,即数据路由。算法
算法;shard = hash(routing) % number_of_primary_shards
举个例子,假设一个index有5个primary shard(p0,p1,p2,p3,p4)。每次对index的一个document进行增删改查的时候,都会带过来一个routing number,默认就是这个documentd的_id(多是手动指定,也能够是自动生成),routing=_id。
假设_id=1,那么就会将routing=1这个routing值传入一个hash函数中,产生一个routing值的hash值,假设hash(routing)=21,而后将hash函数产生的值对这个index的primary shard的数量求余数,21 % 5 = 1
也就决定了这个document就放在p1上。负载均衡
注意:此这个计算过程就能够看出,决定一个document在哪一个shard上,最重要的值就是routing值,默认是_id,也能够手动指定,相同的routing值,每次过来,从hash函数中生成的hash值必定是相同的。不管最后计算的hash值是多少,对number_of_primary_shards求余数,结果必定在0~number_of_primary_shards之间。elasticsearch
默认的routing就是_id,也能够在发送请求的时候手动指定。
下面作一个比较有趣的例子
先测试一下默认的routing函数
//先插入数据 PUT /test_index/_doc/10 { "test_field": "test10 routing _id" } //获取数据不带routing参数 GET /test_index/_doc/10 { "_index" : "test_index", "_type" : "_doc", "_id" : "10", "_version" : 1, "_seq_no" : 0, "_primary_term" : 1, "found" : true, "_source" : { "test_field" : "test10 routing _id" } } //获取数据带routing参数 参数值为_id GET /test_index/_doc/10?routing=10 { "_index" : "test_index", "_type" : "_doc", "_id" : "10", "_version" : 1, "_seq_no" : 0, "_primary_term" : 1, "found" : true, "_source" : { "test_field" : "test10 routing _id" } }
再来测试一下带上routing值,为了看到效果咱们让_id的值与routing的值不同性能
//先插入数据 PUT /test_index/_doc/11?routing=12 { "test_field": "test routing not _id" } //获取数据不带routing参数 GET /test_index/_doc/11 { "_index" : "test_index", "_type" : "_doc", "_id" : "11", "found" : false } //获取数据带routing参数 参数值为自定义的值 GET /test_index/_doc/11?routing=12 { "_index" : "test_index", "_type" : "_doc", "_id" : "11", "_version" : 1, "_seq_no" : 9, "_primary_term" : 1, "_routing" : "12", "found" : true, "_source" : { "test_field" : "test routing not _id" } }
手动指定的routing value是颇有用的,能够保证某一类的document必定被路由到一个shard中去,那么在后续进行应用级别的负载均衡以及提高批量读取的性能的时候,是颇有帮助的。测试
经过上面的分析,特别是路由算法,咱们不难知道,在咱们最开始建立索引的时候,肯定了primary shard的数量,以后根据路由算法,每一个document就被路由到了指定的shard上面,以后的各类操做路由规则都是同样的。试想一下,若是咱们改变了primary shard的数量,那么路由算法取余的时候值可能就跟以前的不同了,就会被路由到其它的shard上面去,就会致使数据混乱,本该已经存在的document,可能经过查询根本查不到,某种程度上说这也会形成数据的丢失。code