针对于elasticsearch,你会怎么去描述呢?
以下从四点来总结,轻喷!
1、elasticsearch是什么?
2、elasticsearch能做什么,业务场景?
3、elasticsearch架构设计?
4、elasticsearch具体的使用其原理是什么?
开始咋们的概述
官方给出:
Elasticsearch是一个高度可扩展的开源全文本搜索和分析引擎。它使您可以快速,近乎实时地存储,搜索和分析大量数据。它通常用作支持具有复杂搜索功能和要求的应用程序的基础引擎/技术。
搜索:
百度、京东等网点搜索功能
分析:
商品销量排行、访问量排行等、ELK日志收集分析
分布式应用,采用多节点多服务器去存储和检索数据能达到秒级
集群cluster
节点node:
master节点:指责主要包括集群、节点、索引的管理
当客户端调用请求接到的主节点,此时叫做coordinating协调节点:协调节点处理请求 对document路由转发(操作 document 选择分片 round-robin随机轮询算法
shard_num = hash(_routing) % num_primary_shards 随机选取一个分片)
data节点:数据管理
分片shard:es是分布式应用,索引会被分解成不同的部分,默认5分片,在不同的节点数据可视为分片,es自动管理分片,会对数据进行平衡分配,默认单个分片的文档数量为20亿,每个分片实质上就是一个lucene索引
副本replica:默认常见分片时则会创建一个副本,分片和其副本不在一个节点上,当分片挂掉会副本会竞选为主分片(只有主分片才能处理编辑请求),副本只能进行查询
合理设置分片数量:
一个分片就是一个lucene索引,会消耗相应的文件句柄,内存和cpu资源
1、协调节点计算对document路由转发对应的分片上
2、将请求写入Memory Buffer,默认每隔一秒写入FileSystem Cache,过程叫做refresh
3、在此过程中可能会出现数据丢失的情况,es通过translog机制保证数据安全。写入Memory Buffer同时写入translog中,当FileSystem Cache落盘(写入磁盘)才会被清除,过程叫做flush
4、flush过程中,Memory Buffer被清除,内容写入一个新段segement,段的fsync()创建提交点 将内容刷盘,flush的触发条件是默认30分钟 or translog超过默认512M
总结:整个过程类似于mysql隔离级别中如何保证一致性,undo log和redo log落盘是类似的
删除和更新也都是写操作,es中的文档是不可变的,因此不能变更。
1、磁盘上的段segement都有对应的.del文件,删除操作时,并未真正删除,而是打了标记,能被搜索,但是在搜索结果中会被过滤掉。当合并段的时候,打标的文档不会被写入
2、更新操作时,更新对应文档的版本号,旧版本打标记同删除
A、对于已知文档的搜索(有documentId)
客户端给主节点发送get请求,当前节点则为协同节点。协同节点使用路由算法计算文档所在的分片并发送请求,文档所在分片/副本分片返回给主节点。
B、对于未知文档的搜索(无documentId)
搜索分为两阶段:初始查询、取回
1、初始查询
查询会广播到每一个分片(轮询算法循环在副本分片中进行请求),每个分片在本地执行搜索并构建一个优先队列(搜索时会查询filesystem cache和Memory buffer 内存操作,所以搜索会实时)
2、取回
协调节点分析需要被取回 并向这些分片提交多个get请求,节点返回文档给协调节点,完成后协调节点返回给客户端。(涉及文档搜索评分)
疑问?es会设计到打分偏离的情况,如何处理?
打分偏离是因为根据每个分片本地查询评分并返回结果,每个分片会有偏差
如何处理?
es的DFS Query Then Fetch
1)预查询每个分片并发送查询请求
2)匹配到所有的文档,使用全局的Term/Document Frequency(TF-IDF)进行打分。对结果创建优先队列。
3)返回结果的元数据到请求节点。(并未发送真实文档,发送的只是评分)
4)分数合起来排序,在按照需要的文档,请求到对应的分片被检索出来
在分片内如何对词条进行搜索?
1、词条根据倒排索引获取文档
疑问?如果词条成千上万如何快速搜索呢?
2、对所有词条进行排序,根据二分法查找,效率是log(N)提高效率es直接通过内存查找。
疑问?词条太多内存操作不太现实如何处理呢?
3、引入了Term Index(类似字典索引页)
核心思想是利用跳表快速做与运算/利用BitSet位图按位与运算
(跳表是由多级链表组成如图)
类似于mysql的b树,比如查32第三级从11和第二个51比较,按照11到第二级,找到32
4)并发情况如何保证读写一致性?
1、可以通过版本号使用乐观并发控制,以确保新版本不会被旧版本覆盖,由应用层来处理具体的冲突;
2、另外对于写操作,一致性级别支持quorum/one/all,默认为quorum,即只有当大多数分片可用时才允许写操作。但即使大多数可用,也可能存在因为网络等原因导致写入副本失败,这样该副本被认为故障,分片将会在一个不同的节点上重建。
3、对于读操作,可以设置replication为sync(默认),这使得操作在主分片和副本分片都完成后才会返回;如果设置replication为async时,也可以通过设置搜索请求参数_preference为primary来查询主分片,确保文档是最新版本。