ES的一知半解

一个互联网应用(例如网上商城),搜索功能基本上是必备的。搜索的解决方案要快,最好有一个零配置和完全免费的搜索模式,能够简单地使用JSON通过HTTP的索引数据。搜索服务器始终可用,并能够从一台扩展到数百台,搜索的实时性要好......

Elasticsearch(简称ES)不仅可以解决这些问题,而且可以做更多的事情。

ES 是什么

ES是基于Lucene的实时搜索和分析引擎,可以用来做全文检索、结构化数据检索、聚合分析等等。ES支持分布式部署到数百节点,以及PB级别的数据。

2010年有了第一个版本,后来成立了商用公司,到2014年2月发布的1.0版本,直到最新的6.5版本。多家云服务厂商也提供了ES服务。ES对外提供RESTful API接口,数据以JSON形式组织,查询也以JSON形式来描述。

为了通俗的理解,可以与MySQL 进行类比。

ES的集群类似于数据库集群。Index的名字,相当于database的名字;Type的名字,相当于table名; Field的名字,相当于column名,这里对Field有约束: 数据类型必须是string,否则报错,另外建立索引时对string做分词处理。在http的URL里包含插入的Index,Type,还有Document的唯一标识ID。如果没有指定ID,那么ES会自动生成ID。

Lucene 基础

ES 是构建在Lucene基础之上的,了解一下Lucene是必要的。

Lucene 是apache软件基金会一个开放源代码的全文检索引擎工具包,是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎。

类似Lucene这样的检索工具,主要过程包括获取内容,构建文档,分析文档和索引文件。

Lucene Directory 是一个抽象的文件系统的接口,用来允许你读写文件,不管lucene的索引是存放在内存中还是在物理磁盘上,它都是通过lucene的Directory抽象层来访问和维护的。

IndexWriter 用来添加、删除和更新lucene里面的索引文档。这些操作是在内存中完成以保证更好的性能,但是保证这些操作的持久化,这些操作是需要flush到磁盘的。flush操作或者是显式的commit提交开销都是比较大的,每次只能有一个IndexWriter对象来对一个索引目录进行索引操作,并且创建这个对象的开销很大。

Lucene 索引被分解为很多段(segments)。每个索引段实际上是一个功能完整的lucene索引,一旦一个索引段创建完成,它将是不可变的,并且不能删除段里面的索引文档。lucene内部会来对commit提交的这些段进行合并,所以要有策略来控制这些合并。

ES架构概要

Elastic Stack 整体的架构如下:

ES的集群节点主要分为Master Node和Data Node,每个节点上都存有全量的元数据。元数据的修改从master node开始,然后全量/增量地publish到数据节点。

Master Node负责节点加入与退出,Index创建与删除、Mapping修改,集群配置修改(比如线程数,Shard分配,移动等)。Data Node负责存储用户数据。每个节点的代码一致,只是根据配置看是否启用相应的功能.

随着产品的升级,引入了更多节点类型:

ES有很多特点,个人觉得需要重点关注的是——Sharding,Replica 和Transaction Log。

Sharding

在实用性的角度来看基于文档的分区方式已经被证明是一个构建大型的分布式信息检索系统的一种行之有效的方法, ES 使用的就是基于文档的分区方式。

一个Index被划分为多个shard,每个shard都有一个单独的Lucene引擎。通过REST API来指定shard(Shardid = hash(doc id)% shard_num)的数目,并且只能在创建Index时指定。

Replication

一般有两种方式来实现复制: Push Replication(推模式) 和 Pull Replication(拉模式)。ES 使用的是Push Replication(推模式)。

用户通过REST API来指定副本的数目,可以在创建Index时指定,也可以创建完成后修改。在多个replica中,ES会选择一个来做Primary。

ES的写入流程如下:

  1. Client 将数据发送到链接的节点上

  2. 节点根据routing计算,把数据发送到primary节点上

  3. Primary local写入成功

  4. 发送给replica

ES的查询流程分为两个阶段:Query 和 Fetch。具体流程如下:

1)客户端把search请求发送到某个节点上,该节点把请求转发到所有的shard上,每个shard收到请求后,需要在本地执行请求,并建立一个优先级队列。

2)每个shard把doc id和排序相关的值返回给该节点,此节点合并各个shard的结果,并建立本地的优先级队列。

3)该节点根据本地排序的结果计算出那些doc需要获取,向对应的shard发送fetch请求。每个shard从本地读取文档,返回给节点。

4)此节点获取完所有的文档后,把结果返回到客户端。

Transaction Log

索引提交的开销较大大,但又必须通过提交操作来保证数据被可靠的持久化,ES通过使用 transaction log,通过日志记录发生在索引上的各种操作,来保证数据的持久化。并且能够很自然的支持推送复制,就算某些节点崩溃了,如果有必要,可以很轻松对日志操作进行回放。

Transaction log 周期性的将数据刷新(flushed)到磁盘,你可以通过 参数 来进行控制。 简单来说就是保存两次提交之间的连续数据操作的记录。

ransaction log还有一个重要的功能就是可以保证在生成快照、分片恢复或是分片热迁移的时候,索引数据不会丢失。

ES的大规模部署架构大约是这样的:

一些场景

举几个例子吧,Github使用ES搜索20TB的数据,包括数十亿的文件和数千亿行的代码。Github在2013年1月升级了代码搜索,由solr转为ES详情请看博客https://github.com/blog/1381-a-whole-new-code-search。而Mozilla公司以火狐著名,使用 WarOnOrange 这个项目来进行单元或功能测试,测试的结果以 json的方式索引到ES中,开发人员可以非常方便的查找 bug。Socorro是公司的程序崩溃报告系统,一有错误信息就插入到 Hbase和PG中,然后从 Hbase中读取数据索引到ES中,方便查找。

除了搜索功能以外,ES 还有一些典型的应用场景。

日志分析

ELK是社区非常流行的一个用来收集和分析日志的架构:

  • Beats: 轻量级数据摄取组件

  • Logstash:ETL组件,把数据抽取并写入ES

  • ES: 分布式的搜索引擎

  • Kibana: 查询ES并做数据可视化,百度自己也开发了一些可视化组件

APM度量

度量是性能优化的前提,ES与APM结合,可以更好的完成性能可视化的工作。

多租户视图

ES中的用户体系包括内置用户(root/superuser)和普通用户。

Root是内置的系统管理用户,进行cluster setting,recovery设置,节点加入退出等。Superuser是管理数据的超级用户,能够创建用户,访问所有用户的数据等。普通用户由Superuser来建立,用来操作相应的业务数据,其权限类型包括READ_ONLYREAD_WRITE

多租户管理用来解决多个业务共享一个集群的问题,隔离的内容包括配置,索引,cpu和io等。每个节点上启动多个实例,每个实例配置IO,CPU,MEMORY和DISK QUOTA等。Master节点。根据一定的策略把实例分配给一个租户。对用户的可视化呈现同样如此。

遇到过的一些问题

“没有银弹”,ES 也不例外,踩坑和填坑是必然的成长过程。

ES不稳定问题

ES不稳定的后果比较严重,可能会停服。大多数不稳定是由高并发读/写。一般滴,可以考虑用户写入MySQL或修改操作、事务仲裁,做数据备份,并提供降级服务,以防止ES不稳定,但MySQL的MPP查询是有限制。

在捕获MySQL的变更之后,ES完成分析查询。需要注意的是,部分业务有分词需求。

数据不一致问题

各个节点的元数据不是实时一致的。客户端可能连接到一个旧的Primary,然后读取到旧数据的副本集,从而不能拒绝处于“假死”状态Primary的写请求。另外,各个副本接收到的数据的顺序也可能不一致。一旦Primary出现故障,无法通过简单的Truncate机制将各副本的数据恢复到一致状态。

这时,可以考虑快照抓取和lease机制。

shard 的恢复问题

当ES集群挂掉一个节点,可能会触发集群中大量的shard恢复和迁移操作,占用大量的系统资源,此时继续写入入就会因为个别节点负载过高而导致速度下降甚至超时。

一般地,可以放宽shard的迁移条件,减少不必要的平衡。当必须要进行shard迁移时,优先移动那些“较老”当shard,或者延迟recovery的时间。

总少不了OOM

ES查询时会把字段值放到内存,尤其是facet查询,对内存要求高,会把结果都放在内存,然后进行排序等操作,一直到使用完毕,当内存不够用时就有可能出现out of memory错误了。

一般地, 可以考虑将缓存类型设置为软引用,并调整ES的最大缓存数据条数和缓存失效时间。

跨机房脑裂

Master节点需要至少minimum_master_nodes 节点投票才能赢得选举,将其设置为合适的数据可部分防止脑裂的场景。

生产集群一般有3个专用的master节点,可以设置minimum_master_nodes=2。

照见现实

ES 从开始的Elasticsearch发展成了Elast Stack,那些x-pack的插件也都称为了ES的诸多feature:

  • Security

  • Alerting

  • Monitoring

  • Reporting

  • Graph

  • Machine Learning

  • Elasticsearch SQL

  • Canvas

在各种技术的组合应用中,ES同样凸显价值,例如与Kafka配合完成跨机房数据传输,与Flink配合实现实时流数据查询,与各种分析工具的无缝衔接等等。个人曾经尝试过 ES over Yarn,现在ES已经几乎是Hadoop上的一个标准插件了。

这是一个云计算的时代,各大公有云厂商(例如,国外的AWS/Azure,国内的百度云/阿里云/青云等等)也都提供了ES云服务。当然,使用ES可以构建自己的私有云服务,实现企业部署。

参考资料
  • https://lucene.apache.org

  • https://www.elastic.co/

  • https://www.elastic.co/pdf/architecture-best-practices.pdf


要回复问题请先登录注册