欢迎访问shiker.tech

请允许在我们的网站上展示广告

您似乎使用了广告拦截器,请关闭广告拦截器。我们的网站依靠广告获取资金。

ES存储原理和集群介绍
(last modified Aug 21, 2023, 7:40 PM )
by
侧边栏壁纸
  • 累计撰写 178 篇文章
  • 累计创建 62 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

ES存储原理和集群介绍

橙序员
2023-07-02 / 0 评论 / 0 点赞 / 288 阅读 / 4,608 字 / 正在检测百度是否收录... 正在检测必应是否收录...
文章摘要(AI生成)

全文检索什么是全文检索?数据总共分为结构化数据和非结构化数据两种,非结构化数据又称为全文数据。对非结构化数据的搜索有两种:顺序扫描法和反向索引法,顺序扫描就是顺序扫描每个文档内容,实现文档查找;反向索引则是提前将搜索的关键字建立索引,然后根据索引查找文档。这种针对非结构化数据的先建立索引在进行搜索的

全文检索

什么是全文检索?

数据总共分为结构化数据和非结构化数据两种,非结构化数据又称为全文数据。对非结构化数据的搜索有两种:顺序扫描法和反向索引法,顺序扫描就是顺序扫描每个文档内容,实现文档查找;反向索引则是提前将搜索的关键字建立索引,然后根据索引查找文档。这种针对非结构化数据的先建立索引在进行搜索的过程就是全文检索

全文检索的过程:

索引创建:将现实世界中所有的结构化和非结构化数据提取信息,创建索引的过程。

搜索索引:就是得到用户的查询请求,搜索创建的索引,然后返回结果的过程。

ES和solr

ES与Solr的比较:

  1. 单纯的对已有数据进行搜索时,solr更快;
  2. 当实时建立索引时,solr会产生io阻塞,查询性能较差,ES具有明显的优势
  3. 当数据量逐渐增加,solr的搜索效率会变得耕地,而ES没有明显变化
  4. 实际生产环境测试中,ES会比solr提升50倍

总结:

  1. ES与solr两者安装都很简单
  2. Solr利用ZK进行分布式管理,而ES自身带有分布式协调管理功能
  3. Solr支持更多格式的数据,而ES仅支持json格式
  4. Solr官方功能更多,而ES本身只关注核心功能,其它由三方插件提供
  5. solr在传统应用中要好于es,但在处理实时搜索时效率明显低于ES

ES存储结构

索引-index

一个索引就是一个拥有几分相似特征的文档的集合。一个索引由一个名字来标识(必须全部是小写字母的),并 且当我们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。在一个集群中,可以定义任意多的索引。

类型-type

在一个索引中,你可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区。通常,会为具有一组共同字段的文档定义一个类型。

文档-document

一个文档是一个可被索引的基础信息单元。文档以JSON(Javascript Object Notation)格式来表示,而JSON是一个到处存在的互联网数据交互格式。 在一个index/type里面,你可以存储任意多的文档。注意,尽管一个文档,物理上存在于一个索引之中,文档必须被索引/赋予一个索引的type。

字段-Field

相当于是数据表的字段,对文档数据根据不同属性进行的分类标识

映射-mapping

mapping是处理数据的方式和规则方面做一些限制,如某个字段的数据类型、默认值、分析器、是否被索引等等,这些都是映射里面可以设置的,其它就是处理es里面数据的一些使用规则设置也叫做映射, 按着最优规则处理数据对性能提高很大,因此才需要建立映射,并且需要思考如何建立映射才能对性能更好。

ES集群

ES集群是一个 P2P类型(使用 gossip 协议)的分布式系统,除了集群状态管理以外,其他所有的请求都 可以发送到集群内任意一台节点上,这个节点可以自己找到需要转发给哪些节点,并且直接跟这些节点通信。

集群中节点数量没有限制,一般大于等于2个节点就可以看做是集群了。一般处于高性能及高可用方面来考虑一般集群中的节点数量都是3个及3个以上。

集群-cluster

一个集群就是由一个或多个节点组织在一起,它们共同持有整个的数据,并一起提供索引和搜索功能。 一个集群由一个唯一的名字标识,这个名字默认就是“elasticsearch”。这个名字是重要的,因为一个节点只能通过指定某个集群的名字,来加入这个集群

节点-node

一个节点是集群中的一个服务器,作为集群的一部分,它存储数据,参与集群的索引和搜索功能。和集群类似,一个节点也是由一个名字来标识的,默认情况下,这个名字是一个随机的漫威漫画角色的名字,这个名字会在启动的时候赋予节点

一个节点可以通过配置集群名称的方式来加入一个指定的集群。默认情况下,每个节点都会被安排加入到一个叫做“elasticsearch”的集群中,这意味着,如果你在你的网络中启动了若干个节点,并假定它们能够相互发现彼此,它们将会自动地形成并加入到一个叫做“elasticsearch”的集群中。

master节点

整个集群只会有一个master节点,它将负责管理集群范围内的所有变更,例如增加、删除索引;或者增加、删除节点等。而master节点并不需要涉及到文档级别的变更和搜索等操作,所以当集群只拥有一个 master节点的情况下,即使流量的增加它也不会成为瓶颈。

  1. 负责集群节点上下线,shard分片的重新分配。
  2. 创建、删除索引。
  3. 负责接收集群状态(cluster state)的变化,并推送给所有节点。
  4. 集群节点都各有一份完整的cluster state,只是master node负责维护。
  5. 利用自身空闲资源,协调创建索引请求或者查询请求,将请求分发到相关node服务器。

数据节点

负责存储数据,提供建立索引和搜索索引的服务。 data节点消耗内存和磁盘IO的性能比较大。

协调节点

不会被选作主节点,也不会存储任何索引数据。主要用于查询负载均衡。将查询请求分发给多个node服务器,并对结果进行汇总处理。

协调节点的作用:

  1. 诸如搜索请求或批量索引请求之类的请求可能涉及保存在不同数据节点上的数据。 例如,搜索请求 在两个阶段中执行(query 和fetch),这两个阶段由接收客户端请求的节点 - 协调节点协调。
  2. 在请求阶段,协调节点将请求转发到保存数据的数据节点。 每个数据节点在本地执行请求并将其结 果返回给协调节点。 在收集fetch阶段,协调节点将每个数据节点的结果汇集为单个全局结果集。
  3. 每个节点都隐式地是一个协调节点。 这意味着将所有三个node.master,node.data设置为 false的节点作为仅用作协调节点,无法禁用该节点。 结果,这样的节点需要具有足够的内存和CPU以便 处理收集阶段。

分片和副本

分片

Elasticsearch提供了将索引划分成多份的能力,这些份就叫做分片。当你创建一个索引的时候,你 可以指定你想要的分片的数量。每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上。分片很重要,主要有两方面的原因:

  1. 允许你水平分割/扩展你的内容容量。
  2. 允许你在分片(潜在地,位于多个节点上)之上进行分布式的、并行的操作,进而提高性能/吞吐量。

至于一个分片怎样分布,它的文档怎样聚合回搜索请求,是完全由Elasticsearch管理的,对于作为用户的你来说,这些都是透明的。

副本

Elasticsearch允许你创建分片的一份或多份拷贝,这些拷贝叫做副本分片,或者直接叫副本。

副本之所以重要,有两个主要原因: 在分片/节点失败的情况下,提供了高可用性。每个索引可以被分成多个分片。一个索引也可以被复制0次(意思是没有复制)或多次。一旦复制了,每个索引就有了主分片(作为复制源的原来的分 片)和副本分片(主分片的拷贝)之别。复制分片不与主分片置于同一节点是非常重要的

集群状态-CLUSTER STATE

Cluster State是指集群中的各种状态和元数据(meta data)信息。其中,索引(Index)的mappings、 settings配置、持久化状态等信息,以及集群的一些配置信息都属于元数据(meta data)。 元数据非常重要,标识了集群中节点状态、索引的配置与状态信息等;假如记录某个index的元数据丢失,那么集群就认为这个index不再存在。ES集群中的每个节点都会保存一份这样的元数据信息,这样在增删索引、节点场景下能够极大方便集群选主流程、集群的管理操作。

  1. ClusterState是不可变对象,每次状态变更都会产生新的ClusterState,版本号随之更新
  2. 在ES中, 集群状态由Master节点维护,并且只能由Master节点更新集群状态
  3. Master节点一次处理一批集群状态更新,计算所需的更改并将更新后的新版集群状态发布到集群中的所有其他节点

Cluster State包含内容:

  1. long version: 当前版本号,每次更新加1,即便集群重启version仍会增加
  2. String stateUUID:该state对应的唯一id
  3. ClusterName clusterName:集群名称
  4. DiscoveryNodes nodes:当前集群全部节点信息
  5. RoutingTable routingTable:集群中所有index的路由表,即集群中全部索引的各个分片在集群节 点上的分布信息
  6. MetaData metaData:集群的meta数据,主要包括所有索引的mappings和settings配置
  7. ClusterBlocks blocks:集群级的限制设定,用于屏蔽某些操作
  8. ImmutableOpenMap customs: 自定义配置,如snapshots,可用插件扩展

Cluster State的更新:

通过两阶段提交保证事务一致性,第一步是向所有节点推送最新的ClusterState,当有超过半数的master节点返回ack请求时,再发送commit请求,要求节点 commit接收到的新版ClusterState。如果没有超过半数的节点返回ack,则认为本次发布失败,同时退出master状态,执行rejoin重新加入集群。

集群选举

当一个节点发现包括自己在内的多数派的master-eligible(master和数据节点)节点认为集群没有master时, 就可以发起master选举。

选举过程

根据节点的ClusterState中的版本作比较,版本越大,优先级越高;版本相同时,比较节点的id,id越小优先级越高

脑裂问题

由于部分节点网络断开,集群分成两部分,且这两部分都有master选举权。就成形成一个与原集群一样名字的集群,这种情况称为集群脑裂(split-brain)现象。这个问题非常危险,因为两个新形成的集群会同时索引和修改集群的数据。

解决方案:

# 决定选举一个master最少需要多少master候选节点。默认是1。
# 这个参数必须大于等于为集群中master候选节点的quorum数量,也就是大多数。
# quorum算法:master候选节点数量 / 2 + 1
# 例如一个有3个节点的集群,minimum_master_nodes 应该被设置成 3/2 + 1 = 2(向下取整)
discovery.zen.minimum_master_nodes: 2
# 等待ping响应的超时时间,默认值是3秒。如果网络缓慢或拥塞,会造成集群重新选举,建议略微调大
这个值。
# 这个参数不仅仅适应更高的网络延迟,也适用于在一个由于超负荷而响应缓慢的节点的情况。
discovery.zen.ping.timeout: 10s
# 当集群中没有活动的Master节点后,该设置指定了哪些操作(read、write)需要被拒绝(即阻塞执行)。有两个设置值:all和write,默认为wirte。
discovery.zen.no_master_block: write

通过设置最小候选节点数量,我们可以让小于候选节点的子网络节点无法选举出主节点。

集群拓展

横向拓展:增加节点,提高查询性能,减少服务器压力;增加副本,可以提高索引吞吐量。

纵向拓展:增加索引,通过索引的模糊匹配,可以增加数据容量。

故障转移

ES有两种集群故障探查机制:

  1. 通过master进行的,master会ping集群中所有的其他node,确保它们是否是存活着的。
  2. 每个node都会去ping master来确保master是存活的,否则会发起一个选举过程。

相同的分片不会放在统一节点上,当其中某一节点下线时,剩余分片会进行重新分配

ES数据存储

当一个写请求发送到 es 后,es 将数据写入 memory buffer 中,并添加事务日志( translog )。此时写入的数据还不能被查询到。默 认设置下,es 每1秒钟将memory buffer 中的数据 refresh 到 Linux 的 File system cache ,并清空 memory buffer ,此时写入的数据就可以被查询到了。

默认设置下,es 每30分钟调用 fsync 将 File system cache 中的数据 flush 到硬盘。因此需要通过 translog 来保证即使因为断电 File system cache 数据丢失,es 重启后也能通过日志回放找回丢失的数据。

ranslog 默认设置下,每一个 indexdeleteupdatebulk 请求都会直接 fsync 写入硬盘。 为了保证translog 不丢失数据,在每一次请求之后执行 fsync 确实会带来一些性能问题。对于一些允许丢失几秒钟数据的场景下,可以通过设置 index.translog.durabilityindex.translog.sync_interval 参数让 translog隔一段时间才调用fsync 将事务日志数据写入硬盘。

索引更新

Lucene 把每次生成的倒排索引,叫做一个段(segment)。然后另外使用一个commit文件,记录索引内所有的 segment

  1. 新接收的数据进入内存 buffer。
  2. 内存 buffer 刷到磁盘,生成一个新的 segment,commit 文件同步更新

利用缓存实现准实时搜索

  1. refresh操作:内存 buffer 生成一个新的 segment,刷到文件系统缓存中,Lucene 即可检索这个新 segment。
  2. 文件系统缓存真正同步到磁盘上,commit 文件更新。

磁盘同步机制translog

  1. Elasticsearch 在把数据写入到内存 buffer 的同时,其实还另外记录 了一个 translog 日志。

  2. 当内存刷新到文件系统缓存中的时候,translog 日志文件依然保持原样

  3. flush操作:等到真正把 segment 刷到磁盘,且 commit 文件进行更新的时候, translog 文件才清空。

translog的一致性

默认情况下,Elasticsearch 每 5 秒,或每次请求操作结束前,会强制刷新 translog 日志到磁盘上。

段的合并

每次更新创建新的segment,都会给服务器带来负载压力,因此,ES 会不断在后台运行任务,主动将这些零散的 segment 做数据归并,尽量让索引内只保有少量的,每个都比较大的segment 文件。

当归并完成,较大的这个 segment 刷到磁盘后,commit 文件做出相应变更,删除之前几个小 segment,改成新的大 segment。等检索请求都从小 segment 转到大 segment 上以后,删除没用的小 segment。

增删改原理

  1. 增加文档就是在新的索引段中增加一个文档,并且新的文档的增加会产生新的索引段。
  2. 删除文档只需要在被删除的文档上打上一个删除标记,等合并索引 段的时候将这个文档删除。
  3. 修改文档也是在旧的文档上打上删除标记,然后增加一个新的文档。等合并索引段的时候将这个文档删除。

文档路由

算法公式:【shard:文档所在分片分片】 = hash(【routing_number:路由id,默认为_id】)%【number_of_primary_shards:分片数量】

0

评论区