1. Elasticsearch是什么

1.1 Elasticsearch简介


  Elaticsearch,简称为 ES, ES 是一个开源的高扩展的分布式全文搜索引擎,是整个 Elastic Stack 技术栈的核心。它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理 PB 级别的数据。 ES 也使用 Java 开发并使用 Lucene 作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的 RESTful API 来隐藏 Lucene 的复杂性,从而让全文搜索变得简单

1.2 全文搜索引擎

  Google,百度类的网站搜索,它们都是根据网页中的关键字生成索引,我们在搜索的时候输入关键字,它们会将该关键字即索引匹配到的所有网页返回;还有常见的项目中应用日志的搜索等等。对于这些非结构化的数据文本,关系型数据库搜索不是能很好的支持。
  一般传统数据库,全文检索都实现的很鸡肋,因为一般也没人用数据库存文本字段。进行全文检索需要扫描整个表,如果数据量大的话即使对 SQL 的语法优化,也收效甚微。建立了索引,但是维护起来也很麻烦,对于 insert 和 update 操作都会重新构建索引。
  基于以上原因可以分析得出,在一些生产环境中,使用常规的搜索方式,性能是非常差的:

  • 搜索的数据对象是大量的非结构化的文本数据;
  • 文件记录量达到数十万或数百万个甚至更多;
  • 支持大量基于交互式文本的查询;
  • 需求非常灵活的全文搜索查询;
  • 对高度相关的搜索结果的有特殊需求,但是没有可用的关系数据库可以满足;
  • 对不同记录类型、非文本数据操作或安全事务处理的需求相对较少的情况;

  为了解决结构化数据搜索和非结构化数据搜索性能问题,我们就需要专业,健壮,强大的全文搜索引擎。
  这里说到的全文搜索引擎指的是目前广泛应用的主流搜索引擎。它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。

1.3 Elasticsearch VS Solr

  Lucene 是 Apache 软件基金会 Jakarta 项目组的一个子项目,提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在 Java 开发环境里 Lucene 是一个成熟的免费开源工具。就其本身而言,Lucene 是当前以及最近几年最受欢迎的免费 Java 信息检索程序库。但 Lucene 只是一个提供全文搜索功能类库的核心工具包,而真正使用它还需要一个完善的服务框架搭建起来进行应用。
  目前市面上流行的搜索引擎软件,主流的就两款:Elasticsearch 和 Solr,这两款都是基于 Lucene 搭建的,可以独立部署启动的搜索引擎服务软件。由于内核相同,所以两者除了服务器安装、部署、管理、集群以外,对于数据的操作 修改、添加、保存、查询等等都十分类似。
  在使用过程中,一般都会将 Elasticsearch 和 Solr 这两个软件对比,然后进行选型。这两个搜索引擎都是流行的,先进的的开源搜索引擎。它们都是围绕核心底层搜索库 Lucene 构建的,但它们又是不同的。像所有东西一样,每个都有其优点和缺点:

特征 Solr/SolrCloud Elasticsearch
社区和开发者 Apache 软件基金和社区支持 单一商业实体及其员工
节点发现 Apache Zookeeper,在大量项目中成熟且经过实战测试 Zen 内置于 Elasticsearch 本身,需要专用的主节点才能进行分裂脑保护
碎片放置 本质上是静态,需要手动工作来迁移分片,从 Solr 7 开始 Autoscaling API 允许一些动态操作 动态,可以根据群集状态按需移动分片
高速缓存 全局,每个段更改无效 每段,更适合动态更改数据
分析引擎性能 非常适合精确计算的静态数据 结果的准确性取决于数据放置
全文搜索功能 基于 Lucene 的语言分析,多建议,拼写检查,丰富的高亮显示支持 基于 Lucene 的语言分析,单一建议 API 实现,高亮显示重新计算
DevOps 支持 尚未完全,但即将到来 非常好的 API
非平面数据处理 嵌套文档和父子支持 嵌套和对象类型的自然支持允许几乎无限的嵌套和父子支持
查询 DSL JSON (有限),XML (有限)或URL参数 JSON
索引/收集领导控制 领导者安置控制和领导者重新平衡甚至可以节点上的负载 不可能
机器学习 内置在流聚合之上,专注于逻辑回归和学习排名贡献模块 商业功能,专注于异常和异常值以及时间序列数据

  Elasticsearch 和 Solr 都是开源搜索引擎,那么我们在使用时该如何选择呢?

  • Google 搜索趋势结果表明,与 Solr 相比,Elasticsearch 具有很大的吸引力,但这并不意味着 Apache Solr 已经死亡。虽然有些人可能不这么认为,但 Solr 仍然是最受欢迎的搜索引擎之一,拥有强大的社区和开源支持。
  • 与 Solr 相比,Elasticsearch 易于安装且非常轻巧。此外,可以在几分钟内安装并运行 Elasticsearch。但是,如果 Elasticsearch 管理不当,这种易于部署和使用可能会成为一个问题。基于 JSON 的配置很简单,但如果要为文件中的每个配置指定注释,那么它不适合我们。总的来说,如果我们的应用使用的是 JSON,那么 Elasticsearch 是一个更好的选择。否则,请使用 Solr,因为它的 schema.xml 和 solrconfig.xml 都有很好的文档记录。
  • Solr 拥有更大,更成熟的用户,开发者和贡献者社区。ES 虽拥有的规模较小但活跃的用户社区以及不断增长的贡献者社区。Solr 贡献者和提交者来自许多不同的组织,而 Elasticsearch 提交者来自单个公司。
  • Solr 更成熟,但 ES 增长迅速,更稳定。
  • Solr 是一个非常有据可查的产品,具有清晰的示例和 API 用例场景。 Elasticsearch 的文档组织良好,但它缺乏好的示例和清晰的配置说明。

  那么,到底是 Solr 还是 Elasticsearch?
  有时很难找到明确的答案。无论我们选择 Solr 还是 Elasticsearch,首先需要了解正确的用例和未来需求,总结他们的每个属性。

  • 由于易于使用,Elasticsearch 在新开发者中更受欢迎。一个下载和一个命令就可以启动一切;
  • 如果除了搜索文本之外还需要它来处理分析查询,Elasticsearch 是更好的选择;
  • 随着数据量的增加,Solr 的搜索效率会变得更低,而 ElasticSearch 却没有明显的变化;
  • Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能;
  • Solr 支持更多格式的数据,比如 JSON、XML、CSV,而 Elasticsearch 仅支持 Json 文件格式;
  • Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供,例如图形化界面需要 Kibana 友好支撑;
  • 单纯的对已有数据进行搜索时,Solr 更快,但更新索引时慢(即插入删除慢),用于电商等查询多的应用;
  • ES 建立索引快(即查询慢),即实时性查询快,用于 facebook、新浪等搜索。
  • 如果需要分布式索引,则需要选择 Elasticsearch。对于需要良好可伸缩性和以及性能分布式环境,Elasticsearch 是更好的选择;
  • Solr 是传统搜索应用的有力解决方案,但 Elasticsearch 更适用于新兴的实时搜索应用;
  • Solr 比较成熟,有一个更大,更成熟的用户、开发和贡献者社区,而 Elasticsearch 相对开发维护者较少,更新太快,学习使用成本较高;
  • 如果你喜欢监控和指标,那么可以使用 Elasticsearch,因为相对于 Solr,Elasticsearch 暴露了更多的关键指标。

1.5 Elasticsearch应用案例

  • GitHub:2013 年初,抛弃了 Solr,采取 Elasticsearch 来做 PB 级的搜索。GitHub 使用 Elasticsearch 搜索 20TB 的数据,包括 13 亿文件和 1300 亿行代码。
  • 维基百科:启动以 Elasticsearch 为基础的核心搜索架构 。
  • SoundCloud:SoundCloud 使用 Elasticsearch 为 1.8 亿用户提供即时而精准的音乐搜索服务。
  • 百度:目前广泛使用 Elasticsearch 作为文本数据分析,采集百度所有服务器上的各类指标数据及用户自定义数据,通过对各种数据进行多维分析展示,辅助定位分析实例异常或业务层面异常。目前覆盖百度内部 20 多个业务线(包括云分析、网盟、预测、文库、直达号、钱包、风控等),单集群最大 100 台机器,200 个 ES 节点,每天导入 30TB+ 数据。
  • 新浪:使用 Elasticsearch 分析处理 32 亿条实时日志。
  • 阿里:使用 Elasticsearch 构建日志采集和分析体系。
  • Stack Overflow:解决 Bug 问题的网站,全英文,编程人员交流的网站。

2. Elasticsearch入门

2.1 Elasticsearch安装

2.1.1 下载软件

  Elasticsearch 的官方地址:https://www.elastic.co/cn/
  Elasticsearch 目前最新的版本是 8.0.0,我们选择 7.17.0 版本(最好不要选最新的版本)
  下载地址:https://www.elastic.co/cn/downloads/past-releases#elasticsearch


  Elasticsearch 分为 Linux 和 Windows 版本,基于我们主要学习的是 Elasticsearch 的 Java 客户端的使用,所以课程中使用的是安装较为简便的 Windows 版本(后续再单独开一篇博客详细说 Linux 的部署教程)。

2.1.2 安装软件

  Windows 版的 Elasticsearch 的安装很简单,解压即安装完毕,解压后的 Elasticsearch 的目录结构如下:

目录 含义
bin 可执行脚本目录
config 配置目录
jdk 内置 JDK 目录
lib 类库
logs 日志目录
modules 模块目录
plugins 插件目录

  解压后,进入bin文件目录,点击elasticsearch.bat文件启动 ES 服务:


  注意:9300端口为 Elasticsearch 集群间组件的通信端口,9200端口为浏览器访问的 http 协议 RESTful 端口。
  打开浏览器(推荐使用谷歌浏览器),输入地址:http://localhost:9200,测试结果:

2.1.3 问题解决

  • Elasticsearch 是使用 java 开发的,且 7.11 版本的 ES 需要 JDK 版本 1.8 以上,默认安装包带有 jdk 环境,如果系统配置 JAVA_HOME,那么使用系统默认的 JDK,如果没有配置使用自带的 JDK,一般建议使用系统配置的 JDK。
  • 双击启动窗口闪退,通过路径访问追踪错误,如果是 “空间不足”,请修改 config/jvm.options 配置文件,添加以下内容:
1
2
3
4
5
6
# 设置JVM初始内存为1G。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存 
# Xms represents the initial size of total heap space
# 设置JVM最大可用内存为1G
# Xmx represents the maximum size of total heap space
-Xms1g
-Xmx1g

  如果本地 JDK 版本不够高,可以手动指定使用自带高版本 JDK,在bin目录下找到elasticsearch-env.bat并打开,加入我们 ES 本身自带的 jdk 路径:


  保存后重新执行elasticsearch.bat即可。

2.2 核心概念

2.2.1 索引(Index)

  一个索引就是一个拥有几分相似特征的文档的集合。比如说,我们可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字来标识(必须全部是小写字母),并且当我们要对这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。在一个集群中,可以定义任意多的索引。
  能搜索的数据必须索引,这样的好处是可以提高查询速度,比如:新华字典前面的目录就是索引的意思,目录可以提高查询速度。
  Elasticsearch 索引的精髓:一切设计都是为了提高搜索的性能。

2.2.2 类型(Type)

  在一个索引中,我们可以定义一种或多种类型。
  一个类型是我们索引的一个逻辑上的分类/分区,其语义完全由我们自己来定。通常,会为具有一组共同字段的文档定义一个类型。不同的版本,类型发生了不同的变化。

版本 Type
5.x 支持多种 type
6.x 只能有一种 type
7.x 默认不再支持自定义索引类型(默认类型为:_doc)

2.2.3 文档(Document)

  一个文档是一个可被索引的基础信息单元,也就是一条数据
  比如:我们可以拥有某一个客户的文档,某一个产品的一个文档,当然,也可以拥有某个订单的一个文档。文档以 JSON(Javascript Object Notation)格式来表示,而 JSON 是一个到处存在的互联网数据交互格式。
  在一个 index/type 里面,我们可以存储任意多的文档。

2.2.4 字段(Field)

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

2.2.5 映射(Mapping)

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

2.2.6 分片(Shards)

  一个索引可以存储超出单个节点硬件限制的大量数据。比如,一个具有 10 亿文档数据的索引占据 1TB 的磁盘空间,而任一节点都可能没有这样大的磁盘空间。或者单个节点处理搜索请求,响应太慢。为了解决这个问题,Elasticsearch 提供了将索引划分成多份的能力,每一份就称之为分片。当我们创建一个索引的时候,我们可以指定自己想要的分片的数量。每个分片本身也是一个功能完善并且独立的 “索引”,这个 “索引” 可以被放置到集群中的任何节点上。
  分片很重要,主要有两方面的原因:

  1. 允许我们水平分割 / 扩展自己的内容容量。
  2. 允许我们在分片之上进行分布式的、并行的操作,进而提高性能/吞吐量。

  至于一个分片怎样分布,它的文档怎样聚合和搜索请求,是完全由 Elasticsearch 管理的,对于作为用户的我们来说,这些都是透明的,无需过分关心。
  被混淆的概念是,一个 Lucene 索引 我们在 Elasticsearch 称作分片 。 一个 Elasticsearch 索引是分片的集合。 当 Elasticsearch 在索引中搜索的时候,他发送查询到每一个属于索引的分片(Lucene 索引),然后合并每个分片的结果到一个全局的结果集。

2.2.7 副本(Replicas)

  在一个网络 / 云的环境里,失败随时都可能发生,在某个分片/节点不知怎么的就处于离线状态,或者由于任何原因消失了,这种情况下,有一个故障转移机制是非常有用并且是强烈推荐的。为此目的,Elasticsearch 允许我们创建分片的一份或多份拷贝,这些拷贝叫做复制分片(副本)。
  复制分片之所以重要,有两个主要原因:

  1. 在分片/节点失败的情况下,提供了高可用性。因为这个原因,注意到复制分片从不与原/主要(original/primary)分片置于同一节点上是非常重要的。
  2. 扩展我们的搜索量/吞吐量,因为搜索可以在所有的副本上并行运行。总之,每个索引可以被分成多个分片。一个索引也可以被复制 0 次(意思是没有复制)或多次。一旦复制了,每个索引就有了主分片(作为复制源的原来的分片)和复制分片(主分片的拷贝)之别。分片和复制的数量可以在索引创建的时候指定。在索引创建之后,我们可以在任何时候动态地改变复制的数量,但是我们事后不能改变分片的数量。默认情况下, Elasticsearch 中的每个索引被分片 1 个主分片和 1 个复制,这意味着,如果我们的集群中至少有两个节点,我们的索引将会有 1 个主分片和另外 1 个复制分片(1 个完全拷贝),这样的话每个索引总共就有 2 个分片,我们需要根据索引需要确定分片个数。

2.2.8 分配(Allocation)

  将分片分配给某个节点的过程,包括分配主分片或者副本。如果是副本,还包含从主分片复制数据的过程。这个过程是由 master 节点完成的。

2.3 Elasticsearch核心概念 VS 数据库核心概念

关系型数据库(比如Mysql) 非关系型数据库(Elasticsearch)
数据库Database 索引Index
表Table 索引Index(原为Type)
数据行Row 文档Document
数据列Column 字段Field
约束 Schema 映射Mapping

  Elasticsearch(集群)中可以包含多个索引(数据库),每个索引中可以包含多个类型(表),每个类型下又包含多个文档(行),每个文档中又包含多个字段(列)。

2.4 系统架构


  一个运行中的 Elasticsearch 实例称为一个节点,而集群是由一个或者多个拥有相同 cluster.name 配置的节点组成, 它们共同承担数据和负载的压力。当有节点加入集群中或者从集群中移除节点时,集群将会重新平均分布所有的数据。
  当一个节点被选举成为主节点时, 它将负责管理集群范围内的所有变更,例如增加、删除索引,或者增加、删除节点等。 而主节点并不需要涉及到文档级别的变更和搜索等操作,所以当集群只拥有一个主节点的情况下,即使流量的增加它也不会成为瓶颈。 任何节点都可以成为主节点。我们的示例集群就只有一个节点,所以它同时也成为了主节点。
  作为用户,我们可以将请求发送到集群中的任何节点 ,包括主节点。 每个节点都知道任意文档所处的位置,并且能够将我们的请求直接转发到存储我们所需文档的节点。 无论我们将请求发送到哪个节点,它都能负责从各个包含我们所需文档的节点收集回数据,并将最终结果返回給客户端。 Elasticsearch 对这一切的管理都是透明的。