Elasticsearch
Elasticsearch(简称ES)是一个分布式、可扩展、实时的搜索与数据分析引擎。ES不仅仅只是全文搜索,还支持结构化搜索、数据分析、复杂的语言处理、地理位置和对象间关联关系等。
ES的底层依赖Lucene,Lucene可以说是当下最先进、高性能、全功能的搜索引擎库。但是Lucene仅仅只是一个库。为了充分发挥其功能,你需要使用Java并将Lucene直接集成到应用程序中。更糟糕的是,您可能需要获得信息检索学位才能了解其工作原理,因为Lucene非常复杂。
鉴于Lucene如此强大却难以上手的特点,诞生了ES。ES也是使用Java编写的,它的内部使用Lucene做索引与搜索,它的目的是隐藏Lucene的复杂性,取而代之的提供一套简单一致的RESTful API。
ES具有如下特点:
一个分布式的实时文档存储引擎,每个字段都可以被索引与搜索
一个分布式实时分析搜索引擎,支持各种查询和聚合操作
能胜任上百个服务节点的扩展,并可以支持PB级别的结构化或者非结构化数据
为什么不使用 MySQL,Oracle 或者 Hbase,redis ?
关系型数据库有什么问题?
传统的关系数据库提供事务保证,具有不错的性能,高可靠性,安全性高,久经历史考验,而且使用简单,功能强大,同时也积累了大量的成功案例。后来,随着访问量的上升,几乎大部分使用 MySQL 架构的网站在数据库上都开始出现了性能问题,无论是查询还是插入都会变的十分缓慢,web 程序不再仅仅专注在功能上,同时也在追求性能。
当然 MySQL 也可以做成分布式,但是部署以及维护成本较高。Oracle 查询速度是很快的,即使数据量较大,查询速度也不会很慢,但是费用较高。
读写分离
由于数据库的写入压力增加,读写集中在一个数据库上让数据库不堪重负,大部分网站开始使用主从复制技术来达到读写分离,以提高读写性能和读库的可扩展性。Mysql 的 master-slave 模式成为这个时候的网站标配了。
后来开始流行使用分表分库来缓解写压力和数据增长的扩展问题。这个时候,分表分库成了一个热门技术,也是业界讨论的热门技术问题。
MySQL 的扩展性瓶颈
大数据量高并发环境下的 MySQL 应用开发越来越复杂,也越来越具有技术挑战性。分表分库的规则把握都是需要经验的。
虽然有像淘宝这样技术实力强大的公司开发了透明的中间件层来屏蔽开发者的复杂性,但是避免不了整个架构的复杂性。分库分表的子库到一定阶段又面临扩展问题。还有就是需求的变更,可能又需要一种新的分库方式。
关系数据库很强大,但是它并不能很好的应付所有的应用场景。MySQL 的扩展性差(需要复杂的技术来实现),大数据下 IO 压力大,表结构更改困难,正是当前使用 MySQL 的开发人员面临的问题。
Redis 或者 Hbase 有什么问题呢?
对于文档数据库,每个数据库都有其应对的需求。
就 Redis 而言,Redis 更适合做缓存数据库,查询速度非常快,但是它的数据结构是键值对,不能够进行复杂的需求查询,只能给一个 key 然后返回结果。
Hbase 是基于Hadoop 的数据库,它的特点是能够存储海量数据,并且扩展起来简单,因为底层是基于 HDFS 的。对于实时需求任务,以及在线分析就比较困难,不可能把所有数据都加载出来,或者写一个 MapReduce job 来进行任务分析,这样的工程是比较耗费资源的。
为什么要使用ElasticSearch
ES 是分布式的,并且在数据量超大的情况下其查询速度也嗖嗖的快。另外对象中无论是怎样的复杂关系,都可以用 JSON 格式表达出来,可读性较高,ES 就是以 JSON 数据格式存储数据。并且支持在线分析、实时分析。
ES 是基于存储、查询、聚合分析和可视化于一体的解决方案。
什么样的数据适合ES?
目前使用最多的还是日志数据,一般如果程序遇到什么问题都可以通过查询日志分析来定位错误的地方,这种需求肯定是能够过关键字查询,能够在线可视化分析。
那么这个需求就不合适放在传统数据库中,因为日志冗余大,而且涉及很多文本查询,使用传统数据库是非常不方便的,Redis 等文档数据库更不适合。
ES 正好就是全文本检索系统,且是分布式的适合这个需求。另外指标数据也是适合存进去的,指标实时在线监控、报警等,ES 提供了一整套解决方案。
所以说不同的数据库或者全文检索系统都有其专门的应用场景,当涉及到实时,文本检索,数据量大,可视化分析,聚合分析的时候都可以考虑使用 ES 来作为解决方案。
ElasticSearch 能够做什么?
从数据获取,存储计算到可视化,ES 开发了一整套解决方案,Logstash 、Beat 负责数据抓取,ES 负责存储计算,kibana 对数据进行展示分析。另外还有收费的 X-Pack 可以实现安全、告警、监控和 ML 等更丰富的功能。ES 在搜索、日志分析、指标分析和安全分析等领域应用广泛。
总结大概就是从前端到后端到数据分析,从云服务到最流行的机器学习,ES 都提供了一整套解决方案。
ElasticSearch 包括什么?
名词解析
集群(cluster)
集群是一个抽象的概念,由一个或多个节点组成的拓扑网络,并通过集群名称与其他集群进行区分,作为一个整体对外提供服务。
节点(node)
单个 ElasticSearch 实例,即集群当中的一个实例,根据在集群的角色一般分为主节点(管理集群的状态)和数据节点(数据服务)。
索引(index)
在 ES 中, 索引是不同类型的文档及其属性的集合,一般是一组文档的集合,通常我们在使用ES前都会先创建索引,比如时间索引。
分片(shard)
因为 ES 是个分布式的搜索引擎, 所以索引(对应底层Lucene的一个索引)通常都会分解成不同部分,而这些分布在不同节点的数据就是分片。通过多分片来提供分布式处理数据,分片又有主副之分,主分片提供数据写入和搜索,副分用于保障数据高可用以及用于数据搜索。ES 自动管理和组织分片, 并在必要的时候对分片数据进行再平衡分配, 所以用户基本上不用担心分片的处理细节,一个分片默认最大文档数量是 20 亿。
副本(replica)
ES 默认为一个索引创建 5 个主分片, 并分别为其创建一个副本分片.。也就是说每个索引都由 5 个主分片成本, 而每个主分片都相应的有一个 copy。
分片及副本的分配是高可用及快速搜索响应的设计核心。主分片与副本都能处理查询请求, 它们的唯一区别在于只有主分片才能处理索引请求。
段(segment)
每个分片包含多个segment(段),每一个segment都是一个倒排索引。默认的最大 segment 大小是 5GB。在查询的时,会把所有的segment查询结果汇总归并后返回。
注意:
1.segment是不可变的,物理上你并不能从中删除信息,所以在删除文档的时候,是在文档上面打上一个删除的标记,然后在执行段合并的时候,进行删除
2.索引segment段的个数越多,搜索性能越低且消耗内存更多
文档(document)
用户提供的源是一条条记录,它们可以是文本文件、字符串或者数据库表的一条记录等等。一条记录经过索引之后,就是以一个Document的形式存储在索引文件中的。用户进行搜索,也是以Document列表的形式返回。
字段(field)
一个Document可以包含多个信息域,例如一篇文章可以包含“标题”、“正文”、“最后修改时间”等信息域,这些信息域就是通过Field在Document中存储的。
Field有两个属性可选:存储和索引。通过存储属性你可以控制是否对这个Field进行存储;通过索引属性你可以控制是否对该Field进行索引。
如果对标题和正文进行全文搜索,所以我们要把索引属性设置为真,同时我们希望能直接从搜索结果中提取文章标题,所以我们把标题域的存储属性设置为真。
由于正文域太大了,我们为了缩小索引文件大小,将正文域的存储属性设置为假,当需要时再直接读取文件;
我们只是希望能从搜索解果中提取最后修改时间,不需要对它进行搜索,所以我们把最后修改时间域的存储属性设置为真,索引属性设置为假。
上面的三个域涵盖了两个属性的三种组合,还有一种全为假的没有用到,事实上Field不允许你那么设置,因为既不存储又不索引的域是没有意义的。
分词(term)
Term是搜索语法的最小单位,其表现形式为文本中的一个词,复杂的搜索语句会分解成一个Term查询。它表示文档的一个词语,Term由两部分组成:它表示的词语和这个词语所出现的Field。
词条(token)
分词过程中记录一些分词信息的对象。
token由字段文本的term产生,包含term的内容,起始,结束位移和类型字符串。
起始和结束偏移能够通过原来的text,连接起来,用于高亮或者匹配文本段等。
一般来说 Field + Token = Term
MySQL与ElasticSearch的对比
关系数据库 ? 数据库 ? 表 ? 行 ? 列(Columns)
Elasticsearch ? 索引 ? 类型 ? 文档 ? 字段(Fields)
ElasticSearch有什么优势?
1.开箱即用,天生集群
- 横向扩展性:只需要增加一台服务器,做一点配置,启动一下ES进程就可以并入集群。
- 分片机制提供更好的分布性:同一个索引分成多个分片(sharding),分而治之的方式来提供处理效率。
- 高可用:提供复制(replica),一个分片可以设置多个复制分片,使得某台服务器宕机的情况下,集群仍旧可以照常运行;
- 速度快,负载能力强,在面对海量数据时候,搜索速度极快。
PS:
在 es 配置好索引后,集群运行中是无法调整分片配置的。如果要调整分片数量,只能新建索引对数据进重新索引(reindex),该操作很耗时,但是不用停机。
分片时主要考虑数据集的增长趋势,不要做过度分片。每个分片都有额外成本,每个分片本质上就是一个 Lucene 索引,因此会消耗相应的文件句柄, 内存和 CPU 资源。
每个搜索请求会调度到索引的每个分片中,如果分片分散在不同的节点倒是问题不太大,但当分片开始竞争相同的硬件资源时,性能便会逐步下降。
每个搜索请求会遍历这个索引下的所有分片,ES 使用词频统计来计算相关性。当然这些统计也会分配到各个分片上,如果在大量分片上只维护了很少的数据,则将导致最终的文档相关性较差。
ES推荐的最大 JVM 堆空间时 30~32G,所以如果分片最大容量限制为 30G,假如数据量达到 200GB,那么最多分配 7 个分片就足够了。过早的优化是万恶之源,过早的分片也是。
Lucene
Lucene 是apache软件基金会一个开放源代码的全文检索引擎工具包,是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎。
它不是一个完整的搜索应用程序,而是为你的应用程序提供索引和搜索功能。lucene 能够为文本类型的数据建立索引,所以你只要能把你要索引的数据格式转化的文本的,Lucene 就能对你的文档进行索引和搜索。
比如你要对一些 HTML 文档,PDF 文档进行索引的话你就首先需要把 HTML 文档和 PDF 文档转化成文本格式的,然后将转化后的内容交给 Lucene 进行索引,然后把创建好的索引文件保存到磁盘或者内存中,最后根据用户输入的查询条件在索引文件上进行查询。
Lucene特性
- 稳定、索引性能高
1)每小时能够索引150GB以上的数据
2)对内存的要求小,只需要1MB的堆内存
3)增量索引和批量索引一样快
4)索引的大小约为索引文本大小的20%~30%
2.高效、准确、高性能的搜索算法
1)良好的搜索排序
2)强大的查询方式支持:短语查询、通配符查询、临近查询、范围查询等
3)支持字段搜索(如标题、作者、内容)
4)可根据任意字段排序
5)支持多个索引查询结果合并
6)支持更新操作和查询操作同时进行
7)支持高亮、join、分组结果功能
8)速度快
9)可扩展排序模块,内置包含向量空间模型、BM25模型可选
10)可配置存储引擎
3.跨平台
1)纯java编写
2)作为Apache开源许可下的开源项目,你可以在商业或开源项目中使用
3)Lucene有多种语言实现版(如C,C++、Python等),不仅仅是JAVA
索引步骤
获取内容:
Lucene本身没有提供获取内容的工具或者组件,内容是要开发者自己提供相应的程序。这一步包括使用网络爬虫或蜘蛛程序来搜索和界定需要索引的内容。当然,数据来源可能包括数据库、分布式文件系统、本地xml等等。
lucene作为一款核心搜索库,不提供任何功能来实现内容获取。目前有大量的开源爬虫软件可以实现这个功能,例如:Solr,lucene的子项;Nutch,apache项目,包含大规模的爬虫工具,抓取和分辨web站点数据;Grub,比较流行的开源web爬虫工具;Heritrix,一款开源的Internet文档搜索程序;Aperture,支持从web站点、文件系统和邮箱中抓取,并解析和索引其中的文本数据。
建立文档:
获取原始内容后,需要对这些内容进行索引,必须将这些内容转换成部件(文档)。
文档主要包括几个带值的域,比如标题,正文,摘要,作者和链接。如果文档和域比较重要的话,还可以添加权值。
设计完方案后,需要将原始内容中的文本提取出来写入各个文档,这一步可以使用文档过滤器,开源项目如Tika,实现很好的文档过滤。
如果要获取的原始内容存储于数据库中,有一些项目通过无缝链接内容获取步骤和文档建立步骤就能轻易地对数据库表进行航所以操作和搜索操作,例如DBSight,Hibernate Search,LuSQL,Compass和Oracle/Lucene集成项目。
文档分析:
搜索引擎不能直接对文本进行索引,必须将文本分割成一系列被称为语汇单元的独立的原子元素。每一个语汇单元能大致与语言中的“单词”对应起来,这个步骤决定文档中的文本域如何分割成语汇单元系列。lucene提供了大量内嵌的分析器可以轻松控制这步操作。
文档索引:
将文档加入到索引列表中。Lucene在这一步骤中提供了强档的API,只需简单调用提供的几个方法就可以实现出文档索引的建立。为了提供好的用户体验,索引是必须要处理好的一环:在设计和定制索引程序时必须围绕如何提高用户的搜索体验来进行。
搜索组件
搜索组件即为输入搜索短语,然后进行分词,然从索引中查找单词,从而找到包含该单词的文档。搜索质量由查准率和查全率来衡量。搜索组件主要包括以下内容:
建立查询:
建立查询主要是指用户输入所要查询的短语,以普通HTML表单或者ajax的方式提交到后台服务器端。然后把词语传递给后台搜索引擎。这就是一个简单建立查询的过程。
搜索查询:
即为查询检索索引然后返回与查询词语匹配的文档。然后把返回来的结构按照查询请求来排序。搜索查询组件覆盖了搜索引擎中大部分的复杂内容。
展现结果:
所谓展现结果,和第一个搜索界面类似。都是一个与用户交互的前端展示页面,作为一个搜索引擎,用户体验永远是第一位。其中前端展示在用户体现上占据了重要地位。