[ElasticSearch]原理之分布式文档存储(Distributed Document Store)

简介: 之前的文章中,我们已经知道如何存储数据到索引中以及如何检索它。但是我们掩盖了数据存储到集群中以及从集群中获取数据的具体实现的技术细节(But we glossed over many technical details surrounding how the data is distributed and fetched from the cluster)。

之前的文章中,我们已经知道如何存储数据到索引中以及如何检索它。但是我们掩盖了数据存储到集群中以及从集群中获取数据的具体实现的技术细节(But we glossed over many technical details surrounding how the data is distributed and fetched from the cluster)。

1. 路由文档到分片中(Routing a Document to a Shard)

当你索引一篇文档时,它会存储到一个主分片中。但是ElasticSearch如何知道文档是属于哪个分片呢?当我们创建一个新的文档,它是怎么知道它是应该存储到分片1上还是分片2上?

数据存储到分片的过程是有一定规则的,并不是随机发生的,因为我们日后还需要从分片中检索出文档。数据存储过程取决于下面的公式:

shard = hash(routing) % number_of_primary_shards

Routing值是一个任意字符串,默认为文档的id,也可以设置为一个用户自定义的值。Routing这个字符串通过一个hash函数处理,并返回一个数值,然后再除以索引中主分片的数目number_of_primary_shards,所得的余数作为主分片的编号,取值一般在0到number_of_primary_shards - 1之间的余数范围中。通过这种方法计算出该数据是存储到哪个分片中。

这就解释了为什么主分片个数在创建索引之后就不能再更改了:如果主分片个数在创建之后可以修改,那么之前所有通过公式得到的值都会失效,之前存储的文档也可能找不到。

所有的文档API(get , index , delete , bulk , update , 和 mget)都可以接受一个routing参数,来自定义文档与分片之间的映射。一个自定义的路由参数可以用来确保所有相关的文档——例如所有属于同一个用户的文档——都被存储到同一个分片中。

2. 主分片与副本分片如何交互

假设我们有一个三个节点的集群。集群里有一个名称为blog的索引,有两个主分片(primary shards)。每个主分片都有两个副本。相同节点的副本不会分配到同一节点,最后如下图展示:

image

我们可以发送请求到集群中的任何一个节点,每个节点都有能力处理我们的请求。每个节点都知道集群中任意文档的存储位置,所以可以直接将请求转发到所需的节点(Every node knows the location of every document in the cluster,so can forward requests directly to the required node)。

在下面的例子中,我们将请求都发送到节点1上,我们将其称为协调节点(coordinating node)。

2.1 创建,索引和删除文档

创建,索引和删除请求都是写操作,所以必须在主分片上写操作完成之后才能被复制到相关的副本分片上(Create, index, and delete requests are write operations, which must be successfully completed on the primary shard before they can be copied to any associated replica shards)。

交互过程如下图所示:

image

下面是成功在主分片和副本分片上创建,索引以及删除文档所必须的步骤:

  • 客户端发送了一个新建,索引 或者 删除文档 请求给节点 1;
  • 节点 1 通过请求文档的 id 值判断出该文档应该被存储在分片 0 中,并且知道分片 0 的主分片 P0 位于节点 3 上。因此节点 1 会把这个请求转发给节点 3;
  • 节点 3 在主分片上执行请求。如果请求执行成功,节点 3 并行将该请求转发给节点 1 和节点 2 上的的副本分片(R0)。一旦所有的副本分片都成功地执行了请求,则向节点 3 报告成功,节点 3 向协调节点 (Node 1 )报告成功,协调节点向客户端报告成功。

在客户端收到成功响应时,文档变更已经在主分片和所有副本分片执行完成,变更是安全的。

有一些可选的请求参数允许您影响这个过程,可能以数据安全为代价提升性能。这些选项很少使用,因为Elasticsearch已经很快,但是为了完整起见,在这里阐述如下:

2.1.1 一致性

默认情况下,在尝试进行写操作之前,主分片需要规定数量(quorum)或大多数(majority)的分片副本shard copies(其中分片副本可以是主分片或副本分片 a shard copy can be a primary or a replica shard)。 这是为了防止将数据写入网络分区的“错误的一边wrong side”。 规定数量quorum定义如下:

int( (primary + number_of_replicas) / 2 ) + 1

一致性consistency值可以是one(只有主分片),all(主分片和所有的副本),或者默认值quorum,或者大多数的分片副本(The allowed values for consistency are one (just the primary shard), all (the primary and all replicas), or the default quorum, or majority, of shard copies.)。

请注意,number_of_replicas是索引设置中指定的副本数,而不是当前活跃的副本数。 如果指定索引有三个副本,则quorum将如下定义:

int( (primary + 3 replicas) / 2 ) + 1 = 3

但是,如果仅启动两个节点,则活跃的分片副本不满足规定数量,您将无法对任何文档进行索引或删除。

2.1.2 超时

如果没有足够的副本分片会发生什么? Elasticsearch会等待,希望更多的分片出现。默认情况下,它最多等待1分钟。 如果你需要,你可以使用 timeout 参数 使它更早终止: 100 100毫秒,30s 是30秒。

备注

新索引默认有 1 个副本分片,这意味着为满足 规定数量 应该 需要两个活动的分片副本。 但是,这些默认的设置会阻止我们在单一节点上做任何事情。为了避免这个问题,要求只有当 number_of_replicas 大于1的时候,规定数量才会执行。

2.2 检索文档

我们可以从一个主分片(primary shard)或者它们任一副本中检索文档,流程如下图:

image

下面是从主分片或者副本分片上检索文档所需要的一系列步骤:

  • 客户端发送了一个 Get 请求给节点 1;
  • 节点 1 通过请求文档的 id 值判断出该文档被存储在分片 0 中。三个节点上都存有分片 0 的复制(节点1上R0,节点2上R0,节点3上P0)。这一次,它将请求转发给节点 2 。
  • 节点 2 返回文档给节点 1 ,节点 1 在返回文档给客户端。

对于读请求,对于每一次请求,请求节点都会选择一个不同的副本分本,达到负载均衡。通过轮询所有的副本分片。

在文档被检索时,已经被索引的文档可能已经存在于主分片上但是还没有复制到副本分片。 在这种情况下,副本分片可能会报告文档不存在,但是主分片可能成功返回文档。 一旦索引请求成功返回给用户,文档在主分片和副本分片都是可用的。

2.3 局部更新文档

更新 API (Update API)融合了上面解释的两种读写模式,如下图所示:

image

下面是部分更新一篇文档所需要的一系列步骤:

  • 客户端发送了一个 Update 请求给节点 1;
  • 节点 1 通过请求文档的 id 值判断出该文档被存储在分片 0 中。并且知道分片 0 的主分片 P0 位于节点 3 上。因此节点 1 会把这个请求转发给节点 3;
  • 节点 3 从主分片(P0)上检索出指定文档,并更改_source字段中的JSON,修改完毕之后试着重新索引文档到主分片(P0)上。如果有人已经修改了该文档,那么会重复步骤3,如果尝试retry_on_conflict次还没有成功则放弃。
  • 如果节点 3 更新文档成功,节点 3 会把文档新版本并行发给节点 1 和 节点 2 上的副本分片,重新索引文档。一旦所有的副本分片返回成功,节点 3 向协调节点返回成功,协调节点向客户端返回成功。

基于文档的复制

当主分片把更改转发到副本分片时, 它不会转发更新请求。 相反,它转发完整文档的新版本。请记住,这些更改将会异步转发到副本分片,并且不能保证它们以发送它们相同的顺序到达。 如果Elasticsearch仅转发更改请求,则可能以错误的顺序应用更改,导致得到损坏的文档。

2.4 多文档模式

mget 和 bulk API的模式类似于单文档模式。 不同的是,协调节点知道每个文档存储在哪个分片中。 它将多文档请求分解成对每个分片的多文档请求,并将请求并行转发到每个参与节点。

一旦从每个节点接收到应答,将每个节点的响应整合到单个响应中,并返回给客户端

2.4.1 mget

如下图所示:

image

以下是使用单个 mget 请求取回多个文档所需的步骤顺序:

  • 客户端向节点 1 发送 mget 请求。
  • 节点 1 为每个分片构建多文档获取请求,然后并行转发这些请求到托管在每个所需的主分片或者副本分片的节点上。一旦收到所有应答, 节点 1 构建响应并将其返回给客户端。
2.4.2 bulk

bulk API,允许在单个批量请求中执行多个创建、索引、删除和更新请求,如下图所示:

image

bulk API 按如下步骤顺序执行:

  • 客户端向 节点 1 发送 bulk 请求。
  • 节点 1 为每个节点创建一个批量请求,并将这些请求并行转发到每个包含主分片的节点主机。
  • 主分片一个接一个按顺序执行每个操作。当每个操作成功时,主分片并行转发新文档(或删除)到副本分片,然后执行下一个操作。 一旦所有的副本分片报告所有操作成功,该节点将向协调节点报告成功,协调节点将这些响应收集整理并返回给客户端。

bulk API 还可以在整个批量请求的最顶层使用 consistency 参数,以及在每个请求中的元数据中使用 routing 参数。



相关实践学习
以电商场景为例搭建AI语义搜索应用
本实验旨在通过阿里云Elasticsearch结合阿里云搜索开发工作台AI模型服务,构建一个高效、精准的语义搜索系统,模拟电商场景,深入理解AI搜索技术原理并掌握其实现过程。
ElasticSearch 最新快速入门教程
本课程由千锋教育提供。全文搜索的需求非常大。而开源的解决办法Elasricsearch(Elastic)就是一个非常好的工具。目前是全文搜索引擎的首选。本系列教程由浅入深讲解了在CentOS7系统下如何搭建ElasticSearch,如何使用Kibana实现各种方式的搜索并详细分析了搜索的原理,最后讲解了在Java应用中如何集成ElasticSearch并实现搜索。  
目录
相关文章
|
11月前
|
NoSQL 算法 安全
分布式锁—1.原理算法和使用建议
本文主要探讨了Redis分布式锁的八大问题,包括非原子操作、忘记释放锁、释放其他线程的锁、加锁失败处理、锁重入问题、锁竞争问题、锁超时失效及主从复制问题,并提供了相应的优化措施。接着分析了Redis的RedLock算法,讨论其优缺点以及分布式专家Martin对其的质疑。此外,文章对比了基于Redis和Zookeeper(zk)的分布式锁实现原理,包括获取与释放锁的具体流程。最后总结了两种分布式锁的适用场景及使用建议,指出Redis分布式锁虽有性能优势但模型不够健壮,而zk分布式锁更稳定但部署成本较高。实际应用中需根据业务需求权衡选择。
|
运维 NoSQL 算法
【📕分布式锁通关指南 04】redis分布式锁的细节问题以及RedLock算法原理
本文深入探讨了基于Redis实现分布式锁时遇到的细节问题及解决方案。首先,针对锁续期问题,提出了通过独立服务、获取锁进程自己续期和异步线程三种方式,并详细介绍了如何利用Lua脚本和守护线程实现自动续期。接着,解决了锁阻塞问题,引入了带超时时间的`tryLock`机制,确保在高并发场景下不会无限等待锁。最后,作为知识扩展,讲解了RedLock算法原理及其在实际业务中的局限性。文章强调,在并发量不高的场景中手写分布式锁可行,但推荐使用更成熟的Redisson框架来实现分布式锁,以保证系统的稳定性和可靠性。
947 0
【📕分布式锁通关指南 04】redis分布式锁的细节问题以及RedLock算法原理
|
存储 分布式计算 Hadoop
基于Java的Hadoop文件处理系统:高效分布式数据解析与存储
本文介绍了如何借鉴Hadoop的设计思想,使用Java实现其核心功能MapReduce,解决海量数据处理问题。通过类比图书馆管理系统,详细解释了Hadoop的两大组件:HDFS(分布式文件系统)和MapReduce(分布式计算模型)。具体实现了单词统计任务,并扩展支持CSV和JSON格式的数据解析。为了提升性能,引入了Combiner减少中间数据传输,以及自定义Partitioner解决数据倾斜问题。最后总结了Hadoop在大数据处理中的重要性,鼓励Java开发者学习Hadoop以拓展技术边界。
515 7
|
存储 Dubbo Java
分布式 RPC 底层原理详解,看这篇就够了!
本文详解分布式RPC的底层原理与系统设计,大厂面试高频,建议收藏。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
分布式 RPC 底层原理详解,看这篇就够了!
|
机器学习/深度学习 存储 运维
分布式机器学习系统:设计原理、优化策略与实践经验
本文详细探讨了分布式机器学习系统的发展现状与挑战,重点分析了数据并行、模型并行等核心训练范式,以及参数服务器、优化器等关键组件的设计与实现。文章还深入讨论了混合精度训练、梯度累积、ZeRO优化器等高级特性,旨在提供一套全面的技术解决方案,以应对超大规模模型训练中的计算、存储及通信挑战。
838 4
|
分布式计算 Hadoop 网络安全
Hadoop-08-HDFS集群 基础知识 命令行上机实操 hadoop fs 分布式文件系统 读写原理 读流程与写流程 基本语法上传下载拷贝移动文件
Hadoop-08-HDFS集群 基础知识 命令行上机实操 hadoop fs 分布式文件系统 读写原理 读流程与写流程 基本语法上传下载拷贝移动文件
244 1
|
存储 机器学习/深度学习 缓存
Hadoop-07-HDFS集群 基础知识 分布式文件系统 读写原理 读流程与写流程 基本语法上传下载拷贝移动文件
Hadoop-07-HDFS集群 基础知识 分布式文件系统 读写原理 读流程与写流程 基本语法上传下载拷贝移动文件
395 1
|
JSON 自然语言处理 算法
ElasticSearch基础2——DSL查询文档,黑马旅游项目查询功能
DSL查询文档、RestClient查询文档、全文检索查询、精准查询、复合查询、地理坐标查询、分页、排序、高亮、黑马旅游案例
ElasticSearch基础2——DSL查询文档,黑马旅游项目查询功能
|
JSON 自然语言处理 数据库
ElasticSearch基础1——索引和文档。Kibana,RestClient操作索引和文档+黑马旅游ES库导入
概念、ik分词器、倒排索引、索引和文档的增删改查、RestClient对索引和文档的增删改查
ElasticSearch基础1——索引和文档。Kibana,RestClient操作索引和文档+黑马旅游ES库导入
|
存储 缓存 数据处理
深度解析:Hologres分布式存储引擎设计原理及其优化策略
【10月更文挑战第9天】在大数据时代,数据的规模和复杂性不断增加,这对数据库系统提出了更高的要求。传统的单机数据库难以应对海量数据处理的需求,而分布式数据库通过水平扩展提供了更好的解决方案。阿里云推出的Hologres是一个实时交互式分析服务,它结合了OLAP(在线分析处理)与OLTP(在线事务处理)的优势,能够在大规模数据集上提供低延迟的数据查询能力。本文将深入探讨Hologres分布式存储引擎的设计原理,并介绍一些关键的优化策略。
847 0

热门文章

最新文章

下一篇
开通oss服务