只有光头才能变强。html
文本已收录至个人GitHub精选文章,欢迎Star:github.com/ZhongFuChen…java
不知道你们的公司用Elasticsearch多很少,反正我公司的是有在用的。平时听同事们聊天确定避免不了不认识的技术栈,例如说:把数据放在引擎,从引擎取出数据等等。node
若是对引擎不了解的同窗,就压根听不懂他们在说什么(我就是听不懂的一位,扎心了)。引擎通常指的是搜索引擎,如今用得比较多的就是Elasticsearch。git
这篇文章主要是对Elasticsearch一个简单的入门,没有高深的知识和使用。至少我想作到的是:之后同事们聊引擎了,至少知道他们在讲什么。github
Elasticsearch is a real-time, distributed storage, search, and analytics engine算法
Elasticsearch 是一个实时的分布式存储、搜索、分析的引擎。sql
介绍那儿有几个关键字:数据库
因而咱们就得知道Elasticsearch是怎么作到实时的,Elasticsearch的架构是怎么样的(分布式)。存储、搜索和分析(得知道Elasticsearch是怎么存储、搜索和分析的)缓存
这些问题在这篇文章中都会有说起。性能优化
我已经写了200多篇原创技术文章了,后续会写大数据相关的文章,若是想看我其余文章的同窗,不妨关注我吧。公众号:Java3y
若是以为我这篇文章还不错,对你有帮助,不要吝啬本身的赞!
在学习一项技术以前,必须先要了解为何要使用这项技术。因此,为何要使用Elasticsearch呢?咱们在平常开发中,数据库也能作到(实时、存储、搜索、分析)。
相对于数据库,Elasticsearch的强大之处就是能够模糊查询。
有的同窗可能就会说:我数据库怎么就不能模糊查询了??我反手就给你写一个SQL:
select * from user where name like '%公众号Java3y%'
复制代码
这不就能够把公众号Java3y相关的内容搜索出来了吗?
的确,这样作的确能够。可是要明白的是:name like %Java3y%
这类的查询是不走索引的,不走索引意味着:只要你的数据库的量很大(1亿条),你的查询确定会是秒级别的
若是对数据库索引还不是很了解的同窗,建议复看一下我之前的文章。我以为我当时写得还不赖(哈哈哈)
GitHub搜关键字:”索引“
并且,即使给你从数据库根据模糊匹配查出相应的记录了,那每每会返回大量的数据给你,每每你须要的数据量并无这么多,可能50条记录就足够了。
还有一个就是:用户输入的内容每每并无这么的精确,好比我从Google输入ElastcSeach
(打错字),可是Google仍是能估算我想输入的是Elasticsearch
而Elasticsearch是专门作搜索的,就是为了解决上面所讲的问题而生的,换句话说:
下面咱们就来学学为何Elasticsearch能够作到上面的几点。
众所周知,你要在查询的时候花得更少的时间,你就须要知道他的底层数据结构是怎么样的;举个例子:
从上面说Elasticsearch的模糊查询速度很快,那Elasticsearch的底层数据结构是什么呢?咱们来看看。
咱们根据“完整的条件”查找一条记录叫作正向索引;咱们一本书的章节目录就是正向索引,经过章节名称就找到对应的页码。
首先咱们得知道为何Elasticsearch为何能够实现快速的“模糊匹配”/“相关性查询”,其实是你写入数据到Elasticsearch的时候会进行分词。
仍是以上图为例,上图出现了4次“算法”这个词,咱们能不能根据此次词为它找他对应的目录?Elasticsearch正是这样干的,若是咱们根据上图来作这个事,会获得相似这样的结果:
->
2,13,42,56这表明着“算法”这个词确定是在第二页、第十三页、第四十二页、第五十六页出现过。这种根据某个词(不完整的条件)再查找对应记录,叫作倒排索引。
再看下面的图,好好体会一下:
众所周知,世界上有这么多的语言,那Elasticsearch怎么切分这些词呢?,Elasticsearch内置了一些分词器
Elasticsearch分词器主要由三部分组成:
显然,Elasticsearch是老外写的,内置的分词器都是英文类的,而咱们用户搜索的时候每每搜的是中文,如今中文分词器用得最多的就是IK。
扯了一大堆,那Elasticsearch的数据结构是怎么样的呢?看下面的图:
咱们输入一段文字,Elasticsearch会根据分词器对咱们的那段文字进行分词(也就是图上所看到的Ada/Allen/Sara..),这些分词汇总起来咱们叫作Term Dictionary
,而咱们须要经过分词找到对应的记录,这些文档ID保存在PostingList
在Term Dictionary
中的词因为是很是很是多的,因此咱们会为其进行排序,等要查找的时候就能够经过二分来查,不须要遍历整个Term Dictionary
因为Term Dictionary
的词实在太多了,不可能把Term Dictionary
全部的词都放在内存中,因而Elasticsearch还抽了一层叫作Term Index
,这层只存储 部分 词的前缀,Term Index
会存在内存中(检索会特别快)
Term Index
在内存中是以FST(Finite State Transducers)的形式保存的,其特色是很是节省内存。FST有两个优势:
前面讲到了Term Index
是存储在内存中的,且Elasticsearch用FST(Finite State Transducers)的形式保存(节省内存空间)。Term Dictionary
在Elasticsearch也是为他进行排序(查找的时候方便),其实PostingList
也有对应的优化。
PostingList
会使用Frame Of Reference(FOR)编码技术对里边的数据进行压缩,节约磁盘空间。
PostingList
里边存的是文档ID,咱们查的时候每每须要对这些文档ID作交集和并集的操做(好比在多条件查询时),PostingList
使用Roaring Bitmaps来对文档ID进行交并集操做。
使用Roaring Bitmaps的好处就是能够节省空间和快速得出交并集的结果。
因此到这里咱们总结一下Elasticsearch的数据结构有什么特色:
从官网的介绍咱们已经知道Elasticsearch是分布式存储的,若是看过个人文章的同窗,对分布式这个概念应该不陌生了。
若是对分布式还不是很了解的同窗,建议复看一下我之前的文章。我以为我当时写得还不赖(哈哈哈)
GitHub搜关键字:”SpringCloud“,"Zookeeper","Kafka","单点登陆"
在讲解Elasticsearch的架构以前,首先咱们得了解一下Elasticsearch的一些常见术语。
相信你们看完上面的对比图,对Elasticsearch的一些术语就不难理解了。那Elasticsearch的架构是怎么样的呢?下面咱们来看看:
一个Elasticsearch集群会有多个Elasticsearch节点,所谓节点实际上就是运行着Elasticsearch进程的机器。
在众多的节点中,其中会有一个Master Node
,它主要负责维护索引元数据、负责切换主分片和副本分片身份等工做(后面会讲到分片的概念),若是主节点挂了,会选举出一个新的主节点。
从上面咱们也已经得知,Elasticsearch最外层的是Index(至关于数据库 表的概念);一个Index的数据咱们能够分发到不一样的Node上进行存储,这个操做就叫作分片。
好比如今我集群里边有4个节点,我如今有一个Index,想将这个Index在4个节点上存储,那咱们能够设置为4个分片。这4个分片的数据合起来就是Index的数据
为何要分片?缘由也很简单:
如今问题来了,若是某个节点挂了,那部分数据就丢了吗?显然Elasticsearch也会想到这个问题,因此分片会有主分片和副本分片之分(为了实现高可用)
数据写入的时候是写到主分片,副本分片会复制主分片的数据,读取的时候主分片和副本分片均可以读。
Index须要分为多少个分片和副本分片都是能够经过配置设置的
若是某个节点挂了,前面所提升的Master Node
就会把对应的副本分片提拔为主分片,这样即使节点挂了,数据就不会丢。
到这里咱们能够简单总结一下Elasticsearch的架构了:
上面咱们已经知道当咱们向Elasticsearch写入数据的时候,是写到主分片上的,咱们能够了解更多的细节。
客户端写入一条数据,到Elasticsearch集群里边就是由节点来处理此次请求:
集群上的每一个节点都是coordinating node
(协调节点),协调节点代表这个节点能够作路由。好比节点1接收到了请求,但发现这个请求的数据应该是由节点2处理(由于主分片在节点2上),因此会把请求转发到节点2上。
shard = hash(document_id) % (num_of_primary_shards)
路由到对应的节点以及对应的主分片时,会作如下的事:
flush index
到磁盘中。解释一下:
说白了就是:写内存缓冲区(定时去生成segement,生成translog),可以让数据能被索引、被持久化。最后经过commit完成一次的持久化。
等主分片写完了之后,会将数据并行发送到副本集节点上,等到全部的节点写入成功就返回ack给协调节点,协调节点返回ack给客户端,完成一次的写入。
Elasticsearch的更新和删除操做流程:
doc
记录打上.del
标识,若是是删除操做就打上delete
状态,若是是更新操做就把原来的doc
标志为delete
,而后从新新写入一条数据前面提到了,每隔1s会生成一个segement 文件,那segement文件会愈来愈多愈来愈多。Elasticsearch会有一个merge任务,会将多个segement文件合并成一个segement文件。
在合并的过程当中,会把带有delete
状态的doc
给物理删除掉。
查询咱们最简单的方式能够分为两种:
public TopDocs search(Query query, int n);
public Document doc(int docID);
复制代码
根据ID去查询具体的doc的流程是:
根据query去匹配doc的流程是:
从上面所讲的写入流程,咱们就能够知道:Get(经过ID去查Doc是实时的),Query(经过query去匹配Doc是近实时的)
Elasticsearch查询又分能够为三个阶段:
QUERY_AND_FETCH(查询完就返回整个Doc内容)
QUERY_THEN_FETCH(先查询出对应的Doc id ,而后再根据Doc id 匹配去对应的文档)
DFS_QUERY_THEN_FETCH(先算分,再查询)
通常咱们用得最多的就是QUERY_THEN_FETCH,第一种查询完就返回整个Doc内容(QUERY_AND_FETCH)只适合于只须要查一个分片的请求。
QUERY_THEN_FETCH整体的流程流程大概是:
(doc id)
返回给协调节点,由协调节点进行数据的合并、排序、分页等操做,产出最终结果。doc id
去各个节点上拉取实际的 document
数据,最终返回给客户端。Query Phase阶段时节点作的事:
doc id
给协调节点Fetch Phase阶段时节点作的是:
doc id
,对这些doc id
作聚合,而后将目标数据分片发送抓取命令(但愿拿到整个Doc记录)doc id
,拉取实际须要的数据返回给协调节点主流程我相信你们也不会太难理解,说白了就是:因为Elasticsearch是分布式的,因此须要从各个节点都拉取对应的数据,而后最终统一合成给客户端
只是Elasticsearch把这些活都干了,咱们在使用的时候无感知而已。
这篇文章主要对Elasticsearch简单入了个门,实际使用确定还会遇到不少坑,但我目前就到这里就结束了。
若是文章写得有错误的地方,欢迎友善指正交流。等年后还会继续更新大数据相关的入门文章,有兴趣的欢迎关注个人公众号。以为这篇文章还行,能够给我一个赞👍
参考资料:
若是你们想要实时关注我更新的文章以及分享的干货的话,能够关注个人公众号「Java3y」。
在公众号下回复「888」便可获取!!
本已收录至个人GitHub精选文章,欢迎Star:github.com/ZhongFuChen…
求点赞 求关注️ 求分享👥 求留言💬 对我来讲真的 很是有用!!!