【工作笔记】从零开始学ElasticSearch( 九)—— 高级扩展:分布式CRUD

路由文档到分片

当你索引一个文档,它被存储在单独一个主分片上。Elasticsearch是如何知道文档属于哪个分片的呢?当你创建一个新文档,它是如何知道是应该存储在分片1还是分片2上的呢?

进程不能是随机的,因为我们将来要检索文档。事实上,它根据一个简单的算法决定

shard = hash(routing) % number_of_primary_shards

routing值是一个任意字符串,它默认是_id但也可以自定义。这个routing字符串通过哈希函数生成一个数字,然后除以主切片的数量得到一个余数(remainder),余数的范围永远是0到number_of_primary_shards - 1,这个数字就是特定文档所在的分片

这也解释了为什么主分片的数量只能在创建索引时定义且不能修改:如果主分片的数量在未来改变了,所有先前的路由值就失效了,文档也就失效了

所有的文档API(get、index、delete、bulk、update、mget)都接收一个routing参数,它用来自定义文档到分片的映射。自定义路由值可以确保所有相关文档

主分片和复制分片如何交互

假设有三个节点的集群。它包含一个叫做bblogs的索引并拥有两个主分片。每个主分片有两个复制分片。相同的分片不会放在同一个节点上
这里写图片描述

我们能够发送请求给集群中任意一个节点。每个节点都有能力处理任意请求。每个节点都知道任意文档所在的节点,所以也可以将请求转发到需要的节点。

下面的例子中,我们将发送所有请求给Node 1,这个节点我们将会称之为请求节点(requesting node)

新建、索引和删除请求都是写(write)操作,它们必须在主分片上成功完成才能复制到相关的复制分片上
这里写图片描述

面我们罗列在主分片和复制分片上成功新建、索引或删除一个文档必要的顺序步骤:

1. 客户端给Node 1发送新建、索引或删除请求。
2. 节点使用文档的_id确定文档属于分片0。它转发请求到Node 3,分片0位于这个节点上。
3. Node 3在主分片上执行请求,如果成功,它转发请求到相应的位于Node1和Node2的复制节点上。当所有的复制节点报告成功,Node 3报告成功到请求的节点,请求的节点再报告给客户端。

客户端接收到成功响应的时候,文档的修改已经被应用于主分片和所有的复制分片。修改生效。

检索文档

文档能够从主分片或任意一个复制分片被检索。
这里写图片描述

下面我们罗列在主分片或复制分片上检索一个文档必要的顺序步骤:

1. 客户端给Node 1发送get请求。
2. 节点使用文档的_id确定文档属于分片0。分片0对应的复制分片在三个节点上都有。此时,它转发请求到Node 2。
3. Node 2返回文档(document)给Node 1然后返回给客户端。

对于读请求,为了平衡负载,请求节点会为每个请求选择不同的分片——它会循环所有分片副本。

可能的情况是,一个被索引的文档已经存在于主分片上却还没来得及同步到复制分片上。这时复制分片会报告文档未找到,主分片会成功返回文档。一旦索引请求成功返回给用户,文档则在主分片和复制分片都是可用的。

局部更新文档

update API 结合了之前提到的读和写的模式
这里写图片描述

执行局部更新必要的顺序步骤:

 1. 客户端给Node 1发送更新请求。
 2. 它转发请求到主分片所在节点Node 3。
 3. Node 3从主分片检索出文档,修改_source字段的JSON,然后在主分片上重建索引。如果有其他进程修改了文档,它以retry_on_conflict设置的次数重复步骤3,都未成功则放弃。
 4. 如果Node 3成功更新文档,它同时转发文档的新版本到Node 1和Node 2上的复制节点以重建索引。当所有复制节点报告成功,Node 3返回成功给请求节点,然后返回给客户端。

多文档模式

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

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

这里写图片描述

通过一个mget请求检索多个文档的顺序步骤:

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

routing 参数可以被docs中的每个文档设置
这里写图片描述

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

批量的格式

批量中每个引用的文档属于不同的主分片,每个分片可能被分布于集群中的某个节点上。这意味着批量中的每个操作(action)需要被转发到对应的分片和节点上

如果每个单独的请求被包装到JSON数组中,那意味着我们需要:

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

这可行,但需要大量的RAM来承载本质上相同的数据,还要创建更多的数据结构使得JVM花更多的时间执行垃圾回收。

取而代之的,Elasticsearch则是从网络缓冲区中一行一行的直接读取数据。它使用换行符识别和解析action/metadata行,以决定哪些分片来处理这个请求。

这些行请求直接转发到对应的分片上。这些没有冗余复制,没有多余的数据结构。整个请求过程使用最小的内存在进行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值