路由一个文档到分片中
之前有提到一个文档至少被储存在一个主分片中,副本分片可以有多个,但是主分片至少有一个。
因此,例如一个集群被设置有3个主分片,为了保证文档被均匀的存储在这些主分片,es会根据routing(可能是文档的id或自己设置),通过一个hash算法将文档分配到一个主分片中进行储存。
这个过程有些像hashmap将一个键值对储存到底层的链表中的算法。
这样做的目的,就是让文档均匀地分布在分片中。
新建或删除文档
- 客户端向节点1发送新建、索引或删除文档的请求;
- 通过id计算文档属于分片P0,主节点向node3转发请求;
- node3在主分片执行请求,如果请求成功,会将结果通知给副本分片所在的节点node1和node2;
- 一旦所有的副本分片都执行成功,会向主节点报告执行结果,主节点会向客户端报告执行结果。
取回单个文档
- 客户端向主节点node1发送请求;
- 结点使用文档的id知道文档所处的分片时分片P0,P0的副本分片R0处于节点2上,因此将请求转发给节点2;
- node2将结果返回给主节点node1,node1将结果返回给客户端。
在处理读取请求时,主结点在每次请求的时候都会通过轮询所有的副本分片来达到负载均衡。也就是确定请求分配给“不忙”的结点。
局部更新文档
- 客户端向主节点发送强求;
- 主节点将请求转发到文档所在的节点;
- node3从主节点接受到请求,尝试修改文档,如果此时有别的线程在修改文档,则继续尝试步骤三,超过 retry_on_conflict 次后放弃;
- node3成功修改后,它将新版本的文档转发到node1和node2的副本节点上,重新建立索引,当所有的副本片区都完成文档更新,会告知主节点,主节点向客户端返回成功。
结论
从es储存、更新机制来看,文档的储存过程非常耗费时间和空间,如果在结构化数据库储存的数据只有一份,在es当中,则需要储存主分片和所有的副本分片,一次新增和修改都需要若干个节点参与。但是正因为每个数据的每个字段都被索引了,es的查询,分析效率非常高。