剖析Elasticsearch集群系列第一篇 Elasticsearch的存储模型和读写操作
剖析Elasticsearch集群系列涵盖了当今最流行的分布式搜索引擎Elasticsearch的底层架构和原型实例。
本文是这个系列的第一篇,在本文中,我们将讨论的Elasticsearch的底层存储模型及CRUD(创建、读取、更新和删除)操作的工作原理。
Elasticsearch是当今最流行的分布式搜索引擎,GitHub、 SalesforceIQ、Netflix等公司将其用于全文检索和分析应用。在Insight,我们用到了Elasticsearch的诸多不同功能,比如:
- 全文检索
- 比如找到与搜索词项(term)最相关的维基百科文章。
- 聚合
- 比如在广告网络中,可视化的搜索词项的竞价直方图。
- 地理空间API
- 比如在顺风车平台,匹配最近的司机和乘客。
正是因为Elasticsearch如此流行并且就在我们身边,我决定深入研究一下。本文,我将分享Elasticsearch的存储模型和CRUD操作的工作原理。
当我在思考分布式系统是如何工作时,我脑海里的图案是这样的:
水面以上的是API,以下的才是真正的引擎,一切魔幻般的事件都发生在水下。本文所关注的就是水下的部分,我们将关注:
- Elasticsearch是主从架构还是无主架构
- Elasticsearch的存储模型是什么样的
- Elasticsearch是怎么执行写操作的
- Elasticsearch是怎么执行读操作的
- 如何定义搜索结果的相关性
在我们深入这些概念之前,让我们熟悉下相关的术语。
1 辨析Elasticsearch的索引与Lucene的索引
Elasticsearch中的索引是组织数据的逻辑空间(就好比数据库)。1个Elasticsearch的索引有1个或者多个分片(默认是5个)。分片对应实际存储数据的Lucene的索引,分片自身就是一个搜索引擎。每个分片有0或者多个副本(默认是1个)。Elasticsearch的索引还包含"type"(就像数据库中的表),用于逻辑上隔离索引中的数据。在Elasticsearch的索引中,给定一个type,它的所有文档会拥有相同的属性(就像表的schema)。
(点击放大图像)
图a展示了一个包含3个分片的Elasticsearch索引,每个分片拥有1个副本。这些分片组成了一个Elasticsearch索引,每个分片自身是一个Lucene索引。图b展示了Elasticsearch索引、分片、Lucene索引和文档之间的逻辑关系。
对应于关系数据库术语
Elasticsearch Index == Database
Types == Tables
Properties == Schema
现在我们熟悉了Elasticsearch世界的术语,接下来让我们看一下节点有哪些不同的角色。
2 节点类型
一个Elasticsearch实例是一个节点,一组节点组成了集群。Elasticsearch集群中的节点可以配置为3种不同的角色:
主节点:控制Elasticsearch集群,负责集群中的操作,比如创建/删除一个索引,跟踪集群中的节点,分配分片到节点。主节点处理集群的状态并广播到其他节点,并接收其他节点的确认响应。
每个节点都可以通过设定配置文件elasticsearch.yml中的node.master属性为true(默认)成为主节点。
对于大型的生产集群来说,推荐使用一个专门的主节点来控制集群,该节点将不处理任何用户请求。
数据节点:持有数据和倒排索引。默认情况下,每个节点都可以通过设定配置文件elasticsearch.yml中的node.data属性为true(默认)成为数据节点。如果我们要使用一个专门的主节点,应将其node.data属性设置为false。
客户端节点:如果我们将node.master属性和node.data属性都设置为false,那么该节点就是一个客户端节点,扮演一个负载均衡的角色,将到来的请求路由到集群中的各个节点。
Elasticsearch集群中作为客户端接入的节点叫协调节点。协调节点会将客户端请求路由到集群中合适的分片上。对于读请求来说,协调节点每次会选择不同的分片处理请求,以实现负载均衡。
在我们开始研究发送给协调节点的CRUD请求是如何在集群中传播并被引擎执行之前,让我们先来看一下Elasticsearch内部是如何存储数据,以支持全文检索结果的低延迟服务的。
存储模型
Elasticsearch使用了Apache Lucene,后者是Doug Cutting(Apache Hadoop之父)使用Java开发的全文检索工具库,其内部使用的是被称为倒排索引的数据结构,其设计是为全文检索结果的低延迟提供服务。文档是Elasticsearch的数据单位,对文档中的词项进行分词,并创建去重词项的有序列表,将词项与其在文档中出现的位置列表关联,便形成了倒排索引。
这和一本书后面的索引非常类似,即书中包含的词汇与其出现的页码列表关联。当我们说文档被索引了,我们指的是倒排索引。我们来看下如下2个文档是如何被倒排索引的:
文档1(Doc 1): Insight Data Engineering Fellows Program
文档2(Doc 2): Insight Data Science Fellows Program
如果我们想找包含词项"insight"的文档,我们可以扫描这个(单词有序的)倒排索引,找到"insight"并返回包含改词的文档ID,示例中是Doc 1和Doc 2。
为了提高可检索性(比如希望大小写单词都返回),我们应当先分析文档再对其索引。分析包括2个部分:
- 将句子词条化为独立的单词
- 将单词规范化为标准形式
默认情况下,Elasticsearch使用标准分析器,它使用了:
- 标准分词器以单词为界来切词
- 小写词条(token)过滤器来转换单词
还有很多可用的分析器在此不列举,请参考相关文档。
为了实现查询时能得到对应的结果,查询时应使用与索引时一致的分析器,对文档进行分析。
注意:标准分析器包含了停用词过滤器,但默认情况下没有启用。
现在,倒排索引的概念已经清楚,让我们开始CRUD操作的研究吧。我们从写操作开始。
剖析写操作
创建((C)reate)
当我们发送索引一个新文档的请求到协调节点后,将发生如下一组操作:
Elasticsearch集群中的每个节点都包含了改节点上分片的元数据信息。协调节点(默认)使用文档ID参与计算,以便为路由提供合适的分片。Elasticsearch使用MurMurHash3函数对文档ID进行哈希,其结果再对分片数量取模,得到的结果即是索引文档的分片。
shard = hash(document_id) % (num_of_primary_shards)
- 当分片所在的节点接收到来自协调节点的请求后,会将该请求写入translog(我们将在本系列接下来的文章中讲到),并将文档加入内存缓冲。如果请求在主分片上成功处理,该请求会并行发送到该分片的副本上。当translog被同步(fsync)到全部的主分片及其副本上后,客户端才会收到确认通知。
- 内存缓冲会被周期性刷新(默认是1秒),内容将被写到文件系统缓存的一个新段上。虽然这个段并没有被同步(fsync),但它是开放的,内容可以被搜索到。
- 每30分钟,或者当translog很大的时候,translog会被清空,文件系统缓存会被同步。这个过程在Elasticsearch中称为冲洗(flush)。在冲洗过程中,内存中的缓冲将被清除,内容被写入一个新段。段的fsync将创建一个新的提交点,并将内容刷新到磁盘。旧的translog将被删除并开始一个新的translog。
下图展示了写请求及其数据流。
(点击放大图像)
更新((U)pdate)和删除((D)elete)
删除和更新也都是写操作。但是Elasticsearch中的文档是不可变的,因此不能被删除或者改动以展示其变更。那么,该如何删除和更新文档呢?
磁盘上的每个段都有一个相应的.del文件。当删除请求发送后,文档并没有真的被删除,而是在.del文件中被标记为删除。该文档依然能匹配查询,但是会在结果中被过滤掉。当段合并(我们将在本系列接下来的文章中讲到)时,在.del文件中被标记为删除的文档将不会被写入新段。
接下来我们看更新是如何工作的。在新的文档被创建时,Elasticsearch会为该文档指定一个版本号。当执行更新时,旧版本的文档在.del文件中被标记为删除,新版本的文档被索引到一个新段。旧版本的文档依然能匹配查询,但是会在结果中被过滤掉。
文档被索引或者更新后,我们就可以执行查询操作了。让我们看看在Elasticsearch中是如何处理查询请求的。
剖析读操作((R)ead)
读操作包含2部分内容:
- 查询阶段
- 提取阶段
我们来看下每个阶段是如何工作的。
查询阶段
在这个阶段,协调节点会将查询请求路由到索引的全部分片(主分片或者其副本)上。每个分片独立执行查询,并为查询结果创建一个优先队列,以相关性得分排序(我们将在本系列的后续文章中讲到)。全部分片都将匹配文档的ID及其相关性得分返回给协调节点。协调节点创建一个优先队列并对结果进行全局排序。会有很多文档匹配结果,但是,默认情况下,每个分片只发送前10个结果给协调节点,协调节点为全部分片上的这些结果创建优先队列并返回前10个作为hit。
提取阶段
当协调节点在生成的全局有序的文档列表中,为全部结果排好序后,它将向包含原始文档的分片发起请求。全部分片填充文档信息并将其返回给协调节点。
下图展示了读请求及其数据流。
(点击放大图像)
如上所述,查询结果是按相关性排序的。接下来,让我们看看相关性是如何定义的。
搜索相关性
相关性是由搜索结果中Elasticsearch打给每个文档的得分决定的。默认使用的排序算法是tf/idf(词频/逆文档频率)。词频衡量了一个词项在文档中出现的次数 (频率越高 == 相关性越高),逆文档频率衡量了词项在全部索引中出现的频率,是一个索引中文档总数的百分比(频率越高 == 相关性越低)。最后的得分是tf-idf得分与其他因子比如(短语查询中的)词项接近度、(模糊查询中的)词项相似度等的组合。
接下来有什么?
这些CRUD操作由Elasticsearch内部的一些数据结构所支持,这对于理解Elasticsearch的工作机制非常重要。在接下来的系列文章中,我将带大家走进类似的那些概念并告诉大家在使用Elasticsearch中有哪些坑。
- Elasticsearch中的脑裂问题及防治措施
- 事务日志
- Lucene的段
- 为什么搜索时使用深层分页很危险
- 计算搜索相关性中困难及权衡
- 并发控制
- 为什么Elasticsearch是准实时的
- 如何确保读和写的一致性
剖析Elasticsearch集群系列第一篇 Elasticsearch的存储模型和读写操作的更多相关文章
- 剖析Elasticsearch集群系列之一:Elasticsearch的存储模型和读写操作
转载:http://www.infoq.com/cn/articles/analysis-of-elasticsearch-cluster-part01 1.辨析Elasticsearch的索引与Lu ...
- 剖析Elasticsearch集群系列之二:分布式的三个C、translog和Lucene段
转载:http://www.infoq.com/cn/articles/anatomy-of-an-elasticsearch-cluster-part02 共识——裂脑问题及法定票数的重要性 共识是 ...
- 剖析Elasticsearch集群系列之三:近实时搜索、深层分页问题和搜索相关性权衡之道
转载:http://www.infoq.com/cn/articles/anatomy-of-an-elasticsearch-cluster-part03 近实时搜索 虽然Elasticsearch ...
- Redis-cluster集群【第一篇】:redis安装及redis数据类型
Redis介绍: 一.介绍 redis 是一个开源的.使用C语言编写的.支持网络交互的.可以基于内存也可以持久化的Key-Value数据库. redis的源码非常简单,只要有时间看看谭浩强的C语言,在 ...
- 解剖 Elasticsearch 集群 - 之三
解剖 Elasticsearch 集群 - 之三 本篇文章是一系列涵盖 Elasticsearch 底层架构和原型示例的其中一篇.在本篇文章中,我们会讨论 Elasticsearch 如何提供准实时搜 ...
- 解剖 Elasticsearch 集群 - 之一
解剖 Elasticsearch 集群 - 之一 本篇文章是一系列涵盖 Elasticsearch 底层架构和原型示例的其中一篇.在本篇文章中,我们会讨论底层的存储模型以及 CRUD(创建.读取.更新 ...
- ELK教程1:ElasticSearch集群的部署ELK
在分布式系统中,应用数量众多,应用调用链复杂,常常使用ELK作为日志收集.分析和展示的组件.本篇文章将讲讲解如何部署ELK,然后讲解如何使用Filebeat采集Spring Boot的日志输出到Log ...
- Elasticsearch集群搭建教程及生产环境配置
Elasticsearch 是一个极其强大的搜索和分析引擎,其强大的部分在于能够对其进行扩展以获得更好的性能和稳定性. 本教程将提供有关如何设置 Elasticsearch 集群的一些信息,并将添加一 ...
- Elasticsearch 集群和索引健康状态及常见错误说明
之前在IDC机房线上环境部署了一套ELK日志集中分析系统, 这里简单总结下ELK中Elasticsearch健康状态相关问题, Elasticsearch的索引状态和集群状态传达着不同的意思. 一. ...
随机推荐
- CentOS下SparkR安装部署:hadoop2.7.3+spark2.0.0+scale2.11.8+hive2.1.0
注:之前本人写了一篇SparkR的安装部署文章:SparkR安装部署及数据分析实例,当时SparkR项目还没正式入主Spark,需要自己下载SparkR安装包,但现在spark已经支持R接口,so更新 ...
- 你知道“移动端车牌识别”可以嵌入到PDA中应用吗?
一.移动端车牌识别产品描述 移动端车牌识别软件是基于移动平台的OCR识别应用程序,支持Android/IOS等多种主流移动操作系统.该产品只需通过智能手机或Pad的摄像头对准车牌,无需拍照,实现自动采 ...
- FFmpeg安装(windows环境)
♣FFmpeg是什么? ♣FFmpeg组成 ♣下载工具 ♣安装FFmpeg ♣应用到j2ee项目 前言:学习视频编码,一定要知道雷霄骅(leixiaohua1020)的专栏 ,伟大的程序员,26岁去世 ...
- nodeJS之TCP模块net
前面的话 TCP服务在网络应用中十分常见,目前大多数的应用都是基于TCP搭建而成的.net模块提供了一个异步网络包装器,用于TCP网络编程,它包含了创建服务器和客户端的方法.本文将详细介绍nodeJS ...
- C++抽象编程·运算符重载与友元函数
运算符重载(Operator overloading) 从我们在几个前篇的类的层次介绍中可以知道,C++可以扩展标准运算符,使其适用于新类型.这种技术称为运算符重载. 例如,字符串类重载+运算符,使其 ...
- 记一次 net 使用 data.oracleclient 使用错误
前提: 公司除了领导和开发人员具有管理员权限,其他人员使用的都是域账号. 过程: 应要求开发一个 winfrom项目,使用data.oracleclient 本地开发,调试无误,放到服务器共享域用户 ...
- Hibernate入门(一)
一 Hibernate介绍 Hibernate 是一个开源.轻量级的ORM(对象关系映射)工具,该工具简化了数据创建.数据处理和数据访问,它是一种将对象映射到数据库中表的编程技术.ORM工具内部使用J ...
- Tomcat 的 catalina.out 日志分割
一.背景 Tomcat 的 catalina.out 日志量不断增加,占用空间较大,且默认是不滚动的.因此,需要对其进行日志分割,并进行清理. 本文选用 Cronolog 对其进行分割. 二.安装 1 ...
- CoreLocation 框架
获取设备的地理位置和方向 一.概述 CoreLocation框架,它提供了如下几种服务 确定设备的地理位置 高度 方向 或到附近 iBeacon 的相对位置. 这个框架使用所有可用的车载硬件.如 Wi ...
- vue全家桶(Vue+Vue-router+Vuex+axios)(Vue+webpack项目实战系列之二)
Vue有多优秀搭配全家桶做项目有多好之类的咱就不谈了,直奔主题. 一.Vue 系列一已经用vue-cli搭建了Vue项目,此处就不赘述了. 二.Vue-router Vue的路由,先献上文档(http ...