Bootstrap

elasticsearch全接触-面试宝典-知识大全

1. 简述什么是Elasticsearch?

Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎。它能很方便的使大量数据具有搜索、分析和探索的能力。充分利用Elasticsearch的水平伸缩性,能使数据在生产环境变得更有价值。Elasticsearch 的实现原理主要分为以下几个步骤,首先用户将数据提交到Elasticsearch 数据库中,再通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据,当用户搜索数据时候,再根据权重将结果排名,打分,再将返回结果呈现给用户。

Elasticsearch是与名为Logstash的数据收集和日志解析引擎以及名为Kibana的分析和可视化平台一起开发的。这三个产品被设计成一个集成解决方案,称为“Elastic Stack”(以前称为“ELK stack”)。

Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。”Elasticsearch是分布式的,这意味着索引可以被分成分片,每个分片可以有0个或多个副本。每个节点托管一个或多个分片,并充当协调器将操作委托给正确的分片。再平衡和路由是自动完成的。“相关数据通常存储在同一个索引中,该索引由一个或多个主分片和零个或多个复制分片组成。一旦创建了索引,就不能更改主分片的数量。

Elasticsearch使用Lucene,并试图通过JSON和Java API提供其所有特性。它支持facetting和percolating,如果新文档与注册查询匹配,这对于通知非常有用。另一个特性称为“网关”,处理索引的长期持久性;例如,在服务器崩溃的情况下,可以从网关恢复索引。Elasticsearch支持实时GET请求,适合作为NoSQL数据存储,但缺少分布式事务。

2. 简述ElasticSearch对比Solr ?

ElasticSearch对比Solr 性能对比
1、单纯对已有数据搜索,solr快很多
2、当实时建立索引,solr会产生I/O阻塞,性能大打折扣
3、随着数据量增大,solr明显不行,而es没有多大变化

ElasticSearch对比Solr 另外还有如下区别:

1、es基本是开箱即用,非常简单。Solr安装略微复杂一丢丢
2、Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能
3、Solr 支持更多格式的数据,比如JSON、XML、CSV,而 Elasticsearch 仅支持json文件格式
4、Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供,例如图形化界面需要kibana友好支撑
5、Solr 查询快,但更新索引时慢(即插入删除慢),用于电商等查询多的应用
6、ES建立索引快(即查询慢),即实时性查询快,用于facebook新浪等搜索
7、Solr 是传统搜索应用的有力解决方案,但 Elasticsearch 更适用于新兴的实时搜索应用
8、Solr比较成熟,有一个更大,更成熟的用户、开发和贡献者社区,而 Elasticsearch相对开发维护者较少,更新太快,学习使用成本较高

3. Elasticsearch 什么是正向索引?什么是倒排索引?

正向索引:基于文档id创建索引。查询词条时必须先找到文档,而后判断是否包含词条
倒排索引:对文档内容分词,对词条创建索引,并记录词条所在文档的信息。查询时先根据词条查询到文档id,而后获取到文档,倒排索引是为了解决非结构化数据的检索问题而产生的

4. 简述ElasticSearch的数据模型核心概念?

(1)索引(index) 是一组具有共同特性的文档集合,类似数据库的表(table)
(2)文档(Document),就是一条条的数据,类似数据库中的行(Row)
(3)字段(Field),就是JSON文档中的字段,类似数据库中的列
(4)在ES中存储记录的单位是JSON“文档”,而JSON“文档”中的“字段”也就是组成JSON的一个个KV对。
(5)Mapping(映射)是索引中文档的约束,例如字段类型约束。类似数据库的表结构(Schema)

5. 详细描述 Elasticsearch 搜索的过程?

搜索的过程简述:

1、搜索被执行成一个两阶段过程,我们称之为 Query Then Fetch;
2、在初始查询阶段时,查询会广播到索引中每一个分片拷贝(主分片或者副本分片)。 每个分片在本地执行搜索并构建一个匹配文档的大小为 from + size 的优先队列。
PS:在搜索的时候是会查询 Filesystem Cache 的,但是有部分数据还在 MemoryBuffer,所以搜索是近实时的。
3、每个分片返回各自优先队列中 所有文档的 ID 和排序值 给协调节点,它合并这些值到自己的优先队列中来产生一个全局排序后的结果列表。
4、接下来就是 取回阶段,协调节点辨别出哪些文档需要被取回并向相关的分片提交多个 GET 请求。每个分片加载并 丰富 文档,如果有需要的话,接着返回文档给协调节点。一旦所有的文档都被取回了,协调节点返回结果给客户端。
5、补充:Query Then Fetch 的搜索类型在文档相关性打分的时候参考的是本分片的数据,这样在文档数量较少的时候可能不够准确,DFS Query Then Fetch 增加了一个预查询的处理,询问 Term 和 Document frequency,这个评分更准确,
但是性能会变差。*

6. Elasticsearch 是如何实现Master选举的 ?

前置条件:
1)只有是候选主节点(master:true)的节点才能成为主节点。
2)最小主节点数(min_master_nodes)的目的是防止脑裂。

Elasticsearch 的选主是 ZenDiscovery 模块负责的,主要包含 Ping(节点之间通过这个RPC来发现彼此)和 Unicast(单播模块包含一个主机列表以控制哪些节点需要 ping 通)这两部分;
获取主节点的核心入口为 findMaster,选择主节点成功返回对应 Master,否则返回 null。

选举流程大致描述如下:
第一步:确认候选主节点数达标,elasticsearch.yml 设置的值 discovery.zen.minimum_master_nodes;
第二步:对所有候选主节点根据nodeId字典排序,每次选举每个节点都把自己所知道节点排一次序,然后选出第一个(第0位)节点,暂且认为它是master节点。
第三步:如果对某个节点的投票数达到一定的值(候选主节点数n/2+1)并且该节点自己也选举自己,那这个节点就是master。否则重新选举一直到满足上述条件。

补充:
这里的 id 为 string 类型。
master 节点的职责主要包括集群、节点和索引的管理,不负责文档级别的管理;data 节点可以关闭 http 功能

7. 详细描述Elasticsearch索引⽂档的过程?

Elasticsearch索引文档的过程可以分为以下几个步骤:

客户端向Elasticsearch节点发送索引请求,请求包含了要索引的文档数据和所属的索引名称。
Elasticsearch接收到请求后,会解析索引请求,然后根据文档数据生成倒排索引(Inverted Index)和文档存储(Document Store)。
倒排索引是Elasticsearch中最核心的数据结构之一,它由一组有序的词项(Term)列表组成,每个词项对应着一组文档ID,表示包含该词项的文档集合。
文档存储是指Elasticsearch将原始文档和一些元数据保存在磁盘上,以便之后进行查询和检索。文档存储会对每个文档进行分析(Analyze),并将分析后的词条(Term)存储在倒排索引中。
倒排索引和文档存储分别被分成多个分片(Shard),每个分片都是独立的、可被复制的数据集合。每个分片都被分配到不同的节点上,从而实现数据的分布式存储和查询。
当文档被索引后,Elasticsearch会通过复制和分片机制将文档的副本存储在多个节点上,从而实现数据的高可用和容错性。
索引请求成功完成后,Elasticsearch会向客户端返回响应,包含了文档的索引信息、分片信息和其他元数据等。
在Elasticsearch中,索引请求的处理涉及到多个组件和技术,包括Lucene倒排索引、文档分析器、分片机制、复制机制和集群管理等。因此,对于大规模数据的索引和查询,需要根据实际业务场景进行性能优化和调整,以提高系统的性能和稳定性

8. ES中match和term差别对比,text和keyword区别、bool查询?

match在匹配时会对所查找的关键词进行分词,然后按分词匹配查找,而term会直接对关键词进行查找。一般模糊查找的时候,多用match,而精确查找时可以使用term
text支持模糊查询,且会进行分词操作。keyword不支持模糊查询,且不支持分词操作。

bool查询中
1、must (must字段对应的是个列表,也就是说可以有多个并列的查询条件,一个文档满足各个子条件后才最终返回)
2、should (只要符合其中一个条件就返回)
3、must_not (与must相反,也就是说可以有多个并列的查询条件,一个文档各个子条件后才最终的结果都不满足)
4、filter(条件过滤查询,过滤条件的范围用range表示gt表示大于、lt表示小于、gte表示大于等于、lte表示小于等于)

9. 阐述Elasticsearch如何确保数据一致性 ?

ElasticSearch是建立在全文搜索引擎 Apache Lucene™ 基础上的分布式,高性能、高可用、可伸缩的实时搜索和分析引擎,可支持扩展到上百台服务器,处理PB级别的结构化或非结构化数据。ElasticSerarch通过分片与副本机制来保障集群的高性能、高可靠。ElasticSearch如何保证副本之间数据一致性呢?

数据一致性需满足哪些特性呢?

持久性:数据写入成功后,数据持久化存在,不会发送回滚或丢失情况。
一致性:数据写入成功后,查询时要保证读取到最新版本的数据,不能读取到旧数据。
原子性:一个写入或者更新操作,要么成功,要么失败,不允许出现中间状态。
隔离性:多个写入并发操作而互不影响。
ElasticSearch集群数据同步机制

Elasticsearch采用一主多副复制方式,没有采用节点级别的主从复制,而是基于分片。

Index由多个Shard组成,每个Shard有一个主节点和多个副本节点。数据写入的时候,首先根据_routing规则对路由参数(路由参数默认使用_id,Index Request中可以设置使用哪个Filed的值作为路由参数)进行Hash确定要写入的Shard,最后从集群的Meta中找出该Shard的Primary节点写入数据,Primary Shard成功写入数据后,Primary Shard将请求同时发送给多个Replica Shard(InSyncAllocationIds),请求在全部Replica Shard上执行成功并响应Primary Shard后,Primary Shard返回结果给客户端。

该模式,Primary要等所有Replica返回才能返回给客户端,那么延迟就会受到最慢的Replica的影响,写入操作的延时就等于latency = Latency(Primary Write) + Max(Replicas Write)。副本的存在,降低了写入效率会较低,但是可以避免单机或磁盘故障导致数据丢失。

Replica写入失败,Primary会执行一些重试逻辑,尽可能保障Replica中写入成功。如果一个Replica最终写入失败,Primary会将Replica节点报告给Master,然后Master更新Meta中Index的InSyncAllocations配置,将Replica从中移除,移除后它就不再承担读请求。在Meta更新到各个Node之前,用户可能还会读到这个Replica的数据,但是更新了Meta之后就不会了。所以这个方案并不是非常的严格,考虑到ES本身就是一个近实时系统,数据写入后需要refresh才可见,所以一般情况下,在短期内读到旧数据应该也是可接受的。

设置wait_for_active_shards参数(可在Index的setting、请求中设置)可保证Es集群数据一致性更高的可能性。该参数设置每次写入shard至少具有的active副本数,如果副本数小于参数值,此时不允许写入。

ElasticSearch节点数据写入机制:

由于Lucene的索引读写的隔离性,需要在添文档后对IndexWriter进行commit,在搜索的时候IndexReader需要重新的打开,这样才能保证查询结果的实时性,然而当硬盘上的索引非常大的时候,IndexWriter的commit操作和IndexReader的open操作都是非常慢的,根本达不到实时性的需要。ElasticSearch是如何解决可见效问题呢?

如上图所示,请求到达DataNode后,首先经过Lucene引擎生成document存入到indexing buffer区中,然后通过refresh操作(默认情况下,es集群中的每个shard会每隔1秒自动refresh一次,这是es是近实时的搜索引擎而不是实时的原因)将indexing buffer区中新增Document在filesystem cache中生成segment,这个sengment就可以打开和查询,从而确保在可见性,refresh操作是非常轻量级的,相对耗时较少,之后经过一定的间隔或外部触发后segment才会被flush到磁盘上,这个操作非常耗时。flush操作完成后会清空掉旧的TransLog。

为了避免segement从内存flush到磁盘这段时间节点crash掉,导致数据丢失,数据经过lucene引擎处理后会写入TransLog,当节点重启后会根据TransLog恢复数据到Checkpoint。通过设置TransLog的Flush频率可以控制可靠性,要么是按请求,每次请求都Flush;要么是按时间,每隔一段时间Flush一次。一般为了性能考虑,会设置为每隔5秒或者1分钟Flush一次,Flush间隔时间越长,可靠性就会越低。对于GetById查询,可以直接从TransLog中获取数据,这时候就成了RT(Real Time)实时系统。

数据一致性保障

持久性:通过Replica和TransLog两种机制来共同保障。
一致性:数据写入成功后,需完成refresh操作之后才可读,由于无法保证Primary和Replica可同时refresh,所以会出现查询不稳定的情况,这里只能实现最终一致性。
原子性:Add和Delete直接调用Lucene的接口,进行原子操作。update操作通过Delete-Then-Add完成,在Delete操作之前会加Refresh Lock,禁止Refresh操作,等Add操作完成后释放Refresh Lock后才能被Refresh,这样就保证了Delete-Then-Add的原子性。
隔离性:采用Version和局部锁来保证更新的是特定版本的数据。
要保证数据写入到ElasticSerach是安全的,高可靠的,需要如下的配置:

设置wait_for_active_shards参数大于等于2。
设置TransLog的Flush策略为每个请求都要Flush

10. ElasticSearch vs Lucene的关系 ?

lasticSearch vs Lucene的关系,简单一句话就是,成品与半成品的关系。

(1)Lucene专注于搜索底层的建设,而ElasticSearch专注于企业应用。
(2)Luncene是单节点的API,ElasticSearch是分布式的—为集群而生。
(3)Luncene需要二次开发,才能使用。不能像百度或谷歌一样,它只是提供一个接口需要被实现才能使用, ElasticSearch直接拿来用。

3.2 ElasticSearch与Solr对比
Solr与elasticsearch是当前两大最流行的搜索应用服务器,他们的底层都是基于lucene。

Elasticsearch是分布式的,不需要其他组件,Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带 有分布式协调管理功能

Elasticsearch设计用于云计算中,处理多租户不需要特殊配置,而Solr则需要更多的高级设置。

当单纯的对已有数据进行搜索时,Solr更快,实时建立索引时, Solr会产生io阻塞,查询性能较差, Elasticsearch 具有明显的优势,随着数据量的增加,Solr的搜索效率会变得更低,而Elasticsearch却没有明显的变化

11. 简述Elasticsearch中文分词 ?

Elasticsearch中文分词我们采用Ik分词,ik有两种分词模式:ik_max_word和ik_smart模式;

ik_max_word 和 ik_smart 什么区别?

ik_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民, 中华,华人,人民共和国,人民,人,民,共和国,共和,和国,国歌”,会穷尽各种可能的组合;

ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民,共和国,国歌”。 索引时,为了提供索引的覆盖范围,通常会采用ik_max_word分析器,会以最细粒度分词索引,搜索时为了提高搜索准确度,会采用ik_smart分析器,会以粗粒度分词

我们可以使用网上的一些工具查看分词的效果,比如Analyzer在线工具,IK Analyzer—在线分词器工具

12. Elasticsearch 中的节点(比如共 20 个),其中的 10 个选了一个 master,另外 10 个选了另一个 master,怎么办?

当集群 master 候选数量不小于 3 个时,可以通过设置最少投票通过数量(discovery.zen.minimum_master_nodes)超过所有候选节点一半以上来解决脑裂问题;
当候选数量为两个时,只能修改为唯一的一个 master 候选,其他作为 data节点,避免脑裂问题。

13. Elasticsearch 客户端在和集群连接时,如何选择特定的节点执行请求的?

client 远程连接连接一个 elasticsearch 集群。它并不加入到集群中,只是获得一个或者多个初始化的地址,并以轮询的方式与这些地址进行通信。

14. 详细描述Elasticsearch 更新和删除文档的过程?

1 删除和更新也都是写操作,但是 Elasticsearch 中的文档是不可变的,因此不能被删除或者改动以展示其变更;(根本原因是底层lucene的segment段文件不可更新删除)
2 磁盘上的每个段都有一个相应的 .del 文件。当删除请求发送后,文档并没有真 的被删除,而是在 .del 文件中被标记为删除。该文档依然能匹配查询,但是会在 结果中被过滤掉。当段合并时,在.del 文件中被标记为删除的文档将不会被写入 新段。
3 在新的文档被创建时,Elasticsearch 会为该文档指定一个版本号,当执行更新 时,旧版本的文档在.del 文件中被标记为删除,新版本的文档被索引到一个新段。

15. Elasticsearch 对于大数据量(上亿量级)的聚合如何实现?

Elasticsearch 提供的首个近似聚合是cardinality 度量。它提供一个字段的基数,即该字段的distinct或者unique值的数目。它是基于HLL算法的。HLL 会先对我们的输入作哈希运算,然后根据哈希运算的结果中的 bits 做概率估算从而得到基数。其特点是:可配置的精度,用来控制内存的使用(更精确 = 更多内存);小的数据集精度是非常高的;我们可以通过配置参数,来设置去重需要的固定内存使用量。无论数千还是数十亿的唯一值,内存使用量只与你配置的精确度相关。

科普&拓展:

HyperLogLog:
下面简称为HLL,它是 LogLog 算法的升级版,作用是能够提供不精确的去重计数。存在以下的特点:

  1. 能够使用极少的内存来统计巨量的数据,在 Redis 中实现的 HyperLogLog,只需要12K内存就能统计2^64个数据。
  2. 计数存在一定的误差,误差率整体较低。标准误差为 0.81% 。
  3. 误差可以被设置辅助计算因子进行降低。

应用场景:

  1. 基数不大,数据量不大就用不上,会有点大材小用浪费空间
  2. 有局限性,就是只能统计基数数量,而没办法去知道具体的内容是什么
  3. 和bitmap相比,属于两种特定统计情况,简单来说,HyperLogLog 去重比 bitmap 方便很多
  4. 一般可以bitmap和hyperloglog配合使用,bitmap标识哪些用户活跃,hyperloglog计数

应用场景:

  1. 基数不大,数据量不大就用不上,会有点大材小用浪费空间
  2. 有局限性,就是只能统计基数数量,而没办法去知道具体的内容是什么
  3. 和bitmap相比,属于两种特定统计情况,简单来说,HyperLogLog 去重比 bitmap 方便很多
  4. 一般可以bitmap和hyperloglog配合使用,bitmap标识哪些用户活跃,hyperloglog计数

16. 简述Elasticsearch 数据类型?

1、ES常用数据类型
1.1 Numbers 数字类型
涉及到的类型很多,具体查阅文档 常用的有long,integer,short,double,float
1.2 Keywords 关键字类型
关键字分为以下几种:
(1)、keyword 用于索引结构化内容,如ID、电子邮件地址、主机名、状态码、邮政编码或标签。
说明:默认情况下text类型不会创建正排索引,而聚合查询要求查询的相关字段必须建立了正排索引,所以当text类型需要进行聚合查询时需要指定keyword类型,其常用于排序、过滤、聚合. 当然可以用fielddata临时给text创建正排索引,但是这种方式创建的正排索引位于jvm的堆内存中,不是已磁盘文件的形式落地.而且text类型默认会被分词,聚合会按照分词结果进行聚合.所以要慎用.
这里还要注意一点是,一般情况下不需要对text类型创建正排索引,因为内容过长,也不利于索引.
注:数据Id应该使用keyword而不是int或者string等类型,因为keyword会创建正排索引
(2)、constant_keyword 对于始终包含相同值的关键字字段。
(3)、wildcard 用于非结构化机器生成的内容。通配符类型针对具有大值或高基数的字段进行了优化。
1.3 Dates 日期类型
日期类型分为以下几种:
(1)、date 日期类型
自动识别机制如下几种
i、Json字符串格式为“2015-01-01”或“2015/01/01 12:10:30”,会被识别为date类型
ii、时间戳
其余注意事项请参考官网
(2)、date_nanos 纳秒类型
如果毫秒的精度不够,可以使用纳秒类型.
1.4 alias 索引别名类型
1.5 binary 二进制类型
二进制类型接受二进制值作为Base64编码字符串。默认情况下,该字段不存储且不可搜索:
2、ES结构化数据类型
2.1、Range 范围类型
范围字段类型表示上限和下限之间的连续值范围。例如,一个范围可以表示10月份的任何日期,也可以表示0到9之间的任何整数。它们使用运算符gt或gte定义下限,使用运算符lt或lte定义上限。它们可以用于查询,并且对聚合的支持有限。唯一支持的聚合是直方图和基数。
其余几种范围类型,请参考官方文档
3、ES文本搜索类型
3.1、text fields 文本类型 常用于文本搜索,但是不能创建正排索引
索引全文值的字段,例如电子邮件正文或产品描述。对这些字段进行分析,即在索引之前,通过分析器将字符串转换为单个术语的列表。分析过程允许Elasticsearch在每个全文字段中搜索单个单词。文本字段不用于排序,很少用于聚合(尽管重要的文本聚合是一个显著的例外)。文本字段最适合非结构化但可读的内容。如果需要索引非结构化机器生成的内容,请参阅映射非结构化内容。
如果您需要索引结构化内容,如电子邮件地址、主机名、状态代码或标记,则可能更应该使用关键字字段。
文本类型分为两种:
(1)、text
全文内容(如电子邮件正文或产品描述)的传统字段类型。
说明:当字段被设置成文本类型后,字段会被分析(经过过滤器和分词器操作),会被分词,在生成倒排索引前,字段会被分词,分成一个个词项,一般无法用作排序和聚合操作.(text无法创建正排索引(用于排序和聚合),因为创建正排索引,会消耗大量的堆空间,尤其是加载高基数字段(经过去重之后,仍然有大量的重复的数据)时),字段一旦被加载到堆中,会在生命周期内保持在那里,同样加载数据也是非常的消耗资源,会产生延迟. es默认不会给test创建正排索引
(2)、match_only_text
一种空间优化的文本变体,禁用评分,在需要位置的查询上执行速度较慢。它最适合索引日志消息。
其余关于文本类型的介绍,参考官方文档.
其余关于搜索的类型参看官方说明.
4、ES对象关系类型 Objects and relational types
4.1 object 对象类型
一般用于嵌套类型,如User和UserType的嵌套关系,前提是两者都是独立的结构.JSON文档本质上是分层的:文档可能包含内部对象,而内部对象本身也可能包含内部对象
4.2 nested 对象数组类型
一般用于报存对象数组类型,嵌套类型是对象数据类型的专门版本,允许以相互独立的方式对对象数组进行索引。
4.3 flattened
默认情况下,对象中的每个子字段分别映射和索引。如果子字段的名称或类型事先未知,则会动态映射它们。flattened 将整个对象映射为单个字段。给定一个对象,展平映射将解析出其叶值,并将其索引到一个字段中作为关键字。然后可以通过简单的查询和聚合来搜索对象的内容。但是也有限制,如只允许基本查询,不支持数值范围查询或高亮显示,具体参阅文档.
4.4 join 关联关系类型
连接数据类型是一个特殊字段,用于在相同索引的文档中创建父/子关系。关系部分定义了文档中一组可能的关系,每个关系都是父名称和子名称。
具体查看官方文档
5、ES特殊数据类型
5.1 geo_point、geo_shape、point、shape 4大类型 常用于地理位置搜索具体查看官方文档.
5.2 completion 配合Completion Suggester使用
自动完成建议类型,类似于百度搜索框输入一段文字后,会出现一个建议的下拉框内容,该类型就是实现这个功能用的.
完成提示器提供键入时自动完成/搜索功能。这是一种导航功能,用于在用户键入时引导用户找到相关结果,从而提高搜索精度。它不是为了拼写纠正,或者你指的是像术语或短语提示器这样的功能。理想情况下,自动完成功能应该与用户键入的速度一样快,以提供与用户已键入内容相关的即时反馈。因此,完成建议器针对速度进行了优化。该建议器使用能够快速查找的数据结构,但构建成本高,并且存储在内存中。

17. 简述Elasticsearch 的底层存储原理?

refresh :数据先写入内存 buffer,然后每隔一段时间,默认 1s,将数据refresh 到一个新的 段 中,
但是此时数据不是直接进入 磁盘文件,而是先进入 文件系统缓存 。这个过程就是 refresh 。

到了 文件系统缓存,数据就能被搜索到 (所以我们才说 es 是近实时搜索的,因为从写入到能被搜索到,中间有 1s 的延迟)。
每隔 5s,将数据写入 translog 文件 (这样如果机器宕机,内存数据全没,最多会有 5s 的数据丢失)
flush:当 translog 大到一定程度(默认512MB),或者默认每隔 30mins,会出发一次 flush 操作。
内存中的数据被refresh到一个新的 段 并 被写入到 文件系统缓存 中。
然后,将一个 提交点写入磁盘文件,里面标识着这个提交点对应的所有 段 ;
同时,文件系统缓存 中所有的数据通过 fsync 刷新到磁盘中。
最后清空 现有 translog 日志文件并创建一个新的 translog。

补充

索引文档以 段 的形式存储在磁盘上,何为段? 索引文件被拆分为多个子文件,则每个子文件叫作段,
每一个段本身都是一个倒排索引 ,并且段具有不变性,一旦索引的数据被写入硬盘,就不可再修改。在底层采用了分段的存储模式,使它在读写时几乎完全避免了锁的出现,大大提升了读写性能。
段被写入到磁盘后会生成一个提交点,提交点是一个用来记录所有提交后段信息的文件。一个段一旦拥有了提交点,就说明这个段只有读的权限,失去了写的权限。相反,当段在内存buffer中时,就只有写的权限,而不具备读数据的权限,意味着不能被检索。(在文件系统缓存中的段是可以被检索的)。
在refresh 阶段:可以通过 es 的 restful api 或者 java api ,手动执行一次 refresh 操作,就是手动将buffer 中的数据刷入 文件系统缓存 中,让数据立马就可以被搜索到。只要数据被输入 文件系统缓存 中,buffer 就会被清空了,因为不需要保留 buffer 了,数据在 translog 里面已经持久化到磁盘去一份了

18. Elasticsearch 读取数据(文档)的过程?

客户端发送请求到任意一个 节点,成为 协调节点 。 协调节点对文档ID 进行路由计算,确定文档 属于哪个分片 ,然后选择该分片的主分片或任一副本分片。
然后将请求转发到 选择的分片所在的节点。 具体选择主分片 还是 哪个副本分片,一般是使用 round-robin 随机轮询算法,在主分片以及其所有副本分片 中随机选择一个, 让读请求负载均衡。
3… 节点 处理请求并 返回 文档 给 协调节点 。 协调节点 再将文档 返回 给客户端。

19. Elasticsearch 删除、更改文档的过程?

删除和更新也都是写操作,但是 Elasticsearch 中的文档是不可变的,因此不能被删除或者改动以展示 其变更;

删除:

磁盘上的每个段都有一个相应的.del 文件。当删除请求发送后,文档并没有真的被删除,而是在.del 文件中被标记为删除。该文档依然能匹配查询,但是会在结果中被过滤掉。
当段合并时,在.del文件中被标记为删除的文档将不会被写入新段,这时才是真正的删除。(逻辑删除)
更新:

在新的文档被创建时,Elasticsearch 会为该文档指定一个版本号,当执行更新时,旧版本的文档在 .del 文件中被标记为删除,新版本的文档被索引到一个新段。旧版本的文档依然能匹配查询,但是会在结果中被过滤掉。(更新 = 删除旧的,创建新的)
写操作后主分片和副本分片的 一致:

当主分片把更改转发到副本分片时, 它不会转发更新请求。 相反,它转发完整文档的新版本。
这些更改将会异步转发到副本分片,并且不能保证它们以发送它们相同的顺序到达。
如果 Elasticsearch 仅 转发更改请求,则可能以错误的顺序应用更改,导致得到损坏的文档。

20. 简述Elasticsearch出现脑裂的原因?如何解决?

脑裂 的成因:
网络问题:集群间的网络延迟导致一些节点访问不到master,认为master挂掉了从而选举出新的master,并对master上的分片和副本标红,分配新的主分片。
节点负载:主节点的角色既为master又为data,访问量较大时可能会导致**ES停止响应(假死状态)**造成大面积延迟,此时其他节点得不到主节点的响应认为主节点挂掉了,会重新选取主节点。
内存回收:主节点的角色既为master又为data,当data节点上的ES进程占用的内存较大,引发JVM的大规模内存回收,造成ES进程失去响应。

脑裂问题 解决:
适当调大响应时间,减少误判:
通过参数 discovery.zen.ping_timeout设置节点状态的响应时间,默认为3s,可以适当调大,如果master在该响应时间的范围内没有做出响应应答,判断该节点已经挂掉了。调大参数(如6s, discovery.zen.ping_timeout:6),可适当减少误判。
增加参与选举的候选节点数:

选举触发我们需要在候选集群中的节点的配置文件中设置参数 discovery.zen.munimum_master_nodes的值,这个参数表示在选举主节点时需要参与选举的候选主节点的节点数,默认值是1,官方建议取值(master_eligibel_nodes/2)+1,即略大于候选节点数一半,其中master_eligibel_nodes为候选主节点的个数。
这样做既能防止脑裂现象的发生,也能最大限度地提升集群的高可用性,因为只要不少于discovery.zen.munimum_master_nodes个候选节点存活,选举工作就能正常进行。当小于这个值的时候,无法触发选举行为,集群无法使用,不会造成分片混乱的情况。(可用节点数太少,集群不工作,可防止出现分片混乱)
角色分离:

即是上面我们提到的 候选主节点和数据节点进行角色分离,这样可以减轻主节点的负担,防止主节点的假死状态发生,减少对主节点“已死”的误判。

21. 如何监控ElasticSearch的集群状态?

elasticsearch-head 插件
通过 Kibana 监控 Elasticsearch。你可以实时查看你的集群健康状态和性能,也可以分析过去的集群、索引和节点指标

22. ElasticSearch JVM 调优?调整哪些参数?

堆大小:

确保堆内存最小值( Xms )与最大值( Xmx )的大小是相同的,防止程序在运行时改变堆内存大小。
Elasticsearch默认安装后设置的堆内存是 1 GB。可通过…/config/jvm.option 文件进行配置,但是最好不要超过物理内存的50% 和 超过32GB。(建议 31G)
GC:

GC 默认采用CMS的方式,并发但是有STW的问题,可以考虑使用G1收集器。
文件系统缓存:

ES非常依赖文件系统缓存(Filesystem Cache),快速搜索。一般来说,应该至少确保物理上有一半的可用内存分配到文件系统缓存。

23. 简述ElasticSearch 分片数量?副本数量的设定 ?

分片和副本的设计为 ES 提供了支持分布式和故障转移的特性,但并不意味着分片和 副本是可以无限分配的。
索引的分片完成分配后由于索引的路由机制,我们是不能重新 修改分片数的。ES 默认分片数是1。 考虑一下 node数量,一般一个节点有时候就是一台物理机,如果分片数过多,大大超过了节点数, 很可能会导致一个节点上存在多个分片,一旦该节点故障,即使保持了 1 个以上的副本,同样有可能 会导致数据丢失,集群无法恢复。所以, 一般都设置分片数不超过节点数的 3 倍。
主分片,副本和节点最大数之间数量,我们分配的时候可以参考以下关系: 节点数<=主分片数*(副本数+1)

24. 简述Elasticsearch拼写纠错实现原理 ?

拼写纠错就是搜索引擎可以智能的感知用户输入关键字的错误,并使用纠正过的关键字进行搜索展示给用户;拼写纠错是一种改善用户体验的功能;
elasticsearch提供了以下不同类型的suggester来完成拼写纠错和自动完成功能;
term suggester主要针对单个的term分词进行纠正的场景;
phrase suggester主要针对整个短语的拼写纠正场景;
completion suggester主要提供一种快速高效的自动提示功能;

二、Term Suggester基于单个词的拼写纠错
Term Suggester会将用户输入的text进行解析分解成单个的word,然后针对每个word进行纠错;
elasticsearch的suggester请求的还是_search端点,要发送一个Term suggester请求,我们需要

1.在body中添加suggest字段;
2.指定我们的suggest的名字,我们可以使用不同的名字同时进行多个拼写纠错, 其最终的执行结果在response中也会使用这个名字进行区分;
3.通过text字段指定要纠正的文本;
4.指定要使用的suggester类型,这里使用term;
5.指定要在哪个字段上进行拼写纠错;

25. Elasticsearch在部署时,对Linux的设置有哪些优化方法?

1、64 GB 内存的机器是非常理想的, 但是32 GB 和16 GB 机器也是很常见的。少于8 GB 会适得其反。
2、如果你要在更快的CPUs 和更多的核心之间选择,选择更多的核心更好。多个内核提供的额外并发远胜过稍微快一点点的时钟频率。
3、如果你负担得起SSD,它将远远超出任何旋转介质。基于SSD 的节点,查询和索引性能都有提升。如果你负担得起,SSD 是一个好的选择。
4、即使数据中心们近在咫尺,也要避免集群跨越多个数据中心。绝对要避免集群跨越大的地理距离。
5、请确保运行你应用程序的JVM 和服务器的JVM 是完全一样的。在Elasticsearch 的几个地方, 使用Java 的本地序列化。
6、通过设置gateway.recover_after_nodes、gateway.expected_nodes、gateway.recover_after_time 可以在集群重启的时候避免过多的分片交换, 这可能会让数据恢复从数个小时缩短为几秒钟。
7、Elasticsearch 默认被配置为使用单播发现,以防止节点无意中加入集群。只有在同一台机器上运行的节点才会自动组成集群。最好使用单播代替组播。
8、不要随意修改垃圾回收器( CMS)和各个线程池的大小。
9、把你的内存的(少于)一半给Lucene(但不要超过32 GB!) ,通过ES_HEAP_SIZE 环境变量设置。
10、内存交换到磁盘对服务器性能来说是致命的。如果内存交换到磁盘上, 一个100 微秒的操作可能变成10 毫秒。再想想那么多10 微秒的操作时延累加起来。不难看出swapping 对于性能是多么可怕。
11、Lucene 使用了大量的文件。同时, Elasticsearch 在节点和HTTP 客户端之间进行通信也使用了大量的套接字。所有这一切都需要足够的文件描述符。你应该增加你的文件描述符,设置一个很大的值,如64,000。
补充:索引阶段性能提升方法
1、使用批量请求并调整其大小: 每次批量数据5– 15 MB 大是个不错的起始点。
2、存储:使用SSD
3、段和合并:Elasticsearch 默认值是20 MB/s,对机械磁盘应该是个不错的设置。如果你用的是SSD,可以考虑提高到100– 200 MB/s。如果你在做批量导入,完全不在意搜索,你可以彻底关掉合并限流。另外还可以增加index.translog.flush_threshold_size 设置,从默认的512 MB 到更大一些的值, 比如1 GB,这可以在一次清空触发的时候在事务日志里积累出更大的段。
4、如果你的搜索结果不需要近实时的准确度, 考虑把每个索引的index.refresh_interval 改到30s。
5、如果你在做大批量导入,考虑通过设置index.number_of_replicas: 0 关闭副本。

26. REST API在 Elasticsearch 方面有哪些优势?

REST API是使用超文本传输协议的系统之间的通信,该协议以 XML 和 JSON格式传输数据请求。
REST 协议是无状态的,并且与带有服务器和存储数据的用户界面分开,从而增强了用户界面与任何类型平台的可移植性。它还提高了可伸缩性,允许独立实现组件,因此应用程序变得更加灵活。
REST API与平台和语言无关,只是用于数据交换的语言是XML或JSON。
借助:REST API 查看集群信息或者排查问题都非常方便。

27. 安装 Elasticsearch 需要依赖什么组件吗?

ES 早期版本需要JDK,在7.X版本后已经集成了 JDK,已无需第三方依赖。

28. 如何启动 Elasticsearch 服务器?

动方式有很多种,一般 bin 路径下

./elasticsearch -d
1.
就可以后台启动。

打开浏览器输入 http://ES IP:9200 就能知道集群是否启动成功。
如果启动报错,日志里会有详细信息,逐条核对解决就可以。

29. 简单阐述Elasticsearch Cluster?

Elasticsearch 集群是一组连接在一起的一个或多个 Elasticsearch 节点实例。
Elasticsearch 集群的功能在于在集群中的所有节点之间分配任务,进行搜索和建立索引

30. 简述什么是Elasticsearch Node?

节点是 Elasticsearch 的实例。实际业务中,我们会说:ES集群包含3个节点、7个节点。

这里节点实际就是:一个独立的 Elasticsearch 进程,一般将一个节点部署到一台独立的服务器或者虚拟机、容器中。

不同节点根据角色不同,可以划分为:

主节点
帮助配置和管理在整个集群中添加和删除节点。

数据节点
存储数据并执行诸如CRUD(创建/读取/更新/删除)操作,对数据进行搜索和聚合的操作。

客户端节点(或者说:协调节点) 将集群请求转发到主节点,将与数据相关的请求转发到数据节点
摄取节点
用于在索引之前对文档进行预处理。

31. Elasticsearch 与关系型数据库对比?

在Elasticsearch中,文档归属于一种 类型(type) ,而这些类型存在于 索引(index)中,类比传统关系型数据库:
Relational DB --> Databases --> Tables --> Rows --> Columns
关系型数据库 数据库 表 行 列
Elasticsearch --> Indices --> Types --> Documents --> Fields
Elasticsearch 索引 类型 文档 域(字段)

RelationalDB(关系型数据库) Elasticsearch(搜索引擎)
Database->Index
Table ->Type
Row->Document
Column->Field
Schema->Papping
Index->Everything isindexed
SQL->DSL

32. 能否在 Elasticsearch 中定义映射?

映射(Mapping)是定义文档及其包含的字段如何存储和索引的过程。 每个文档都是字段的集合,每个字段都有自己的数据类型。为数据创建一个映射定义,包含与文档相关的字段列表。

动态映射(Dynamic mapping)
当Elasticsearch在文档中检测到新字段时,会动态将该字段添加到映射中称为动态映射。

动态字段映射:根据数据类型规则应用于动态添加的字段。支持的数据类型包括:boolean、double、integer、object、array、date。
dynamic:开启动态映射的模式
date_detection:开启日期检测
dynamic_date_formats:检测的日期格式
numeric_detection: true:开启数值检测
动态模板:又称自定义映射,根据匹配条件应用于动态添加的字段。
match_mapping_type: Elasticsearch检测到的数据类型进行操作
match and unmatch: 使用模式来匹配字段名称
path_match and path_unmatch: 使用字段的路径来匹配
显式映射(Explicit mapping)
显式映射以完全控制字段的存储和索引方式。

显式映射的意义:

区分全文本字符串字段和精确值字符串字段
执行特定语言的文本分析
优化字段进行部分匹配
自定义日期格式
无法自动检测到的数据类型,如地理信息
字段数据类型(Field data types)
常见的类型:

binary:二进制编码为Base64字符串
boolean:布尔值
Keywords:关键字,通常用于过滤、排序和聚合。包括keyword、constant_keyword和wildcard。
Numbers:数值类型,包括long、integer、short、byte、double、float
Dates:日期类型,包括date和date_nanos
alias:为现有字段定义别名
对象和关系类型:

object:JSON对象。扁平的键-值对列表
flattened:将整个JSON对象作为单个字段值
nested:保留其子字段之间关系的JSON对象,维护每个对象的独立性
join:为同一索引中的文档定义父/子关系
结构化数据类型:

Range:范围,包括long_range, double_range, date_range, and ip_range
ip:IPv4和IPv6地址
version:软件版本。特殊的关键字,用于处理软件版本值并支持它们的专用优先级规则
murmur3:计算和存储值的散列。提供了在索引时计算字段值的哈希并将其存储在索引中的功能
聚合数据类型:

aggregate_metric_double:度量值进行聚合
histogram:柱状图,以直方图形式聚合数值
文本搜索类型:

text:非结构化文本。配置分词器
annotated_text:注解文本。带有映射器注释的文本插件提供了索引文本的功能。如WWW与World Wide Web同义
completion:补全提示。是一个导航功能,引导用户在输入时查看相关结果,提高搜索精度
search_as_you_type:自定义搜索。类似文本的字段,经过优化提供开箱即用的按需输入搜索服务。如搜索框
token_count:符号计数。分词分析后对数量进行索引
文档排名类型:

rank_feature:记录一个数字特性,以便在查询中增强文档。
空间数据类型:

geo_point:经纬度
geo_shape:复杂的形状,如多边形
元数据:

_index:文档所属的索引
_id:文档ID
_doc_count:桶聚合(Bucket)返回字段,显示桶中已聚合和分区的文档数
_source:原始JSON文档
_size:_source字段的大小
_routing:自定义路由
_meta:元数据信息
映射参数(Mapping parameters)
analyzer:text字段文本解析器
boots:增强匹配权重,默认1.0。如:title的匹配权重大于content匹配权重
coerce:强行类型转换,默认true。如:如string(“10”)强制转换为integer(10)
copy_to:将多个字段的值复制到同一字段中。如:first_name和last_name,复制到full_name
doc_values:开启字段的排序、聚合和脚本中访问字段,支持除了text和annotated_text的所有字段类型,默认true。本质上是列式存储,保持与原始文档字段相同的值,关闭可节省空间
dynamic:新检测到的字段添加到映射,默认true。false表示不建立索引,strict表示拒绝文档
eager_global_ordinals:全局序号映射。文档中字段的值仅存储序号,而不存原始内容,用于聚合时提高性能
enabled:尝试为字段建立索引,仅可应用于顶级映射和object类型下,默认true。如果禁用整个映射,意味着可以对其进行获取,但是不会以任何方式对它的内容建立索引
format:自定义日期格式
ignore_above:超过长度的字符串内容将不会被索引
ignore_malformed:忽略错误的数据类型插入到索引中。默认抛出异常并丢弃文档
index:控制是否对字段值建立索引,默认true。未索引的字段不可查询
index_options:控制哪些信息添加到倒排索引已进行搜索并突出显示,仅使用于文本字段
index_phrases:将两个词的组合词索引到一个单独的字段中。默认false
index_prefixes:为字段值的前缀编制索引,以加快前缀搜索速度
meta:附加到字段的元数据
fields:为不同的目的以不同的方式对同一字段建立索引
norms:用于计算查询的文档分数,默认true。对于仅用于过滤或聚合的字段,不需要对字段进行打分排序时设置为false
null_value:使用指定的值替换为null值,以便可以进行索引和搜索
position_increment_gap:当为具有多个值的文本字段建立索引时,将在值之间添加“假”间隙,以防止大多数短语查询在值之间进行匹配,默认值为100
properties:类型映射,object字段和nested字段包含子字段叫properties
search_analyzer:查询时使用指定的分析器
similarity:字段打分的相似性算法,默认BM25
store:单独存储属性值。默认对字段值进行索引以使其可搜索,但不单独存储它们,但是已存储在_source字段中
term_vector:存储分析过程的词矢量(Term vectors)信息。包括:词、位置、偏移量、有效载荷
映射限制设置(mapping limit settings)
索引中定义太多字段会导致映射爆炸,从而导致内存不足错误和难以恢复的情况。在动态映射中,如果每个新插入的文档都引入新字段,每个新字段都添加到索引映射中,随着映射的增长,这会成为一个问题。使用映射限制设置可以限制(手动或动态创建的)字段映射的数量,并防止文档引起映射爆炸。

index.mapping.total_fields.limit: 字段最大数限制,默认1000
index.mapping.depth.limit: 字段的最大深度,默认20
index.mapping.nested_fields.limit: 单个索引中嵌套类型(nested)最大数限制,默认50
index.mapping.nested_objects.limit: 单个文档中嵌套JSON对象的最大数限制,默认10000

33. 简述Elasticsearch的文档是什么?

文档是存储在 Elasticsearch 中的 JSON 文档。它等效于关系数据库表中的一行记录。

34. Elasticsearch 中列出集群的所有索引的语法是什么?

GET _cat/indices

35. 在Elasticsearch中 按 ID检索文档的语法是什么?

GET test_001/_doc/1

36. 解释 Elasticsearch 中的相关性和得分?

当你在互联网上搜索有关 Apple 的信息时。它可以显示有关水果或苹果公司名称的搜索结果。

你可能要在线购买水果,检查水果中的食谱或食用水果,苹果对健康的好处。
你也可能要检查Apple.com,以查找该公司提供的最新产品范围,检查评估公司的股价以及最近6个月,1或5年内该公司在纳斯达克的表现。
同样,当我们从 Elasticsearch 中搜索文档(记录)时,你会对获取所需的相关信息感兴趣。基于相关性,通过Lucene评分算法计算获得相关信息的概率。

ES 会将相关的内容都返回给你,只是:计算得出的评分高的排在前面,评分低的排在后面。
计算评分相关的两个核心因素是:词频和逆向文档频率(文档的稀缺性)。
大体可以解释为:单篇文档词频越高、得分越高;多篇文档某词越稀缺,得分越高。

37. Elasticsearch 中执行搜索的各种可能方式有哪些?

核心方式如下:

方式一:基于 DSL 检索(最常用) Elasticsearch提供基于JSON的完整查询DSL来定义查询。

GET /shirts/_search
{
“query”: {
“bool”: {
“filter”: [
{ “term”: { “color”: “red” }},
{ “term”: { “brand”: “gucci” }}
]
}
}
}

方式二:基于 URL 检索

GET /my_index/_search?q=user:seina
1.
方式三:类SQL 检索

登录后复制
POST /_sql?format=txt
{
“query”: “SELECT * FROM uint-2020-08-17 ORDER BY itemid DESC LIMIT 5”
}

38. Elasticsearch 支持哪些类型的查询?

查询主要分为两种类型:精确匹配、全文检索匹配。

精确匹配,例如 term、exists、term set、 range、prefix、 ids、 wildcard、regexp、 fuzzy等。
全文检索,例如match、match_phrase、multi_match、match_phrase_prefix、query_string 等

39. ElasticSearch 精准匹配检索和全文检索匹配检索的不同?

两者的本质区别:

精确匹配用于:是否完全一致?
举例:邮编、身份证号的匹配往往是精准匹配。

全文检索用于:是否相关?
举例:类似B站搜索特定关键词如“马保国 视频”往往是模糊匹配,相关的都返回就可以。

40. 解释一下 Elasticsearch 中聚合?

聚合有助于从搜索中使用的查询中收集数据,聚合为各种统计指标,便于统计信息或做其他分析。聚合可帮助回答以下问题:

我的网站平均加载时间是多少?
根据交易量,谁是我最有价值的客户?
什么会被视为我网络上的大文件?
每个产品类别中有多少个产品?
聚合的分三类:

主要查看7.10 的官方文档,早期是4个分类,别大意啊!

分桶 Bucket 聚合
根据字段值,范围或其他条件将文档分组为桶(也称为箱)。

指标 Metric 聚合
从字段值计算指标(例如总和或平均值)的指标聚合。

管道 Pipeline 聚合
子聚合,从其他聚合(而不是文档或字段)获取输入

41. Elasticsearch 中的数据存储流程简述 ?

Elasticsearch是一个搜索引擎,输入写入ES的过程就是索引化的过程,数据按照既定的 Mapping 序列化为Json 文档实现存储

42. 请列出 Elasticsearch 各种类型的分析器 ?

Elasticsearch Analyzer 的类型为内置分析器和自定义分析器。

Standard Analyzer
标准分析器是默认分词器,如果未指定,则使用该分词器。
它基于Unicode文本分割算法,适用于大多数语言。
Whitespace Analyzer
基于空格字符切词。
Stop Analyzer
在simple Analyzer的基础上,移除停用词。
Keyword Analyzer
不切词,将输入的整个串一起返回。

自定义分词器的模板

自定义分词器的在Mapping的Setting部分设置:

PUT my_custom_index
{
“settings”:{
“analysis”:{
“char_filter”:{},
“tokenizer”:{},
“filter”:{},
“analyzer”:{}
}
}
}

脑海中还是上面的三部分组成的图示。其中:

“char_filter”:{},——对应字符过滤部分;
“tokenizer”:{},——对应文本切分为分词部分;
“filter”:{},——对应分词后再过滤部分;
“analyzer”:{}——对应分词器组成部分,其中会包含:1. 2. 3。

43. 简述如何使用 Elasticsearch Tokenizer?

Tokenizer 接收字符流(如果包含了字符过滤,则接收过滤后的字符流;否则,接收原始字符流),将其分词。同时记录分词后的顺序或位置(position),以及开始值(start_offset)和偏移值(end_offset-start_offset)。

44. 简述Token filter 过滤器 在 Elasticsearch 中如何工作?

针对 tokenizers 处理后的字符流进行再加工,比如:转小写、删除(删除停用词)、新增(添加同义词)等。

45. Master 节点和 候选 Master节点有什么区别?

ingest 节点可以看作是数据前置处理转换的节点,支持 pipeline管道 设置,可以使用 ingest 对数据进行过滤、转换等操作,类似于 logstash 中 filter 的作用,功能相当强大

46. 简述Elasticsearch中的属性 enabled, index 和 store 的功能?

enabled:false,启用的设置仅可应用于顶级映射定义和 Object 对象字段,导致 Elasticsearch 完全跳过对字段内容的解析。
仍然可以从_source字段中检索JSON,但是无法搜索或以其他任何方式存储JSON。

如果对非全局或者 Object 类型,设置 enable : false 会报错如下:

“type”: “mapper_parsing_exception”,
“reason”: “Mapping definition for [user_id] has unsupported parameters: [enabled : false]”

index:false, 索引选项控制是否对字段值建立索引。它接受true或false,默认为true。未索引的字段不可查询。
如果非要检索,报错如下:

“type”: “search_phase_execution_exception”,
“reason”: “Cannot search on field [user_id] since it is not indexed.”

store:
某些特殊场景下,如果你只想检索单个字段或几个字段的值,而不是整个_source的值,则可以使用源过滤来实现;

47. Elasticsearch Analyzer 中的字符过滤器如何利用?

字符过滤器将原始文本作为字符流接收,并可以通过添加,删除或更改字符来转换字符流。

字符过滤分类如下:

HTML Strip Character Filter.
用途:删除HTML元素,如,并解码HTML实体,如&amp 。

Mapping Character Filter
用途:替换指定的字符。

Pattern Replace Character Filter
用途:基于正则表达式替换指定的字符

48. 解释有关 Elasticsearch的 NRT?

从文档索引(写入)到可搜索到之间的延迟默认一秒钟,因此Elasticsearch是近实时(NRT)搜索平台。
也就是说:文档写入,最快一秒钟被索引到,不能再快了。
写入调优的时候,我们通常会动态调整:refresh_interval = 30s 或者更达值,以使得写入数据更晚一点时间被搜索到。

49. Elasticsearch 支持哪些配置管理工具?

Ansible
Chef
Puppet
Salt Stack 是 DevOps 团队使用的 Elasticsearch支持的配置工具。

50. 解释一下X-Pack for Elasticsearch的功能?

X-Pack 是与Elasticsearch一起安装的扩展程序。

X-Pack的各种功能包括安全性(基于角色的访问,特权/权限,角色和用户安全性),监视,报告,警报等。

51. 简述Elasticsearch中 cat API的功能?

cat API 命令提供了Elasticsearch 集群的分析、概述和运行状况,其中包括与别名,分配,索引,节点属性等有关的信息。

这些 cat 命令使用查询字符串作为其参数,并以J SON 文档格式返回结果信息

52. 描述Elasticsearch 中常用的 cat命令有哪些?

GET _cat/aliases?v
分配相关
GET _cat/allocation
计数
GET _cat/count?v
字段数据
GET _cat/fielddata?v
运行状况
GET_cat/health?
索引相关
GET _cat/indices?v
主节点相关
GET _cat/master?v
节点属性
GET _cat/nodeattrs?v
节点
GET _cat/nodes?v
待处理任务
GET _cat/pending_tasks?v
插件
GET _cat/plugins?v
恢复
GET _cat / recovery?v
存储库
GET _cat /repositories?v

GET _cat /segments?v
分片
GET _cat/shards?v
快照
GET _cat/snapshots?v
任务
GET _cat/tasks?v
模板
GET _cat/templates?v
线程池
GET _cat/thread_pool?v

53. 详细说明ELK Stack ?

ELK 不是一款软件,而是 Elasticsearch、Logstash 和 Kibana 三种软件产品的首字母缩写。这三者都是开源软件,通常配合使用,而且又先后归于 Elastic.co 公司名下,所以被简称为 ELK Stack。根据 Google Trend 的信息显示,ELK Stack 已经成为目前最流行的集中式日志解决方案。

Elasticsearch:分布式搜索和分析引擎,具有高可伸缩、高可靠和易管理等特点。基于 Apache Lucene 构建,能对大容量的数据进行接近实时的存储、搜索和分析操作。通常被用作某些应用的基础搜索引擎,使其具有复杂的搜索功能;
Logstash:数据收集引擎。它支持动态的从各种数据源搜集数据,并对数据进行过滤、分析、丰富、统一格式等操作,然后存储到用户指定的位置;
Kibana:数据分析和可视化平台。通常与 Elasticsearch 配合使用,对其中数据进行搜索、分析和以统计图表的方式展示;
Filebeat:ELK 协议栈的新成员,一个轻量级开源日志文件数据搜集器,基于 Logstash-Forwarder 源代码开发,是对它的替代。在需要采集日志数据的 server 上安装 Filebeat,并指定日志目录或日志文件后,Filebeat 就能读取数据,迅速发送到 Logstash 进行解析,亦或直接发送到 Elasticsearch 进行集中式存储和分析。

54. Kibana在Elasticsearch的哪些地方以及如何使用?

Kibana 是通向 Elastic 产品集的窗口。 它可以在 Elasticsearch 中对数据进行视觉探索和实时分析。 Kibana是一个针对Elasticsearch的开源分析及可视化平台,用来搜索,查看,用来交互存储在Elasticsearch索引中的数据。使用Kibana,可以通过各种图表进行高级数据分析及展示。

55. Logstash 如何与 Elasticsearch 结合使用?

logstash 是ELK Stack附带的开源 ETL 服务器端引擎,该引擎可以收集和处理来自各种来源的数据。

最典型应用包含:同步日志、邮件数据,同步关系型数据库(Mysql、Oracle)数据,同步非关系型数据库(MongoDB)数据,同步实时数据流 Kafka数据、同步高性能缓存 Redis 数据等。

56. Beats 如何与 Elasticsearch 结合使用?

Beats是一种开源工具,可以将数据直接传输到 Elasticsearch 或通过 logstash,在使用Kibana进行查看之前,可以对数据进行处理或过滤。

传输的数据类型包含:审核数据,日志文件,云数据,网络流量和窗口事件日志等。

57. 简述什么是Elasticsearch 数据预热?

对于经常访问的数据,可以做一个缓存预热的系统,提前访问,通过后台自动搜索刷到缓存中,提升用户访问性能

58. 对于GC方面,在使用Elasticsearch时要注意什么?

1、倒排词典的索引需要常驻内存,无法GC,需要监控data node 上segmentmemory 增长趋势。

2、各类缓存, field cache, filter cache, indexing cache, bulk queue 等等,要设置合理的大小,并且要应该根据最坏的情况来看heap 是否够用,也就是各类缓存全部占满的时候,还有heap 空间可以分配给其他任务吗?避免采用clear cache等“ 自欺欺人”的方式来释放内存。

3、避免返回大量结果集的搜索与聚合。确实需要大量拉取数据的场景,可以采用scan & scroll api 来实现。

4、cluster stats 驻留内存并无法水平扩展,超大规模集群可以考虑分拆成多个集群通过tribe node 连接。

5、想知道heap 够不够,必须结合实际应用场景,并对集群的heap 使用情况做持续的监控。

59. 阐述什么是ElasticSearch 字典树?

字典树,又称为 Trie树或者前缀树,是一种用于快速检索字符串的树型数据结构。它的基本思想是将所有的字符串按照字符顺序建立一个树形结构,使得具有相同前缀的字符串共享相同的前缀节点。在字典树中,每个节点代表一个字符串的前缀,从根节点开始,到每个节点的路径上所代表的字符串,都是该节点所代表字符串的前缀。
字典树的优点是可以快速的查找字符串,时间复杂度为 O(k),其中 k为字符串的长度。另外,字典树还可以用于解决字符串相关的问题,例如查找最长公共前缀、查找所有以某个字符串为前缀的字符串等。
字典树的缺点是它的空间消耗较大,因为它需要为每个节点保存一个指向子节点的指针。此外,如果要在大量字符串中查找某些字符串,需要将所有字符串都插入到字典树中,这个过程可能会很慢。

60. 请举例ELK日志分析相关的应用场景?

ELK日志分析框架可以应用于以下业务场景:

  1. 网站和应用程序的性能监控:ELK可以收集和分析应用程序和网站的日志,以帮助开发人员更好地了解系统的性能,并及时发现和解决性能问题。

  2. 安全和审计:ELK可以收集和分析系统的安全日志,以帮助系统管理员及时发现和解决安全问题,并进行审计。

  3. 故障排除:ELK可以收集和分析系统的日志,以帮助系统管理员及时发现和解决故障问题。

  4. 数据分析:ELK可以收集和分析系统的日志,以帮助企业更好地了解客户行为,改善产品和服务,并做出更好的决策。

61. 简述ElasticSearch 冷热架构?

为了保证Elasticsearch的读写性能,官方建议磁盘使用SSD固态硬盘。然而Elasticsearch要解决的是海量数据的存储和检索问题,海量的数据就意味需要大量的存储空间,如果都使用SSD固态硬盘成本将成为一个很大的问题,这也是制约许多企业和个人使用Elasticsearch的因素之一。为了解决这个问题,Elasticsearch冷热分离架构应运而生。

冷热架构是一项十分强大的功能,能够让您将 Elasticsearch 部署划分为“热”数据节点和“冷”数据节点。

热数据节点处理所有新输入的数据,并且存储速度也较快,以便确保快速地采集和检索数据。
冷节点的存储密度则较大,如需在较长保留期限内保留日志数据,不失为一种具有成本效益的方法。
将这两种类型的数据节点结合到一起后,您便能够有效地处理输入数据,并将其用于查询,同时还能在节省成本的前提下在较长时间内保留数据。此架构对日志用例来说尤其大有帮助,因为在日志用例中,人们的大部分精力都会专注于近期的日志(例如最近两周),而较早的日志(由于合规性或者其他原因仍需要保留)则可以接受较慢的查询时间。

1.2 典型应用场景
一句话:在成本有限的前提下,让客户关注的实时数据和历史数据硬件隔离,最大化解决客户反应的响应时间慢的问题。业务场景描述:
每日增量6TB日志数据,高峰时段写入及查询频率都较高,集群压力较大,查询ES时,常出现查询缓慢问题。

ES集群的索引写入及查询速度主要依赖于磁盘的IO速度,冷热数据分离的关键为使用SSD磁盘存储热数据,提升查询效率。
若全部使用SSD,成本过高,且存放冷数据较为浪费,因而使用普通SATA磁盘与SSD磁盘混搭,可做到资源充分利用,性能大幅提升的目标。

62. 简述Docker中安装Elasticsearch?

先拉取镜像
docker pull docker.elastic.co/elasticsearch/elasticsearch:6.7.1
然后创建容器 (这是一条长的命令!!!)
docker run -e ES_JAVA_OPTS=“-Xms256m -Xmx256m” -d -p 9200:9200 -p 9300:9300 -e “discovery.type=single-node” 技术分享图片docker.elastic.co/elasticsearch/elasticsearch:6.7.1

63. 简述Elasticsearch(ES)配置及优化措施 ?

在Elasticsearch中,索引的大小和存储能力取决于多个因素,包括文档大小、索引的分片数、硬件规格、查询负载和其他因素。

索引和分片配置:索引和分片的数量和配置会对查询并发性能产生影响。如果索引和分片的数量太少,可能会导致查询性能不佳,而如果数量过多,可能会增加网络和节点之间的通信开销。因此,需要根据实际的查询负载和数据量进行合理的索引和分片规划。

硬件资源:硬件资源,如CPU、内存、磁盘I/O等也会影响查询并发性能。更高的CPU核心数和更大的内存可以帮助提高查询并发性能,而更快的磁盘I/O速度可以帮助提高查询响应速度。

查询负载:查询负载的复杂度和大小也会影响查询并发性能。如果查询包含大量聚合操作或复杂的脚本字段,可能会导致查询响应时间变慢,并且限制了并发查询的数量。

网络和通信:Elasticsearch集群中的网络和通信开销也会对查询并发性能产生影响。如果网络延迟或带宽限制较大,可能会导致查询响应时间变慢,并降低并发查询的数量。

调优和优化:对Elasticsearch进行调优和优化可以帮助提高查询并发性能。例如,使用合适的查询类型和查询参数、优化索引和分片配置、配置合适的缓存和连接池等等。

优化
分布式架构:对于大规模数据存储和高并发查询的场景,通常采用分布式架构,将数据分散到多个节点上,以便能够扩展和平衡查询负载。Elasticsearch可以使用多个节点组成集群,每个节点存储一部分数据,并且负责处理查询请求,这样可以实现数据的水平扩展和查询负载的负载均衡。

分片和副本:在Elasticsearch中,可以将一个索引分成多个分片,每个分片可以存储一部分数据,以便能够并行处理查询请求。同时,可以使用副本来提高查询性能和容错性,当主分片不可用时,副本可以接管查询请求。因此,可以将索引分成多个分片,并创建多个副本,以便能够处理高并发查询。

硬件配置:对于大规模数据存储和高并发查询的场景,需要使用高性能的硬件资源来支撑查询负载。例如,使用16核CPU和64GB内存的服务器可以提供更高的处理能力和内存容量,以便能够支持更多的查询并发和更大的数据量。

查询优化:可以通过查询优化来提高查询性能。例如,可以使用合适的查询类型和查询参数来减少查询的响应时间,或者使用缓存和连接池等技术来缓存查询结果和减少网络通信开销。

网络和通信:由于Elasticsearch是分布式系统,查询需要在不同的节点之间进行通信,因此需要确保网络和节点通信的稳定性和高效性。可以使用负载均衡器和DNS轮询等技术来分布查询负载,并使用高速网络连接来提高通信速度和可靠性。

需要注意的是,以上是一些常规的优化和配置建议,具体的优化和配置策略还需要根据实际的硬件和查询负载等因素进行测试和优化。因此,建议进行基准测试来确定最佳的配置和优化策略,以获得最佳的查询性能和响应时间。

场景
在平均文档大小约为1-2KB的情况下,一台拥有32GB内存的机器可以在一个具有50个字段的Elasticsearch索引中存储数十亿个文档,假设查询不太复杂,且索引和搜索流量不太大,可以进行2000个并发查询,QPS能达到上万。

分片数量越多,索引可以存储的数据量就越大,因为数据可以更好地分布在不同的分片之间,从而提高了查询性能和可伸缩性。然而,分片数量也会增加Elasticsearch集群的复杂性和维护成本,因此需要进行谨慎的规划和测试。

一般来说,每个分片的推荐大小应该在20GB以下,这意味着在一个有100个分片的索引中,总存储量可能最多达到数TB。但是这只是一个粗略的估计,具体取决于实际的硬件和查询负载等多个因素,因此建议进行负载测试和基准测试,以确定最佳的分片和硬件配置。

需要注意的是,实际可存储的数据量和可处理的查询并发性取决于各种因素,因此最好进行负载测试和基准测试,以确定特定用例的最佳配置。

分片导致的统计误差
在 Elasticsearch 中,分片的数量是一个非常重要的参数,它可以决定索引数据的分布和查询的并发能力。在一些情况下,分片的数量会对分片统计数量产生影响,使其不准确。

具体来说,当一个索引中的数据量比较小,并且分片数量比较多时,分片统计数量可能会不准确。这是因为 Elasticsearch 统计分片数量是通过查询每个分片的文档数并相加得到的,如果分片数量太多,每个分片的文档数会比较少,这会导致文档数统计的误差变大。

此外,在使用分片副本时,分片统计数量也可能会不准确。分片副本是 Elasticsearch 用来提高数据可用性和查询性能的一种机制,副本与主分片的文档数量一样,但是分片统计数量却不包括副本。如果在查询时包含了分片副本,就会导致文档数统计的误差。

需要注意的是,分片统计数量的不准确并不会影响实际查询结果,因为 Elasticsearch 在查询时会遍历每个分片来计算结果,而不是依赖于分片统计数量。因此,如果分片数量不是非常多,或者查询条件比较简单,分片统计数量的误差可以忽略不计。但是,在某些需要准确文档数的场景下,例如使用 Elasticsearch 进行数据统计和分析时,可能需要使用其他方法来计算文档数,例如使用聚合查询等方式

64. 阐述ElasticSearch核心配置文件 ?

配置文件目录
elasticsearch.keystore 密钥库
elasticsearch.yml es相关的配置
jvm.options Jave jvm相关配置
log4j2.properties   日志相关的配置 log4j的日志框架
role_mapping 角色映射相关
roles 角色一般没动
elasticsearch.yml
Cluster集群相关配置
1 cluster.name: my-application #配置集群名称,由多个es实例组成的集群,有一个共同的名称。
2 transport.tcp.port: 9300 #集群端口设置。
3 cluster.routing.allocation.same_shard.host:true #防止同一个shard的主副本存在同一个物理机上。
4 cluster.routing.allocation.node_initial_primaries_recoveries: 4 #初始化数据恢复时,并发恢复线程的个数,默认是4个。
5 cluster.routing.allocation.node_concurrent_recoveries: 4 #添加删除节点或者负载均衡时并发恢复线程的个数。默认是4个。
Node节点相关配置
1 node.name: node-1 #节点名称配置,一个es实例其实是一个es进程,在集群中被称为节点。如果一个服务器上配置集群,各节点的名称不能重复。
2
3 node.attr.rack: r1 #为节点添加自定义属性
4
5 node.master: true #该节点是否有资格成为主节点,默认为true
6
7 node.data: true #设置节点是否存储数据
8
9 index.number_of_shards: 5 #设置默认主分片的个数,默认为5片,需要说明的是,主分片一经分配则无法更改
10
11 index.number_of_replicas: 1 #设置默认复制分片的个数,默认一个主分片对应一个复制分片,需要说明的是,复制分片可以手动调整
12
13 indices.recovery.max_size_per_ser: 0 #设置数据恢复时限制的带宽,默认0及不限制
14
15 indices.recovery.concurrent_streams: 5 #设置这个参数来限制从其它分片恢复数据时最大同时打开并发流的个数,默认为5
16
17 indices.recovery.max_size_per_ser: 0 #设置数据恢复时限制的带宽,默认0及不限制
18
19 indices.recovery.concurrent_streams: 5 #设置这个参数来限制从其它分片恢复数据时最大同时打开并发流的个数,默认为5
Paths 存储路径配置
1 path.data: /path/to/data #存储数据路径设置,多个路径以英文状态的逗号分隔,默认根目录下的conf目录。
2 #path.data: /path/to/data1,/path/to/data1
3
4 path.work: /path/to/work #设置临时文件存储路径,默认是es目录下的work目录。
5
6 path.logs: /path/to/logs #日志文件路径,默认为根目录下的logs目录。
7
8 path.logs: /path/to/logs #设置日志文件的存储路径,默认是es目录下的logs目录。
9
10 path.plugins: /path/to/plugins #设置插件的存放路径,默认是es目录下的plugins目录。
Network相关配置
1 network.host: 192.168.0.1 #为es实例绑定特定的IP地址。
2
3 #上面的设置可以拆分为两个参数。
4 network.bind_host: 192.168.0.1 #设置绑定的ip地址,ipv4或ipv6都可以
5 network.publish_host: 192.168.0.1 #设置其它节点和该节点交互的ip地址,如果不设置它会自动判断,值必须是个真实的ip地址
6
7 http.port: 9200 #为es实例设置特定的端口,默认为9200端口。
Discovery相关配置
1 discovery.zen.ping.multicast.enabled: true #设置是否打开多播发现节点,默认是true。
2
3 #配置es单播发现列表,在es启动时,通过这个列表发现别的es实例,从而加入集群。
4 discovery.zen.ping.unicast.hosts: [“host1”, “host2”]
5 discovery.zen.ping.unicast.hosts: [“10.0.0.1”, “10.0.0.3:9300”, “10.0.0.6[9300-9400]”]
6
7 discovery.zen.minimum_master_nodes:2 #设置是告诉集群有多少个节点有资格成为主节点,一般的规则是集群节点数除以2(向下取整)再加一。比如3个节点集群要设置为2,这个试着是为了防止脑裂问题。
8
9 discovery.zen.ping.timeout: 3s #设置集群中自动发现其它节点时ping连接超时时间,默认为3秒,对于比较差的网络环境可以高点的值来防止自动发现时出错。
Memory相关配置
1 #启动时锁定内存,默认为true,因为当jvm开始swapping时es的效率 会降低,所以要保证它不swap,可以把ES_MIN_MEM和ES_MAX_MEM两个环境变量设置成同一个值,并且保证机器有足够的内存分配给es。 同时也要允许elasticsearch的进程可以锁住内存,linux下可以通过ulimit -l unlimited命令
2 bootstrap.memory_lock: true
3
4 bootstrap.mlockall: true #禁止swapping交换。
Gateway相关配置
1 transport.tcp.compress: true #设置是否压缩tcp传输时的数据。默认是false不压缩。
2 http.max_content_length: 100mb #设置内容的最大容量,默认是100mb。
3 http.enabled: false #是否使用http协议对外提供服务。默认为true。
4 gateway.type: local #设置gateway的类型,默认为本地文件系统,也可以设置分布式文件系统、Hadoop的HDFS或者AWS的都可以。
5 gateway.recover_after_nodes: 3 #在完全重新启动集群之后阻塞初始恢复,直到启动N个节点为止
6 gateway.recover_after_time: 5m #设置初始化数据恢复进程的超时时间。默认是5分钟。
7 gateway.expected_nodes: 2 #设置该集群中节点的数量,默认为2个,一旦这N个节点启动,就会立即进行数据恢复。 我在recovery配置中用到这三参数
Various多方面配置
1 action.destructive_requires_name: true #删除索引时需要显式名称。
jvm.options相关配置
1 #设置jvm堆的大小,最大值和最小值,应该是一致的,并且应该根据你的物理内存决定。
2 -Xms1g #设置最小堆为1g
3 -Xmx1g #设置最大堆为1g

65. 如何修改Elasticsearch最大返回结果数 ?

#!/bin/bash
curl -H “Content-Type: application/json” -XPUT http://127.0.0.1:9200/_settings -d ‘{ “index” : { “max_result_window” : 50000000}}‘

66. 理解PHP中使用Elasticsearch的方法?

PHP中使用Elasticsearch

composer require elasticsearch/elasticsearch
会自动加载合适的版本!我的php是5.6的,它会自动加载5.3的elasticsearch版本!

Using version ^5.3 for elasticsearch/elasticsearch
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 4 installs, 0 updates, 0 removals

  • Installing react/promise (v2.7.0): Downloading (100%)
  • Installing guzzlehttp/streams (3.0.0): Downloading (100%)
  • Installing guzzlehttp/ringphp (1.1.0): Downloading (100%)
  • Installing elasticsearch/elasticsearch (v5.3.2): Downloading (100%)
    Writing lock file
    Generating autoload files
    简单使用

class MyElasticSearch
{
private $es;
// 构造函数
public function __construct()
{
include(‘…/vendor/autoload.php’);
$params = array(
‘127.0.0.1:9200’
);
KaTeX parse error: Undefined control sequence: \Elasticsearch at position 12: this->es = \̲E̲l̲a̲s̲t̲i̲c̲s̲e̲a̲r̲c̲h̲\ClientBuilder:…params)->build();
}

public function search() {
$params = [
‘index’ => ‘megacorp’,
‘type’ => ‘employee’,
‘body’ => [
‘query’ => [
‘constant_score’ => [ //非评分模式执行
‘filter’ => [ //过滤器,不会计算相关度,速度快
‘term’ => [ //精确查找,不支持多个条件
‘about’ => ‘谭’
]
]

]
]
]
];

$res = t h i s − > e s − > s e a r c h ( this->es->search( this>es>search(params);

print_r($res);
}
}
require “./MyElasticSearch.php”;

$es = new MyElasticSearch();

$es->search();
执行结果

Array
(
[took] => 2
[timed_out] =>
[_shards] => Array
(
[total] => 5
[successful] => 5
[skipped] => 0
[failed] => 0
)

[hits] => Array
(
[total] => 1
[max_score] => 1
[hits] => Array
(
[0] => Array
(
[_index] => megacorp
[_type] => employee
[_id] => 3
[_score] => 1
[_source] => Array
(
[first_name] => 李
[last_name] => 四
[age] => 24
[about] => 一个PHP程序员,热爱编程,谭康很帅,充满激情。
[interests] => Array
(
[0] => 英雄联盟
)

)

)

)

)

)
下面是官方的一些样例:

初始化
require ‘…/vendor/autoload.php’;
use Elasticsearch\ClientBuilder;
$client = ClientBuilder::create()->build();
增加配置

$hosts = [
‘127.0.01:9200’, // IP + Port
];

c l i e n t = C l i e n t B u i l d e r : : c r e a t e ( ) / / I n s t a n t i a t e a n e w C l i e n t B u i l d e r − > s e t H o s t s ( client = ClientBuilder::create() // Instantiate a new ClientBuilder ->setHosts( client=ClientBuilder::create()//InstantiateanewClientBuilder>setHosts(hosts) // Set the hosts
->build(); // Build the client object

$hosts = [
‘127.0.01:9200’, // IP + Port
];

$clientBuilder = ClientBuilder::create(); // Instantiate a new ClientBuilder
c l i e n t B u i l d e r − > s e t H o s t s ( clientBuilder->setHosts( clientBuilder>setHosts(hosts); // Set the hosts
$client = $clientBuilder->build(); // Build the client object
插入一个文档
// Index 一个文档
$params = [
‘index’ => ‘my_index’,
‘type’ => ‘my_type’,
‘id’ => ‘my_id’,
‘body’ => [‘testField’ => ‘abc’]
];

$response = c l i e n t − > i n d e x ( client->index( client>index(params);
print_r($response);
获取一个文档
$params = [
‘index’ => ‘my_index’,
‘type’ => ‘my_type’,
‘id’ => ‘my_id’
];

$response = c l i e n t − > g e t ( client->get( client>get(params);
print_r($response);
查询一个文档
$params = [
‘index’ => ‘my_index’,
‘type’ => ‘my_type’,
‘body’ => [
‘query’ => [
‘match’ => [
‘testField’ => ‘abc’
]
]
]
];

$response = c l i e n t − > s e a r c h ( client->search( client>search(params);
print_r($response);
删除一个文档
$params = [
‘index’ => ‘my_index’,
‘type’ => ‘my_type’,
‘id’ => ‘my_id’
];

$response = c l i e n t − > d e l e t e ( client->delete( client>delete(params);
print_r($response);
结果如下

Array
(
[_index] => my_index
[_type] => my_type
[_id] => my_id
[_version] => 3
[result] => deleted
[_shards] => Array
(
[total] => 2
[successful] => 1
[failed] => 0
)

[_seq_no] => 2
[_primary_term] => 1
)
删除一个索引
$deleteParams = [
‘index’ => ‘my_index’
];
$response = c l i e n t − > i n d i c e s ( ) − > d e l e t e ( client->indices()->delete( client>indices()>delete(deleteParams);
print_r($response);
创建一个索引
$params = [
‘index’ => ‘my_index’,
‘body’ => [
‘settings’ => [
‘number_of_shards’ => 2,
‘number_of_replicas’ => 0
]
]
];

$response = c l i e n t − > i n d i c e s ( ) − > c r e a t e ( client->indices()->create( client>indices()>create(params);
print_r($response);

67. Logstash如何把MySQL数据库中的数据导入到Elasticsearch?

1.解压logstash2.2.2后台,进入到etc目录下,创建logstash-simple.conf,添加如下配置,根据自己的环境修改
input {
jdbc {
jdbc_driver_library => “/usr/local/elasticsearch-2.2.1/mysqldriver/mysql-connector-java-5.1.30-bin.jar”
jdbc_driver_class => “com.mysql.jdbc.Driver”
jdbc_connection_string => “jdbc:mysql://10.10.13.7:3306/carsrc?autoReconnect=true&useSSL=false”
jdbc_user => “devuser”
jdbc_password => “devuser”
schedule => “* * * * *”
jdbc_default_timezone => “Asia/Shanghai”
statement => “SELECT * FROM company_secondcar_source_order;”
}
}
output {
elasticsearch {
index => “carsrc”
document_type => “secondcarsource”
document_id => “%{car_source_id}”
hosts => [“10.10.13.7:9200”]
}
}
2.然后执行
./logstash -f …/etc/logstash-simple.conf
这样就会把表里的数据导入elasticsearch
用logstash2.2.2把mysql数据库中的数据导入到elasticsearch

68. 简述Elasticsearch和Redis区别?

Redis的最大特点当然就是key-value存储所带来的简单和高性能了。(推荐学习:Redis视频教程)

所谓key-value存储,就是每一条记录只包含一个用于查询数据的Key,以及与之对应的存储数据的value,就如同现实生活中的门牌号与住户,而没有诸如表、字段这些常规数据库中必需有的复杂概念,所有的查询都仅仅依赖于key值。因此,key-value数据库可谓是数据库中数据结构最简单的一种,也得益于这种简单的结构,再加上Redis会把所有数据加载到内存中的,Redis能得到远高于MongoDB这类常规数据库的读写性能。当然,Redis的功能还不止key-value存储这么简单,相较它的key-value前辈Memcached,Redis还支持数据持久化,list、set等多种数据结构,主从复制备份等一些列功能,因此Redis绝对称得上是key-value数据库中功能最全面、最简单易用的款。

Redis的key-valule存储带来了性能这个优势,但是也给复杂查询带来了很多局限。由于阉割掉了数据表、字段这样的重要特性,且所有的查询都依赖key,因此Redis无法提供常规数据库所具备的多列查询、区段查询等复杂查询功能。同时,由于Redis需要把数据存在内存中,这也大大限制了Redis可存储的数据量,这也决定了Redis难以用在数据规模很大的应用场景中。

Elasticsearch(ES)

相较于MongoDB和Redis,晚一年发布的ES可能知名度要低一些,但是ES在搜索引擎领域的名声绝对是是响当当的。相较于其他高大上的数据库产品,ES的出身要屌丝很多。ES的创建者Shay Banon曾经是一个失业的屌丝程序员,在无事可干的时候为了方便老婆搜索食谱而创建了ES(当然,当时还不叫ES)。不料无心插柳柳成荫,成就了今天最热门的搜索引擎数据库,果然妹子才是程序员工作的最大动力啊!ES也专门成立了自己的Elastic公司已经获得数亿美金融资,当年的屌丝程序员Shay Banon也早已逆袭成为CEO并走上人生巅峰。诸位程序员看官读完这个故事是不是也已经开始内心澎湃的想象自己出任CEO迎娶白富美那一天了?

ES的特点,正如其名,那就是搜索。严格的说,ES不是一个数据库,而是一个搜索引擎,ES的方方面面也都是围绕搜索设计的。ES支持全文搜索,这里简单解释下什么是全文搜索:对于“我在北京的一家互联网公司工作”这样的数据,如果你搜索“北京”、“互联网”、“工作”这些关键词都能命中这条数据的话,这就是全文搜索,你每天都在用的百度、Google都属于全文搜索。值得一提的是,ES的全文搜索对中文也有很好的支持(单是中文分词器就有很多种),绝对能够满足国内大多数人的全文搜索需求。除了搜索之外,ES还会自动的替你对所有字段建立索引,以实现高性能的复杂聚合查询,因此只要是存入ES的数据,无论再复杂的聚合查询也可以得到不错的性能,而且你再也不用为如何建立各种复杂索引而头痛了。

区别

如果你对数据的读写要求极高,并且你的数据规模不大,也不需要长期存储,选redis;

如果你需要构造一个搜索引擎或者你想搞一个看着高大上的数据可视化平台,并且你的数据有一定的分析价值或者你的老板是土豪,选ElasticSearch;

69. 理解Java操作Elasticsearch ?

引入依赖

org.springframework.boot
spring-boot-starter-data-elasticsearch

配置客户端
@Configuration
public class RestClientConfig extends AbstractElasticsearchConfiguration {
@Override
@Bean
public RestHighLevelClient elasticsearchClient() {
final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo(“172.16.91.10:9200”)
.build();
return RestClients.create(clientConfiguration).rest();
}
}
客户端对象
ElasticsearchOperations
RestHighLevelClient 推荐
ElasticsearchOperations
特点: 始终使用面向对象方式操作 ES
索引: 用来存放相似文档集合
映射: 用来决定放入文档的每个字段以什么样方式录入到 ES 中 字段类型 分词器…
文档: 可以被索引最小单元 json 数据格式
相关注解
@Document(indexName = “products”, createIndex = true)
public class Product {
@Id
private Integer id;
@Field(type = FieldType.Keyword)
private String title;
@Field(type = FieldType.Float)
private Double price;
@Field(type = FieldType.Text)
private String description;
//get set …
}
//1. @Document(indexName = “products”, createIndex = true) 用在类上 作用:代表一个对象为一个文档
– indexName属性: 创建索引的名称
– createIndex属性: 是否创建索引
//2. @Id 用在属性上 作用:将对象id字段与ES中文档的_id对应
//3. @Field(type = FieldType.Keyword) 用在属性上 作用:用来描述属性在ES中存储类型以及分词情况
– type: 用来指定字段类型

索引文档
@Test
public void testCreate() throws IOException {
Product product = new Product();
product.setId(1);
//存在id指定id 不存在id自动生成id
product.setTitle(“怡宝矿泉水”);
product.setPrice(129.11);
product.setDescription(“我们喜欢喝矿泉水…”);
elasticsearchOperations.save(product);
}

删除文档
@Test
public void testDelete() {
Product product = new Product();
product.setId(1);
String delete = elasticsearchOperations.delete(product);
System.out.println(delete);
}

查询文档
@Test
public void testGet() {
Product product = elasticsearchOperations.get(“1”, Product.class);
System.out.println(product);
}

更新文档
@Test
public void testUpdate() {
Product product = new Product();
product.setId(1);
product.setTitle(“怡宝矿泉水”);
product.setPrice(129.11);
product.setDescription(“我们喜欢喝矿泉水,你们喜欢吗…”);
elasticsearchOperations.save(product);
//不存在添加,存在更新
}

删除所有
@Test
public void testDeleteAll() {
elasticsearchOperations.delete(Query.findAll(), Product.class);
}

查询所有
@Test
public void testFindAll() {
SearchHits productSearchHits = elasticsearchOperations.search(Query.findAll(), Product.class);
productSearchHits.forEach(productSearchHit -> {
System.out.println(“id: " + productSearchHit.getId());
System.out.println(“score: " + productSearchHit.getScore());
Product product = productSearchHit.getContent();
System.out.println(“product: " + product);
}
);
}
RestHighLevelClient
创建索引映射
@Test
public void testCreateIndex() throws IOException {
CreateIndexRequest createIndexRequest = new CreateIndexRequest(“fruit”);
createIndexRequest.mapping(”{\n” +
" “properties”: {\n” +
" “title”:{\n" +
" “type”: “keyword”\n" +
" },\n" +
" “price”:{\n" +
" “type”: “double”\n" +
" },\n" +
" “created_at”:{\n" +
" “type”: “date”\n" +
" },\n" +
" “description”:{\n" +
" “type”: “text”\n" +
" }\n" +
" }\n" +
" }\n" , XContentType.JSON);
CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
System.out.println(createIndexResponse.isAcknowledged());
restHighLevelClient.close();
}

索引文档
@Test
public void testIndex() throws IOException {
IndexRequest indexRequest = new IndexRequest(“fruit”);
indexRequest.source(“{\n” +
" “id” : 1,\n" +
" “title” : “蓝月亮”,\n" +
" “price” : 123.23,\n" +
" “description” : “这个洗衣液非常不错哦!”\n" +
" }",XContentType.JSON);
IndexResponse index = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
System.out.println(index.status());
}

更新文档
@Test
public void testUpdate() throws IOException {
UpdateRequest updateRequest = new UpdateRequest(“fruit”,“qJ0R9XwBD3J1IW494-Om”);
updateRequest.doc(“{“title”:“好月亮”}”,XContentType.JSON);
UpdateResponse update = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
System.out.println(update.status());
}

删除文档
@Test
public void testDelete() throws IOException {
DeleteRequest deleteRequest = new DeleteRequest(“fruit”,“1”);
DeleteResponse delete = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
System.out.println(delete.status());
}

基于 id 查询文档
@Test
public void testGet() throws IOException {
GetRequest getRequest = new GetRequest(“fruit”,“1”);
GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
System.out.println(getResponse.getSourceAsString());
}

查询所有
@Test
public void testSearch() throws IOException {
SearchRequest searchRequest = new SearchRequest(“fruit”);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchAllQuery());
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//System.out.println(searchResponse.getHits().getTotalHits().value);
SearchHit[] hits = searchResponse.getHits().getHits();
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
}

综合查询
@Test
public void testSearch() throws IOException {
SearchRequest searchRequest = new SearchRequest(“fruit”);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder
.from(0)
.size(2)
.sort(“price”, SortOrder.DESC)
.fetchSource(new String[] {
“title”
}
,new String[] {
}
)
.highlighter(new HighlightBuilder().field(“description”).requireFieldMatch(false).preTags(“”).postTags(“”))
.query(QueryBuilders.termQuery(“description”,“错”));
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("总条数: "+searchResponse.getHits().getTotalHits().value);
SearchHit[] hits = searchResponse.getHits().getHits();
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
Map highlightFields = hit.getHighlightFields();
highlightFields.forEach((k,v)-> System.out.println("key: "+k + " value: "+v.fragments()[0]));
}
}

;