如今,企业淹没在系统生成的浩瀚数据流当中。大数据技术业已集中在如何存储和处理这些海量的数据上。虽然离线数据的批处理非常重要,但我们通常需要对相应的实时数据做出明智的判断。这就是搜索引擎的用武之地, siteber.com 将其描述为“最具活力的行业”:
搜索引擎行业在过去几年的成长,已经足以巩固其在美国最具创新性行业之一的地位。
于是乎, Elasticsearch 和 Apache Solr 这两款当世领先的开源搜索引擎,正在享受着更广泛的使用,吸引着更多人的关注。Gheorghe、Hinman 和 Russo 所著的新书《Elasticsearch in Action》是一本非常好的书,简洁地一步步介绍了搜索,解释了 Elasticsearch 是如何实现搜索功能的,并提供很多代码示例。这本书还深入讲述了 Elasticsearch 的管理和配置,强调了索引和搜索性能之间的权衡。
这本书的主要内容分为两部分:“核心功能”和“高级功能”,随后是几个附录,覆盖了非常重要但不通用的功能(只适用于一些特殊的应用场景)。
本书的第一部分描述了 Elasticsearch 核心构建块及其功能。覆盖了 Elasticsearch 建模和索引数据的主要功能和方法,它们将用于支持基于应用系统的查询和分析。
- 第一章介绍了通用搜索引擎的功能,及其在 Elasticsearch 中的实现。这章的最后介绍了 Elasticsearch 的安装,用于运行全书提供的示例。
- 第二章讲述了 Elasticsearch 服务器中的数据组织,包括逻辑数据模型(搜索应用与 Elasticsearch 交互的方式)和物理布局(服务器内部处理数据的方式)。接下来,展示了这种数据模型是如何运用于典型的操作场景之中,即索引文档、查询文档、通过聚合分析数据,并水平扩展到多个节点上。
- 第三章详述了从 Elasticsearch 读写数据和维护数据的细节:索引、更新和删除文档。通过分析文档的字段,详述了索引过程;向读者讲述了当我们写入时,都包含哪些内容,会发生什么事情。
- 第四章详述了全文搜索,包括主要的查询器和过滤器、它们的内部工作机制,以及各种搜索方法的权衡。本章的最后,演示了一些最常用的过滤器和查询器,并解释了它们对于不同应用场景的适用性。
- 第五章阐述了如何将文档和查询器中的文本,分析和拆分为用于搜索的词条。本章介绍了 Elasticsearch 提供的不同类型的分析器,并说明了如何构建我们自己的分析器,以充分利用 Elasticsearch 的全文搜索潜能。本章还介绍了用于解决复杂搜索业务的 Ngrams、Shingles 和 Stemming。
- 第六章关注于相关性计算,也就是打分(score),它定义了文档对原始查询的相关性。本章描述了影响文档打分的因素及其维护方式——使用不同的打分算法、调整指定查询器或者字段的 boost 值。本章还展示了 Elasticsearch 中,用于计算打分的 API。
- 第七章展示了如何使用聚合来执行实时数据分析。在 Elasticsearch 中的具体做法是,加载文档、匹配搜索条件,以及执行各种排序计算,比如统计字符类型字段中词项的数量,或者计算数值类型字段的平均值。聚合被分为两种:度量和桶。度量聚合是指对一组文档进行静态分析,得到度量值,比如最小值、最大值、均方差等。桶式聚合将匹配的文档拆分进一个或多个桶容器,然后告诉你每个桶里有多少文档。
- 第八章是第一部分的最后一章,讲述了 Elasticsearch 对关系的支持。本章讨论了 Elasticsearch 提供的处理关系的几种常见方法,包括对象类型、嵌套文档、父子关系和一般的非规范化。同时,说明了如何使用每一种方法,以及它的优点和缺点。
本书的第二部分讲述了如何在生产环境中使用 Elasticsearch。书中提供了每种功能的工作原理,及其对性能和稳定性的影响:
- 第九章讲述了水平扩展 Elasticsearch 到多个节点。包括增加、删除、解除节点、选举 Master 的过程和分片迁移的机制。还深入分析了扩展的策略,包括索引分片和副本的最佳实践,比如,使用 Oversharding 或者基于时间的索引来确保当前的设计可以处理明年的数据。此外,还说明了如何使用索引别名和路由来提高集群的灵活性和可扩展性。在本章的最后,演示了如何使用 Elasticsearch 的 API 展示集群的状态和健康状况。
- 第十章讲述了多种提高集群性能的办法。首先是如何将多个请求,比如 index、update、delete、get 和 search 合并成一次 HTTP 调用。这种分组通过最小化网络往返流量,可以大幅提高应用的性能。接着是 Elasticsearch 如何处理 Lucene(底层搜索库)段:如何设置读写的刷新(refresh 和 flush)、合并策略和存储,这些设置对索引和搜索性能有何影响,以及在索引和搜索之间性能调优的权衡。本章的最后,讨论了影响 Elasticsearch 速度的一个重要的因素,缓存。详述了过滤器缓存的细节和最佳实践。还讲述了分片查询缓存,以及如何在预留足够的空间给 Elasticsearch 堆空间的同时,给操作系统足够的空间去缓存索引。
- 第十一章讲述了监控和管理生产集群。包括额外的设置方法、简化集群管理,以及监控生产环境必要的度量指标。最后,讨论了备份和恢复一个数据节点。
六个附录包含了有关 Elasticsearch 的更多信息:
- 附录 A 是关于地理空间搜索的。它可以为应用带来位置感知能力。Elasticsearch 支持存储位置信息(点和多边形)和通用的空间操作,比如两点间距离、图形包含点、图形间重叠等计算。附录演示了如何在搜索中使用这一功能。
- 附录 B 是讲如何管理 Elasticsearch 插件的。插件是一种开箱即用的,能为 Elasticsearch 带来扩展和增强功能的强大方式。附录中介绍了两种类型的插件。一种是 site 插件,没有额外的功能,只是为 Elasticsearch 提供了网页服务。另一种是 code 插件,可以是任何包含 JVM 代码、能被 Elasticsearch 执行的插件。附录讲述了如何安装、使用和卸载插件。
- 附录 C 是关于 Highlighting 选项及其实现的。Highlighting 指示为什么文档出现再查询结果中,匹配的词项被加上强调样式,让用户感受到文档是说什么的,以及和查询之间的关系。
- 附录 D 是关于监控插件的。Elasticsearch 社区提供了很多监控插件,可以通过引人入胜的图形界面,更容易地管理集群的状态、索引,以及执行查询。
- 附录 E 是关于如何使用 Elasticsearch 渗滤器(percolator)的。渗滤器通常被定义为『搜索倒置』。渗滤器索引的是查询信息而不是索引文档。将查询注册并存储到内存当中,以便日后快速执行。使用渗滤器时,我们发送给 Elasticsearch 的是文档,而不是查询信息。这被称为渗滤文档,基本上会对其索引到小内存索引上。Elasticsearch 根据小索引从已然注册的查询信息中查询,并返回匹配的查询信息。
- 最后,附录 F 是关于建议器(suggester)的。附录解释了如何使用不同的建议器实现用户意图的自动补全功能。这里所描述的基本功能,包括词项和短语的建议、补全和上下文的建议。附录描述了各种建议器和 Elasticsearch 中与此功能相关的 API。
Manning 出版社为 InfoQ 的读者提供了这本书的第八章节选,“文档之间的关系”。
InfoQ 采访了本书的作者,一起讨论更多关于 Elasticsearch 的实现和使用的信息。
InfoQ:本书中,在讨论典型 Elasticsearch 用例时,你们提出的一个选项是“增加 Elasticsearch 到现有系统中”。这个选项假定增加 Elasticsearch 到现有的数据存储系统。由于 Elasticsearch 的数据可用性有延迟,这可能导致在不同的存储系统中,产生数据之间的竞赛条件。特别是当数据被删除的时候,Elasticsearch 仍然会返回查询结果。关于如何应对这样的情况,有什么好的建议吗?
Roy Russo:这种场景的最简回答是在应用层面管理整个过程,将分别从不同的数据存储系统中删除,封装为一个
try-catch
代码块,就像我们执行一次写操作。因此,第一步是调用 Elasticsearch 删除记录,然后调用主数据存储节点。如果任何阶段失败了,要处理异常逻辑。这里没有事务可用,因此异常处理需要手动回滚。因为我所见过的最常用的 Elasticsearch 使用是基于时间序列的数据,这种场景并不常见。除非在某种罕见环境中,大多数软件没有规律地从时间序列存储中删除记录。还有一个办法是使用 Elasticsearch 作为单独的数据存储系统,但是这将带来其他健康方面的讨论,我不想陷于此处。
InfoQ:在 Otis Gospodnetić所写的 Elasticsearch 对比 Solr 的文章中说,相比控制在一家公司手中的 Elasticsearch 而言,Solr 更加开源。你同意这种评价吗,这对 Elasticsearch 用户来说是个问题吗?
Roy Russo:首先,我得说自己是 Otis 在 Sematext 所做成就的粉丝,但是我不同意他的观点。两个项目都是以 Apache Software 许可分发的,它们都接受来自社区的提交,受益于透明的缺陷、pull 请求和讨论。任何情况下,给出一个专业的开源软件和一个业余的开源软件供选择,留给读者去选择哪个最适合他的下一次关键的部署。
Elasticsearch 用户受益于一个资金雄厚的公司提供的支持服务、插件和辅助产品,比如:Watcher,一种告警装置、Shield,支持认证和授权,以及与 Hadoop 集成。在很短的时间里,Elastic 已经将这个开源项目打造成一款产品。这里有一个区别,因为有一家公司在驱动产品,因此增加了质量保证流程、产品管理以决定哪些功能被添加、工艺路线图,以及结构化的工程团队做具体执行。我目前的角色是在关键任务的情况下部署大型集群、熟知这款由一个财务健康、专业的工程师团队所支持的产品。
InfoQ: Elasticsearch 集群的每一个节点都提供了 REST API 端点,Elasticsearch 是否提供了负载均衡的实现,以确保某个客户端不会压垮某一节点?
Roy Russo:虽然每个节点可以灵活地配置为不同的节点类型(Master、Client、Data)作为不完全解决方案,但是确实需要一个容错系统,我建议用户在 Elasticsearch 前面使用他们自己的负载均衡器。Nginx 常用于负载均衡 / 反向代理。因此,有很多的教程和示例在线演示不同的负载均衡方案(轮询、最后连接等等),甚至是使用 Nginx 为指定的 API 端点或者 HTTP 方法做重定向(认证 / 授权)。
InfoQ:在这本书中,你们只展示了如何使用 REST API 操作 Elasticsearch。与此同时,还存在很多 Elasticsearch 的 Java 客户端。有什么好的推荐吗?
Roy Russo:就全功能的实现而言,官方提供的 Java 客户端是最好的选择。使用官方的客户端,你的软件不会通过 REST API 通信,而是扮演一个正在加入集群的额外节点。以此方式附加到集群的好处是省去了每次请求中额外的跳(hop),因为操作会被自动路由到相关的节点。对于 Spring 用户来说,Spring Data Elasticsearch 可以完美地处理这些,通过在 ORM 中增加一些方便的属性即可。Spring Data Elasticsearch 以依赖包的方式内置了官方的 Elasticsearch Java 客户端,因此它的行为和使用 Spring Data 带来的益处一致。
InfoQ:父子关系实现上的描述稍微令人困惑。首先,你说父文档的索引过程不受到任何特殊影响,但子文档必须参考的父文档。你又说一个子文档参考一个父文档。我会认为这是指一个 ID 引用,但你后面又说,父文档可以在以后添加。因此,在这种情况下,如何指定引用呢?此外,你后面又谈到了父文档中有子文档的字段。这个字段是何时填充的呢?
Lee Hinman:子文档中对父文档的引用是通过 URL 中特殊的’parent’参数传入的,因此在索引子文档的时候父文档是不存在的,纵然这个父文档不存在,Elasticsearch 还是允许指定’parent’参数的。父子关系在子文档的特殊字段中指定(不是在父文档,这就是为什么在父文档不存在的情况下,可以索引子文档),has_child 查询或者 has_parent 查询,可以自动加载 id mapping 缓存。
InfoQ:在讲述多节点集群搜索时,你说“默认情况下,主分片和分片副本是轮询搜索的。”在这种情况下,是否存在本地因素?比如,一个副本存在与接收请求的节点,它将被使用?
Roy Russo:是的,如果主分片或者分片副本存在于当前节点,它将被使用。但是,有一点非常重要,我们必须意识到查询会在集群中广播到索引的每一个分片。那些分片执行本地查询并汇报匹配文档。
InfoQ:书中讲述了通过每个文档的版本号实现并发控制。Elasticsearch 为每个文档存储很多的版本号还是只存最后一个版本号?
Roy Russo:这是个常见话题而且令人困惑。Elasticsearch 根本没有提供版本控制,因为它保留了原始文档的拷贝。它只持有一个计数器,当文档更新、索引或者删除时,“_version”会自增。这是一个便捷的乐观锁,有助于保证在并发更新中,更新的是同一版本号的文档,而不是不同版本的。
InfoQ:书中讲述了两种节点的发现机制,多播(multicast)和单播(unicast,提供 host 列表)。两者都能用于 AWS。是否还有其他的发现机制,比如基于 AWS 的负载均衡组?
Roy Russo:在 AWS 上部署时,我强烈推荐 Elasticsearch cloud-aws 插件。使用 AWS IAM 角色分配到 EC2 实例上,或者使用 AWS Access key 配置 Elasticsearch 配置文件,可以神奇般地让节点彼此发现。如果希望使用 IAM 角色配置,需要注意的是只能在 EC2 创建的时候指定 IAM 角色,此后不能再次修改。这个 cloud-aws 插件,可以无缝地让同一集群名称的各个节点彼此通信,是 AWS 环境中确定推荐和支持的。
额外需要注意的是,因为 2.x 的发布,这款插件从 S3 插件中分离出来。那些我们自动备份在 S3 上的插件,现在需要单独安装。
InfoQ:在 Elasticsearch 实现 Lucene 索引合并时,是只对主分片操作,然后拷贝全部副本吗?
Lee Hinman:不是这样的,Elasticsearch 中的合并是独立运行的。因为 Elasticsearch 使用文档级别的副本,而不是文件级别,所以每个索引的每个分片的合并方式是不确定的。
InfoQ:现在 AWS 提供了 Elasticsearch托管服务,对 Elasticsearch 的采用会有什么影响?如何简化集群管理?
Roy Russo:坦白地讲,我希望这对 Elasticsearch 的采用没有伤害。我很喜欢 AWS,但是 Elasticsearch 的发展需要业余时间,也许会给 Elasticsearch 用户数月之久的糟糕体验。
使用 AWS Elasticsearch 服务部署一个集群只需要非常方便的几次点击,但是需要你为便捷牺牲灵活性和可扩展性,直到他们开放配置信息和功能。我已经看到和经历的一些显著问题是,无法调优和自定义 Elasticsearch 性能和日志,无法安装插件,无法支持 Elasticsearch v1.5.x,以及受阻于 CORS。此外,你无法在 VPC 及相关软件中运行该服务,我会规避直到 Amazon 在该服务上解决。谁知道呢?也许他们能阅读我们这本书,然后为 Elasticsearch 服务做出成功的改变。
作者简介
Roy Russo 是预测分析公司 Predikto 的工程副总裁。在加入 Predikto 之前,Roy 是佐治亚州亚特兰大 AltiSource 实验室的首席架构师。Roy 曾是亚特兰大营销自动化软件供应商 LoopFuse(最近被亚特兰大的 SalesFusion 收购)的联合创始人和产品管理副总裁。Roy 还帮助联合创建 JBoss Portal,JSR-168 兼容的企业级 Java 门户网站,是 Java 内容仓库,JSR-170 中,JBoss 的代表。他目前是领先的 ElasticSearch 集群开源监控和管理应用,ElasticHQ.org 的创始人《Elasticsearch in Action》一书的合作者。
Radu Gheorghe 供职于 Sematext,他为客户提供搜索咨询、产品支持,培训各种 Elasticsearch 和 Solr 的部署。他热衷于日志工具,比如 rsyslog(是的,这可能是钟爱之一),他在 Sematext 也得到了负责日志分析服务 Logsene 的机会。
Matthew Lee Hinman 是一位充满激情的软件开发者,寻找具有挑战性的软件开发。活跃于开源社区,是 Clojure 和 Elasticsearch 社区的贡献者。Lee 乐于在解决挑战性和趣味性问题的团队中工作。他非常关心代码质量,开源了他大部分业余时间编写的代码。
查看英文原文:“Elasticsearch in Action” – Book Review and Authors Interview
评论