05 Document路由原理
1、什么是document路由?
一个index会被分为多个主分片(primary_shards),一个document只能放在一个primary_shards中。
在客户端创建document的时候,ES就要决定document放在index的哪个shard上。这个过程称为document routing,即数据路由。
2、路由算法
shard = hash(routing) % number_of_primary_shards
每次增删改查一个document的时候,都会带过来一个routing number,默认就是这个document的_id(_id可能是手动指定,也可能是自动生成)。
将这个routing值,传入一个hash函数中,产出一个routing值的hash值,假设hash(routing) = 21,然后将hash函数产出的值对这个index的primary shard的数量求余数(假设primary shard的数量为3):21 % 3 = 0,就决定了,这个document就放在P0上。
相同的routing值,每次过来,从hash函数中产出的hash值一定是相同的。
3、手动指定routing
默认的routing就是_id
也可以在发送请求的时候,手动指定一个routing value,比如说put /index/type/id?routing=user_id
手动指定routing value是很有用的,这样可以让某一类document一定被路由到一个shard上去,那么在后续进行应用级别的负载均衡,以及提升批量读取的性能的时候,是很有帮助的。
4、primary shard数量不可变的原因
primary shard的数量确定之后不可更改,这是因为,数据路由时确定了shard的数值,后续primary shard数量变了的话,再根据路由算法确定shard的位置,得到的shard数值就会与原先不一致,导致找不到数据。
5、通过协调节点进行增删改的内部原理
前面讲了数据路由原理,这里要讲的是document是在哪里进行路由,那么就要引出一个概念:协调节点。简单地说所有的shard都是成为协调节点。java客户端可以往任何一个shard发送请求,因为任何一个shard都知道每个document在哪个shard上。请求发送到哪个节点上,哪个节点就可以成为该请求的协调节点。
下面讲一下增删改的流程/内部原理:
(1)客户端请求任意一个节点,该节点成为协调节点。
(2)通过document路由计算后,请求会从协调节点被转发到最终的primary shard上去处理。(因为是增删改操作,所以不能由replica shard处理)
(3)primary shard会在自己本地进行相关的处理操作,然后primary shard将document同步到自己的replica shard上。
(4)协调节点发现路由到的所有primary shard和对应的replica shard都处理完请求后,就返回响应结果给客户端。
6、通过协调节点进行查询的内部原理
对于读请求,与增删改不同的是,协调节点会把查询请求路由到涉及到的document的其中一个primary shard或replica shard上,因为replica shard是可以服务于读请求的。具体会使用round-robin随机轮询算法,使读请求负载均衡至多个shard上。被分配的shard会将请求回复给协调节点,最终由协调节点响应客户端。
1、我们发送任何一个增删该查操作的时候,比如说PUT /index/type/id ,都可以带上一个consistency参数,指明我们想要的写一致性是什么取值。例如put /index/type/id?consistency=quorum,consistency一共有如下取值:
one : 要求我们这个写操作,只要primary shard 是active活跃可用的,就可以执行
all: 要求我们这个写操作,必须所有的primary shard和replica shard都是活跃的,才可以执行这个写操作
quorum :默认值,要求所有的shard中,必须大部分shard 都是活跃的,可用的
2、quorum机制,写之前必须确保大多数shard可用。
quorum = (int(primary + number_of_repilicas)/2)+1。如果consistency=quorum时,只有当numer_of_replicas>1时才生效。
举个例子 ,3个primary shard ,number_of_replicas=1,总共3+3*1 = 6个shard
quroum = (int(3+1)/2)+1 = 3
所以,要求6个shard中至少有3个shard 是active状态的,才可以执行这个写操作。
3、如果节点数少于quorum数量,可能导致quorum不齐全,进而导致无法执行任何写操作。
比如"3个primary shard,replica=1",要求至少3个shard是active,3个shard按照之前学习的shard&replica机制,必须在不同的节点上,如果说只有2台机器的话,3个shard都没法分配齐全,此时就可能会出现写操作无法执行的情况。
es提供了一种特殊的处理场景,就是说当number_of_replicas>1时才生效,因为假如说,1个primary shard,replica=1,此时就2个shard,此时,quorum=(1 + 1 / 2) + 1 = 2,要求必须有2个shard是活跃的,但是可能就1个node,此时就1个shard是活跃的,如果你不特殊处理的话,导致我们的单节点集群就无法工作
4、quorum不齐全时,请求会wait,默认1分钟。
等待期间,期望活跃的shard数量可以增加,最后实在不行,就会timeout。
我们其实可以在写操作的时候,加一个timeout参数,比如说PUT /index/type/id?timeout=30,这个就是说自己去设定quorum不齐全的时候,es的timeout时长,可以缩短,也可以增长。timeout默认单位为ms,可以指定单位,例如PUT /index/type/id?timeout=30s。
https://blog.csdn.net/zx711166/article/details/82355214
例如:from=100&size=10,表示从第100条开始的10条记录。
如果要查询的数据分布在3个Primary shard中,在分页时,就需要在每个shard中进行查询前110条,每个shard都提供110条给协调节点,然后协调节点在对这110*3=330条数据进行排序,然后返回这个排序中的从第100条开始的10条记录。