概念
我们知道,一个index的数据会被分为多片,每片都放在一个shard中.所以,一个document只能存在于一个shard中.
当客户端创建document的时候,es此时就要决定这个document是要放在哪一个shard中. 这个过程就被是document routing 数据路由
路由算法
1 | shard = hash(routing) % number_of_primary_shards |
每次增删改查一个document的时候,都会带过来一个routing number,默认的就是这个document的id(可以是手动指定,也可以是自动生成).
举个例子,现在有一个index,有3个shard P0 P1 P2,假设routing = _id, _id = 1, es会将这个routing值传入一个hash函数中,返回一个routing值的hash值, 假如hash(routing) = 21, 然后将hash函数产出的值对这个index的primary shard的数量求余数, 21 % 3 = 0,就决定了这个document应该放在P0上面.
决定一个document在哪个shard上,最重要的一个值就是routing值,默认是id也可以手动指定,相同的routing值,每次过来,从hash函数中产出的hash值一定是相同的
无论hash值是多少,无论是什么数字,对number_of_primary_shard求余数,结果一定是在0~number_of_primary_shard-1 这个范围之内的.
再来想想我们之前说过,primary shard的数量在创建完index之后是不能去修改的,还是上面那个例子,数据被放到了P0中,如果现在加了一个primary shard的数量会怎么样呢.
我们去查询这个document的时候,_id = 1, hash值还是21, 21 % 4 = 1,计算结果是数据在P1上面,但是实际在P0上,就会间接导致数据的丢失.
routing值的作用和如何手动指定
默认的routing就是_id,也可以在发送请求的时候,手动指定一个routing ,如下:1
PUT /index/type/id?routing=user_id
手动指定routing是很有用的,可以保证说,某一类的document一定被路由到一个shard上去,那么在后续进行应用级别的负载均衡,以及提升批量读取的性能的时候,是很有帮助的