1.为什么使用ElasticSearch
系统中的数据随着业务发展,时间推移数据会越来越多;而业务中的数据量扩大到一定程度就算有索引查询起来也会比较吃力,且业务中有往往采用模糊查询进行数据的搜索,而模糊查询会导致“查询引擎”放弃索引,导致系统数据查询时都是走全表扫描,这样查询效率是非常低的。而使用ES做一个全文索引将经常查询的某些字段比如 电商系统的商品表中的商品名称,描述、价格还有id这些字段我们放在索引库中可以提高查询效率;
2.ElasticSearch的Master选举流程
1.ElasticSearch中负责选举主节点是由ZenDiscovery模块负责的,该模块主要包含Ping(节点之间
通过RPC来发现彼此) 和 Unicast(一个主机列表需要控制哪些节点需要ping通);
2.对有资格成为master(node.master:true)的节点根据nodeId字典排序,选出第一个节点暂时认为
它是master,同时根据对某个节点的投票(超过半数),并且该节点自己也选举自己做为master那
么这个节点就是master。否则重新执行上面选举流程直到满足条件;
3.master节点职责主要包括 集群索引、节点的管理,不负责文档级别的管理(data节点可以关闭http
功能);
3.ElasticSearch集群脑裂问题
什么是集群脑裂?
即集群中有多个master主节点;
3.1.脑裂问题出现的原因
网络问题
集群中因为网络延迟导致一些节点访问不到master,这些节点认为master可能已经宕机
了从而选举产生新的master,并重新分配分片;
节点负载
主节点角色既为 master 又为 data,当访问量较大时可能会导致ES停止响应造成大面积
延迟,此时其它节点得不到主节点响应,认为主节点已经宕机故重新选举新的master;
内存回收
data节点上的ES进程占用较大内存时引发JVM大规模回收内存,造成ES进程失去响应,
因多数data节点未得到主节点响应故认为主节点宕机从而选择新的master;
3.2.如何解决脑裂问题
减少误判
调大discovery.zen.ping.timeout参数(默认3秒),该参数是指master未在其设置的时间范
围内响应就认为该节点已经宕机,可适当调大此参数减少误判的可能;
选举触发
discovery.zen.minimum_master_nodes(默认值为1,容易出现脑裂问题),该参数用于控
制触发选举行为发生的最小集群主节点数,当备选主节点数大于等于参数
(discovery.zen.minimum_master_nodes)值且备选主节点中有该参数值个节点认为主节
点已经宕机则触发从新选举master节点;
官方推荐设置规则:(集群候选主节点数/2) + 1
角色分离
即master节点与data节点分离;
主节点配置为:
node.master:true
node.data:false
从节点配置为:
node.master:false
node.data:true
4.ElasticSearch索引文档流程
协调节点默认使用文档 ID 参与计算(也通过支持 routing) 规则:shard = hash(文档ID) % (分片数);
当分片所在的节点接收到来自协调节点的请求后,会将请求写入到 Memory Buffer,然后定时(默认是每隔 1 秒)写入到 Filesystem Cache,这个从 Memory Buffer 到 Filesystem Cache 的 过程就叫做 refresh;
当然在某些情况下,存在 Momery Buffer 和 Filesystem Cache 的数据可能会丢失, ES 是通过 translog的机制来保证数据的可靠性的。其实现机制是接收到请求后,同时也会写入到 translog 中,当 Filesystemcache 中的数据写入到磁盘中时,才会清除掉,这个过程叫做 flush;
在 flush 过程中,内存中的缓存将被清除,内容被写入一个新段(segment),段的 fsync 将创建一个新的提交点,并将内容刷新到磁盘,旧的 translog 将被删除并开始一个新的 translog。
flush 触发的时机是定时触发(默认 30 分钟)或者 translog 达到512MB(默认为 512M);
5.ElasticSearch删除和更新文档流程
删除和更新文档都是写操作,但在ES中文档是不可变的,因此不能被删除或改动以展示其变
更;
删除:
磁盘上每个“段”(segment)都有一个相应的.del文件,当发送删除请求时文档并没有真正被删除,而是在.del文件中被标记为删除,被标记删除的文档依然能被匹配查询,只是在返回结果时被过滤掉。当段合并时在.del文件中被标记为删除的文档不会被写入新段;
更新:
在新的文档创建时ES会为该文档指定一个版本号,当执行更新时旧版本的文档在.del文件中被标记为删除,新版本的文档被索引到一个新段(segment),旧版本的文档依旧能被匹配查询,只是在返回结果时被过滤掉;
6.ElasticSearch搜索流程
搜索被执行成一个两阶段过程,我们称之为 Query Then Fetch(查询数据 + 取数据);
在初始查询阶段时,查询会广播到索引中每一个分片和副本。 每个分片在本地执行搜索并构建一个匹配文档的大小为 from + size 的优先队列。 PS:在搜索的时候是会查询Filesystem Cache 的,但是有部分数据还在 Memory Buffer,所以搜索是近实时的。(ES不仅会从磁盘中查询数据还会从Cache 或 Buffer中查询数据)
每个分片返回各自优先队列中 所有文档的 ID 和排序值 给协调节点,它合并这些值到自己的优先队列中来产生一个全局排序后的结果列表。
接下来就是取回阶段, 协调节点辨别出哪些文档需要被取回并向相关的分片提交多个 GET 请求。每个分片加载并丰富文档,如果有需要的话,接着返回文档给协调节点。一旦所有的文档都被取回了,协调节点返回结果给客户端。
Query Then Fetch 类型的搜索在文档相关性打分的时候参考的是本分片的数据,这样在文档数量较少的时候可能不够准确, DFS Query Then Fetch 增加了一个预查询的处理,询问 Term 和 Document frequency,这个评分更准确,但是性能会变差。
7.在Linux中部署ElasticSearch时有哪些优化方法
1.选择较大内存的服务器,因为ES会从Cache 或 Buffer中查询数据;
2.在更快CPU和更多核心数CPU中选择更多核心的更好,多个核心提供的并发远胜于前者;
3.固态和机械硬盘选择固态,在固态硬盘中查询和索引性能都有提升;
4.确保后台应用的JVM和ES服务器的JVM是一致的,在ES的一些地方使用Java的本地序列化
(JVM一致避免序列化时出现冲突)
5.通过设置 gateway.recover_after_nodes、 gateway.expected_nodes、
gateway.recover_after_time 可以在集群重启的时候避免过多的分片交换,这可能会让数据
恢 复从数个小时缩短为几秒钟;
6.Elasticsearch 默认被配置为使用单播发现,以防止节点无意中加入集群。只有在同一台机
器上运行的节点才会自动组成集群。最好使用单播代替组播;
7.假如64G内存将小于内存的一半给 Lucene(但不要超过 32 GB!),通过ES_HEAP_SIZE
环境变量设置;
8.Lucene 使用了大量的文件。同时, Elasticsearch 在节点和 HTTP 客户端之间进行通信也
使用了大量的套接字。 所有这一切都需要足够的文件描述符。你应该增加你的文件描述
符,设置一个很大的值,如 64,000;
8.ElasticSearch对于大数据量(上亿量级)的聚合如何实现
Elasticsearch 提供的首个近似聚合是 cardinality 度量。它提供一个字段的基数,即该字段的 distinct或者 unique 值的数目。它是基于 HLL 算法的。 HLL 会先对我们的输入作哈希运算,然后根据哈希运算的结果中的 bits 做概率估算从而得到基数。其特点是:可配置的精度,用来控制内存的使用(更精确 = 更多内存);小的数据集精度是非常高的;我们可以通过配置参数,来设置去重需要的固定内存使用量。无论数千还是数十亿的唯一值,内存使用量只与你配置的精确度相关;
9.并发情况下Elasticsearch 如果保证读写一致?
可以通过版本号使用乐观锁并发控制,以确保新版本不会被旧版本覆盖,由应用层来处理具体的冲突;
另外对于写操作,一致性级别支持 quorum(大多数分片可用时)/one(一个分片可用时)/all(所有分片可用时),默认为 quorum,即只有当大多数分片可用时才允许写操作。但即使大多数可用,也可能存在因为网络等原因导致写入副本失败,这样该副本被认为故障,分片将会在一个不同的节点上重建;
对于读操作,可以设置 replication 为 sync(默认),这使得操作在主分片和副本分片都完成后才会返回;如果设置 replication 为 async(异步)时,也可以通过设置搜索请求参数_preference 为 primary 来查询主分片,确保文档是最新版本;
10.如何监控ElasticSearch集群状态
1.可通过谷歌的elasticsearch-head插件(该插件为谷歌浏览器上的一个扩展程序);
2.可通过Kibana监控集群监控状态和性能;
11.Elasticsearch 中的集群、节点、索引、文档、类型是什么
集群是一个或多个节点(服务器)的集合,它们共同保存数据,并提供跨所有节点的联合索引和搜索功能。集群由唯一名称标识,默认情况下为"elasticsearch"。此名称很重要,因为如果节点设置为按名称加入群集,则该节点为群集的一部分;
节点是属于集群一部分的单个服务器。它存储数据并参与群集索引和搜索功能;
索引就像关系数据库中的“数据库”。它有一个定义多种类型的映射。索引是逻辑名称空间,映射到一个或多个主分片,并且可以有零个或多个副本;
文档类似于关系数据库中的一行,不同是ES中文档存储非结构化的数据;
类型相当于数据库中表的概念(ES中已经取消“类型”这个概念);
12.ElasticSearch中什么是倒排索引
倒排索引是搜索引擎的核心。搜索引擎的主要目标是在查找发生搜索条件的文档时提供快速搜索。ES中的倒排索引其实就是 lucene 的倒排索引,区别于传统的正向索引(Mysql根据索引匹配内容), 倒排索引会在存储数据时将关键词(数据分词)和数据进行关联,保存到倒排表中,然后查询时,将查询内容进行分词后在倒排表中进行查询,最后匹配数据即可;