Elasticsearch 批量请求

多文档模式

mgetbulk API与单独的文档类似。差别是请求节点知道每个文档所在的分片。它把多文档请求拆成每个分片 的对文档请求,然后转发每个参与的节点。

一旦接收到每个节点的应答,然后整理这些响应组合为一个单独的响应,最后返回给客户端。

通过mget检索多个文档通过mget检索多个文档

下面我们将罗列通过一个mget请求检索多个文档的顺序步骤:

  1. 客户端向Node 1发送mget请求。
  2. Node 1为每个分片构建一个多条数据检索请求,然后转发到这些请求所需的主分片或复制分片上。当所有回复被接收,Node 1构建响应并返回给客户端。

routing 参数可以被docs中的每个文档设置。

通过打包批量修改文档通过打包批量修改文档

下面我们将罗列使用一个bulk执行多个createindexdeleteupdate请求的顺序步骤:

  1. 客户端向Node 1发送bulk请求。
  2. Node 1为每个分片构建批量请求,然后转发到这些请求所需的主分片上。
  3. 主分片一个接一个的按序执行操作。当一个操作执行完,主分片转发新文档(或者删除部分)给对应的复制节点,然后执行下一个操作。一旦所有复制节点报告所有操作已成功完成,节点就报告success给请求节点,后者(请求节点)整理响应并返回给客户端。

bulk API还可以在最上层使用replicationconsistency参数,routing参数则在每个请求的元数据中使用。

为什么是奇怪的格式?

你可能会问:“为什么bulk API需要带换行符的奇怪格式,而不是像mget API一样使用JSON数组?”为了回答这个问题,我们需要简单的介绍一下背景:批量中每个引用的文档属于不同的主分片,每个分片可能被分布于集群中的某个节点上。这意味着批量中的每个操作(action) 需要被转发到对应的分片和节点上。如果每个单独的请求被包装到JSON数组中,那意味着我们需要:

  • 解析JSON为数组(包括文档数据,可能非常大)
  • 检查每个请求决定应该到哪个分片上
  • 为每个分片创建一个请求的数组
  • 序列化这些数组为内部传输格式
  • 发送请求到每个分片

这可行,但需要大量的RAM来承载本质上相同的数据,还要创建更多的数据结构使得JVM花更多的时间执行垃圾回收。取而代之的,Elasticsearch则是从网络缓冲区中一行一行的直接读取数据。它使用换行符识别和解析action/metadata 行,以决定哪些分片来处理这个请求。这些行请求直接转发到对应的分片上。这些没有冗余复制,没有多余的数据结构。整个请求过程使用最小的内存在进行。