1、Elasticsearch document数据路由原理

我们知道,一个index的数据会被分成多个分片shard,所以说一个document只能存在与一个shard中。当客户端创建document的时候,elasticsearch此时就需要决定这个document是放在这个index的哪个分片shard中,这个过程就称之为document routing,即数据路由。

2、document数据路由算法

算法;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之间。

3、routing实战

默认的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中去,那么在后续进行应用级别的负载均衡以及提升批量读取的性能的时候,是很有帮助的。

4、主分片数量不可变

通过上面的分析,特别是路由算法,我们不难知道,在我们最开始创建索引的时候,确定了primary shard的数量,之后根据路由算法,每个document就被路由到了指定的shard上面,之后的各种操作路由规则都是一样的。试想一下,如果我们改变了primary shard的数量,那么路由算法取余的时候值可能就跟之前的不一样了,就会被路由到其它的shard上面去,就会导致数据混乱,本该已经存在的document,可能通过查询根本查不到,某种程度上说这也会造成数据的丢失。


郑国
301 声望88 粉丝