一、与ES的邂逅
如果问自己最近几年最喜欢研究的技术,我会毫不犹豫地选择ES。源于5年前参加工作时接触到的一个产品,它最具有竞争力的功能就在于搜索,数据源是实时更新的,需要满足用户能实时搜索的核心需求。基于随着版本的迭代、数据量的快速增长这一特点,急需一种搜索性能良好且易于部署的搜索引擎满足产品需求,通过查阅资料以及专业的数据库综合测评网站:DBRanking,结果就这样邂逅了ES,下面正式开启ES之旅。
二、ES的研究之路
为什么选择它
这几年随着移动互联网、物联网的兴起,信息量呈现爆炸式的增长,早期的关系型数据库已无法满足从海量数据中快速筛选出所需信息的要求。数据种类与格式日益增多,不再局限于文本数据,而且现在需要从海量数据中提取出关键词,再根据关键词搜索出相关的数据记录,常规的模糊匹配无法满足性能指标。
除了高性能的检索,它的分布式特性,简单易用的DSL可以构建满足各种需求的聚合及数据分析,这些都是一般的SQL语句所不具备的。所以无论是基于ES开发业务层面的应用,还是做成一个通用的指标数据监控平台,它都是不二之选!DB-engines调查的数据库排名也说明在搜索引擎领域,也是位居首位!
应用场景
在我参与的研发中,主要是和Kafka配合做数据的存储和实时展示。其实ES的最常用的核心功能:检索和聚合在很多场景中都有落地实现,如:日志分析和舆情监控,数据聚合分析,安全监控,运维管理平台等等。在我们的日常生活中,比如打车软件、购物平台、地图搜索都有ES的身影,对于研发人员没有使用的Github,Wikipedia,里面的代码检索就是用ES做的。
- 云托管服务:阿里云ES集群托管
- 搜索领域:滴滴打车、高德地图、站内检索
- 安全领域:阿里安全在安全业务中的实践
- 数据查询:将ES作为NoSQL的替代方案,加速数据的查询
- 日志分析:通过Elastic Stack中的ELK可以完成日志的采集、存储、分析、搜索、监控、展示等整个流程;
架构初探
从架构图中可以看到,从底向上大体可以分为如下几层:
- 最底层是存储索引的文件系统;
- 往上一层是ES的基础:分布式的Lucene框架;
- 基于Lucene是搜索和索引模块,映射解析模块;
- 中间层就是节点发现与选举的模块,支持脚本语言的嵌入模块,而且支持第三方的插件接入;
- 接近用户层的传输模块,ES的管理模块;
- 最上层就是与用户交换的应用层,通过restful接口与ES集群交互数据。
高级特性
- 分布式特性:集群内的节点能自动分配平衡数据;
- 近实时搜索:从数据接入到可查询这个过程会有1秒的延时,所以称为近实时;
- 高可用:部分节点不可用不会导致这个ES挂掉,集群节点具有容错机制;
- 动态映射:根据索引的数据,自动判断字段的类型生成mapping,把索引存入ES;
- restful接口:使用json的结构,通过http请求可以很方便高效地与ES交互,支持多客户端;
分布式架构
分布式架构带来的好处是,支持水平扩容,提升系统的可用性,部分节点挂掉不影响整个集群的服务。
容易带来脑裂问题:
脑裂其实是分布式中的网络问题,由于网络出现问题,导致一个节点无法与其他节点连接,node2和node3会重新选举,node1单独作为一个集群选举,出现了多个master,当网络恢复时,无法正确恢复。
写数据底层原理
写数据的大致流程是:内存缓冲区 —> refresh -> 操作系统缓存 -> translog -> commit -> flush -> buffer区的数据写入segment file
1.数据先写入内存buffer,每隔1秒刷新数据到操作系统缓存(把数据写入segment),此时数据就能被搜索到(因为从segment写入磁盘相对比较耗时,借助操作系统的缓存,刷新阶段把segment先写入缓存以开放查询,这里解释了为什么是近实时搜索)
2.为了保证数据不丢失,索引数据的同时,每隔5秒,把数据写入translog文件,它默认会落盘(即使机器宕机,最多丢失5秒的数据)。【注:在第一步执行刷新操作时,内存buffer的数据会被清空,translog文件不会清空】
3.当translog文件大到一定程度,或默认每隔30分钟,触发commit操作,把缓冲区的数据flush到segment file磁盘文件中,此时就建好了倒排索引。具体就是此阶段会调用fsync,将segment写入磁盘,同时清空translog文件
倒排索引
通常作数据搜索的思路是:在数据的字段中模糊匹配关键词,如果匹配成功,则返回对应的数据。但是这里的有个最大的问题是,模糊匹配很耗费性能,影响检索效率,在大文本数据中体现得尤其明显。ES采取了非常规的思路,设计了倒排索引的数据结构,就是把文本进行分词处理,提取出其中的词项,然后建立词项到文档的映射关系,形成倒排索引表。
倒排索引:其实由单词词典、倒排列表和倒排文件组成。
- 单词词典:是文档集合中所有的单词的集合;
- 倒排列表记录了词项到文档的映射关系,每个倒排列表项包含:词项,文档id集合,词项在文档中的次数,出现的偏移位置等;
- 倒排文件:用于存储所有单词对应的倒排列表,这里是存储倒排索引的物理文件。
通过图示理解如下:
创建倒排索引步骤大致以下几步:
- 分词器处理;
- 单词处理器,自然语言理解;
- 合成倒排列表,生成索引;
问题思考:
为什么ES检索比MySQL快?
MySQL:只有词项字典这一层,底层用的是B+树的数据结构存储,检索一个词项需要若干次的磁盘随机读写;
ES:Lucene在词项字典的基础上增加了词项索引这一层,它以字典树的数据结构缓存在内存,根据词项索引找到词项字典中的位置之后,再去磁盘查找词项,这样减少了磁盘的随机读写次数,大大地提升了检索性能。图示理解如下:
搜索机制
搜索文档的步骤:
- 查询分析;
- 分词处理;
- 关键词检索;
- 搜素排序,返回结果;
示例如下,假设有如下四个文档:
通过建立倒排索引,建立词项到文档的映射表:
如果要根据某个关键词查找出对应的文档,会经历如下图示的过程:
图中从第一象限到第四象限,表示整个的搜索流程:
- 文档写入ES之后,经过分词、过滤操作后会生成倒排索引;
- 用户发送搜索请求,后台收到请求会到倒排列表中查询词项对应的文档集合列表;
- 后台经过评分、排序、高亮等处理之后,最终返回结果给用户;
分布式更新文档
更新过程:
- 用户发送更新请求到Coordinate Node,它根据hash路由算法把请求路由到另一个节点;
- 节点node先执行删除操作,再执行index操作;
- 最后写入成功之后,发送成功结果给用户;
分布式删除文档
删除过程:
- 用户发送删除请求到Coordinate Node(协调节点),根据hash路由算法把请求路由到主分片节点;
- 把删除副本的请求发送给协调节点,执行删除操作,删除完成之后返回删除成功给主分片节点;
- 主分片节点把删除成功的结果返回给协调节点,最后返回响应结果给用户;
三、ES学习不止
ES的探究之路目前还只停留在应用层面,底层原理及源码层面还涉猎甚少。在官方的版本快速迭代下,弄清楚新版本的改进点及引进的新特性实属非常有必要,接下来的学习脚步将会继续下去,不仅仅是ES本身这一项技术,学习其它的技术也是一样,既然选择了学习一项技术,就要彻底弄懂它。
四、ES未来的无限可能
随着物联网5G时代的来临,大数据的检索需求也会趋于多元化,更加智能化,在更新的版本中,官方也在其中引入了机器学习模块,顺应了日志监控,安全异常检测等系统越来越智能化的趋势。随着ECS的推出,拥抱K8s已成必然,目前提供了集群的管理和升级,弹性伸缩的能力,更好地支持云原生,最后,个人很看好Elastic Stack在未来的进一步发展!
道可顿悟,事需渐修!