Lucene和Solr和Elasticsearch的区别

Lucene

是apache下的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,

而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎。

官网地址:https://lucene.apache.org/

Solr

Solr是一个高性能,采用Java5开发,基于Lucene的全文搜索服务器。

同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能进行了优化,并且提供了一个完善的功能管理界

面,是一款非常优秀的全文搜索引擎。官网地址:http://lucene.apache.org/solr/

Elasticsearch

Elasticsearch跟Solr一样,也是一个基于Lucene的搜索服务器,它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。

官网地址:https://www.elastic.co/products/elasticsearch

 

Elasticsearch的优缺点:

优点:

1.Elasticsearch是分布式的。不需要其他组件,分发是实时的,被叫做"Push replication"。

2.Elasticsearch 完全支持 Apache Lucene 的接近实时的搜索。

3.处理多租户(multitenancy)不需要特殊配置,而Solr则需要更多的高级设置。

4.Elasticsearch 采用 Gateway 的概念,使得完备份更加简单。

5.各节点组成对等的网络结构,某些节点出现故障时会自动分配其他节点代替其进行工作。

缺点:

1.只有一名开发者(当前Elasticsearch GitHub组织已经不只如此,已经有了相当活跃的维护者)

2.还不够自动(不适合当前新的Index Warmup API)

 

Solr的优缺点:

优点

1.Solr有一个更大、更成熟的用户、开发和贡献者社区。

2.支持添加多种格式的索引,如:HTML、PDF、微软 Office 系列软件格式以及 JSON、XML、CSV 等纯文本格式。

3.Solr比较成熟、稳定。

4.不考虑建索引的同时进行搜索,速度更快。

缺点

1.建立索引时,搜索效率下降,实时索引搜索效率不高。

 

Elasticsearch 与 Solr 的比较:

1.二者安装都很简单;

2.Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能;

3.Solr 支持更多格式的数据,而 Elasticsearch 仅支持json文件格式;

4.Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供;

5.Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用时效率明显低于 Elasticsearch。

6.Solr 是传统搜索应用的有力解决方案,但 Elasticsearch 更适用于新兴的实时搜索应用。

 

elasticsearch 索引数据多了怎么办,如何调优,部署。

使用bulk API

初次索引的时候,把 replica 设置为 0

增大 threadpool.index.queue_size

增大 indices.memory.indexbuffersize

增大 index.translog.flushthresholdops

增大 index.translog.sync_interval

增大 index.engine.robin.refresh_interval

https://www.jianshu.com/p/5eeeeb4375d4

 

es 写数据过程

  1. 客户端选择一个 node 发送请求过去,这个 node 就是 coordinating node(协调节点)。
  2. coordinating node 对 document 进行路由,将请求转发给对应的 node(有 primary shard)。
  3. 实际的 node 上的 primary shard 处理请求,然后将数据同步到 replica node。
  4. coordinating node 如果发现 primary node 和所有 replica node 都搞定之后,就返回响应结果给客户端。

 

es数据库压缩率 es压缩查看器官网_搜索

 

 

es 读数据过程

可以通过 doc id 来查询,会根据 doc id 进行 hash,判断出来当时把 doc id 分配到了哪个 shard 上面去,从那个 shard 去查询。

  1. 客户端发送请求到任意一个 node,成为 coordinate node。
  2. coordinate node 对 doc id 进行哈希路由,将请求转发到对应的 node,此时会使用 round-robin随机轮询算法,在 primary shard 以及其所有 replica 中随机选择一个,让读请求负载均衡。
  3. 接收请求的 node 返回 document 给 coordinate node。
  4. coordinate node 返回 document 给客户端。

 

es 搜索数据过程

es 最强大的是做全文检索,就是比如你有三条数据:

java真好玩儿啊
java好难学啊
j2ee特别牛

你根据 java 关键词来搜索,将包含 java的 document 给搜索出来。es 就会给你返回:java真好玩儿啊,java好难学啊。

客户端发送请求到一个 coordinate node。

协调节点将搜索请求转发到所有的 shard 对应的 primary shard 或 replica shard,都可以。

query phase:每个 shard 将自己的搜索结果(其实就是一些 doc id)返回给协调节点,由协调节点进行数据的合并、排序、分页等操作,产出最终结果。

fetch phase:接着由协调节点根据 doc id 去各个节点上拉取实际的 document 数据,最终返回给客户端。

写请求是写入 primary shard,然后同步给所有的 replica shard;读请求可以从 primary shard 或 replica shard 读取,采用的是随机轮询算法。

 

写数据底层原理

es数据库压缩率 es压缩查看器官网_Elastic_02

先写入内存 buffer,在 buffer 里的时候数据是搜索不到的;同时将数据写入 translog 日志文件。

如果 buffer 快满了,或者到一定时间,就会将内存 buffer 数据 refresh 到一个新的 segment file 中,

但是此时数据不是直接进入 segment file 磁盘文件,而是先进入 os cache 。这个过程就是 refresh。

 

每隔 1 秒钟,es 将 buffer 中的数据写入一个新的 segment file,每秒钟会产生一个新的磁盘文件 segment file,这个 segment file 中就存储最近 1 秒内 buffer 中写入的数据。

但是如果 buffer 里面此时没有数据,那当然不会执行 refresh 操作,如果 buffer 里面有数据,默认 1 秒钟执行一次 refresh 操作,刷入一个新的 segment file 中。

 

操作系统里面,磁盘文件其实都有一个东西,叫做 os cache,即操作系统缓存,就是说数据写入磁盘文件之前,会先进入 os cache,先进入操作系统级别的一个内存缓存中去。只要 buffer中的数据被 refresh 操作刷入 os

cache中,这个数据就可以被搜索到了。

为什么叫 es 是准实时的? NRT,全称 near real-time。默认是每隔 1 秒 refresh 一次的,所以 es 是准实时的,因为写入的数据 1 秒之后才能被看到。可以通过 es 的 restful api 或者 java api,手动执行一次 refresh 操作,就是手动将 buffer 中的数据刷入 os cache中,让数据立马就可以被搜索到。只要数据被输入 os cache 中,buffer 就会被清空了,因为不需要保留 buffer 了,数据在 translog 里面已经持久化到磁盘去一份了。

 

重复上面的步骤,新的数据不断进入 buffer 和 translog,不断将 buffer 数据写入一个又一个新的 segment file 中去,每次 refresh 完 buffer 清空,translog 保留。随着这个过程推进,translog 会变得越来越大。当 translog 达到一定长度的时候,就会触发 commit 操作。

 

commit 操作发生第一步,就是将 buffer 中现有数据 refresh 到 os cache 中去,清空 buffer。然后,将一个 commit point写入磁盘文件,里面标识着这个 commit point 对应的所有 segment file,同时强行将 os cache 中目前所有的数据都 fsync 到磁盘文件中去。最后清空 现有 translog 日志文件,重启一个 translog,此时 commit 操作完成。

 

这个 commit 操作叫做 flush。默认 30 分钟自动执行一次 flush,但如果 translog 过大,也会触发 flush。flush 操作就对应着 commit 的全过程,我们可以通过 es api,手动执行 flush 操作,手动将 os cache 中的数据 fsync 强刷到磁盘上去。

translog 日志文件的作用是什么?你执行 commit 操作之前,数据要么是停留在 buffer 中,要么是停留在 os cache 中,无论是 buffer 还是 os cache 都是内存,一旦这台机器死了,内存中的数据就全丢了。所以需要将数据对应的操作写入一个专门的日志文件 translog 中,一旦此时机器宕机,再次重启的时候,es 会自动读取 translog 日志文件中的数据,恢复到内存 buffer 和 os cache 中去。

 

translog 其实也是先写入 os cache 的,默认每隔 5 秒刷一次到磁盘中去,所以默认情况下,可能有 5 秒的数据会仅仅停留在 buffer 或者 translog 文件的 os cache 中,如果此时机器挂了,会丢失 5 秒钟的数据。但是这样性能比较好,最多丢 5 秒的数据。也可以将 translog 设置成每次写操作必须是直接 fsync 到磁盘,但是性能会差很多。

实际上你在这里,如果面试官没有问你 es 丢数据的问题,你可以在这里给面试官炫一把,你说,其实 es 第一是准实时的,数据写入 1 秒后可以搜索到;可能会丢失数据的。有 5 秒的数据,停留在 buffer、translog os cache、segment file os cache 中,而不在磁盘上,此时如果宕机,会导致 5 秒的数据丢失。

 

总结一下,数据先写入内存 buffer,然后每隔 1s,将数据 refresh 到 os cache,到了 os cache 数据就能被搜索到(所以我们才说 es 从写入到能被搜索到,中间有 1s 的延迟)。每隔 5s,将数据写入 translog 文件(这样如果机器宕机,内存数据全没,最多会有 5s 的数据丢失),translog 大到一定程度,或者默认每隔 30mins,会触发 commit 操作,将缓冲区的数据都 flush 到 segment file 磁盘文件中。

数据写入 segment file 之后,同时就建立好了倒排索引。

 

删除/更新数据底层原理

如果是删除操作,commit 的时候会生成一个 .del 文件,里面将某个 doc 标识为 deleted 状态,那么搜索的时候根据 .del 文件就知道这个 doc 是否被删除了。

如果是更新操作,就是将原来的 doc 标识为 deleted 状态,然后新写入一条数据。

buffer 每 refresh 一次,就会产生一个 segment file,所以默认情况下是 1 秒钟一个 segment file,这样下来 segment file 会越来越多,此时会定期执行 merge。

每次 merge 的时候,会将多个 segment file 合并成一个,同时这里会将标识为 deleted 的 doc 给物理删除掉,然后将新的 segment file 写入磁盘,

这里会写一个 commit point,标识所有新的 segment file,然后打开 segment file 供搜索使用,同时删除旧的 segment file。

 

底层 lucene

简单来说,lucene 就是一个 jar 包,里面包含了封装好的各种建立倒排索引的算法代码。

我们用 Java 开发的时候,引入 lucene jar,然后基于 lucene 的 api 去开发就可以了。

通过 lucene,我们可以将已有的数据建立索引,lucene 会在本地磁盘上面,给我们组织索引的数据结构。

 

如何检查Elasticsearch服务器是否正在运行?

通常,ElasticSearch使用9200-9300的端口范围。因此,要检查它是否在您的服务器上运行,只需键入主页的URL,然后输入端口号。

例如:mysitename.com:9200

 

列出Elasticsearch的不同类型的查询?

这些查询分为两种类型,在它们下面有多个查询分类:

基于全文检索:匹配查询、匹配词组查询、多匹配查询、匹配词组前缀查询、常用词查询、查询字符串查询、简单查询字符串查询。

基于词条检索:词条查询、词条集查询、范围查询、前缀查询、通配符查询、regexp查询、模糊查询、存在查询、类型查询、id查询

 

基于词条的查询和全文的查询有什么区别?

基于词条的查询:词条查询或模糊查询等查询是没有分析阶段的低级查询。词条查询术语Foo在倒排索引中搜索确切的词条并计算IDF / TF相关性分数对于每个有词条的文档。

全文查询:匹配查询或查询字符串查询等查询是了解字段映射的高级查询。只要查询汇总了完整的项目列表,它就会为每个项执行适当的低级查询,最后结合他们的结果来产生每个文档的相关性分数。