简介
ES是一款基于Lucene实现的一款分布式搜索引擎,它有以下优点
- 快
- Restful API,接入不需要编程语言支持
- 数据安全(主从)
- 功能丰富
- 接近实施的更新
Lucene
Lucene是一个由Java实现的搜索引擎,接下来简要介绍下它的原理
1.倒排索引
倒排索引是搜索引擎常用的一种索引方式。
它十分简单,首先将需要索引的语句进行分词,然后以每个词为key,需要索引的语句为value放入一个"MAP"中.
这里MAP之所以打引号,是因为我们不去限制这个MAP的实现方法,他可以用任意实现,比如红黑树,hash或者之后会介绍的FST。
举个例子:
需要索引的句子:
1.ElasticSearch 学习笔记
2.ElasticSearch 牛逼
倒排索引:
"ElasticSearch" : [1,2],
"学习" :[1]
"笔记" : [1]
"牛逼" : [2]
通过倒排索引,我们就能通过单个当词语查询到句子。
2.FST
FST全称是Finite State Transducer,
单从字面上看它类似于有限自动机,但实际可以把它看作一个压缩过但字典树,
字典树会对词语对前缀进行合并,而FST还会对词语对后缀进行合并。
我们以mon,thurs,tues三个词为例,
FST和字典树的结构分别如下:
字典树
FST
优点:内存占用率低,压缩率一般在3倍~20倍之间、模糊查询支持好、查询快
缺点:结构复杂、输入要求有序、更新不易
如何构建一个FST?
- 将所有的句子按照字典序进行排序
- 将句子先按照字典树的方式插入
- 如果确定有相同的后缀,则进行链接。
具体原理可参考:https://www.shenyanchao.cn/blog/2018/12/04/lucene-fst/
3.怎么存储倒排索引?(猜的)
一部分缓存在内存,一部分存在硬盘。
当FST当一个前缀有超过一定数量当后缀则放到内存中,否则存入磁盘。
真的是这样??
ES 与 Lucene 当关系
ES 的结构
ES是一个分布式服务,它由n个分片和m个备份构成,分片(P)和备份(R)被分配在不同的机器(Node)上,
ES
分片
一个分片里指存储了部分集群信息,具体存哪些则根据文档的routing字段决定(默认就是_id)
而一个分片上包含以下结构:
- 多个段(你可以把段理解为倒排索引)
- commit point,用于找到多个段
- In-memory buffer,用来收集更新信息
- transLog,类似与mysql的binLog,用于记录更新操作
为什么要有多个段?
一个段相当于一个Lucene,那为什么要有多个段?
因为Lucene的倒排索引采用FST实现,FST虽然高效,并且内存利用率高,但是更新困难。因此与其每次花大代价去更新原来的段,不如每次都新建一个段,之后索引时,遍历所有的段,并得出搜索结果。
但是这样做有两个问题:
- 随着段越来越多,搜索的效率会大大降低。
- 写入一个新的段需要IO操作,因此如果频繁写入,那么效率底下。
为了解决问题1,ES启动了一个后台的合并任务,他会在空闲时把这些段合并成一个大段。(类似于LevelDB的level合并机制)
为了解决问题2,ES使用In-memory buffer在内存中缓存新接受的更新请求。隔一段时间将这些请求整理成一个段,再将这个段放入系统段文件缓存中(注意不立即写入磁盘)。同时将每一个更新操作写入Translog当中,保证数据的持久性。当文件缓存中当段真正被写入磁盘后,清除Translog即可。
怎样把一个句子存入ES
首先我们得有一个句子,比如 "ES是=_=世界上最牛逼的搜索引擎",
ES通过句子的_id找到需要被存储的分片位置,将该句子发送过去,
之后这个句子会被解析器进行解析。(在ES中有许多解析器,你可以根据需求定义字段对应的解析器)
- 首先这个句子首先经过剔除特殊字符的解析器:
变成 => "ES是世界上最牛逼的搜索引擎"
- 经过剔除无用字的解析器:
变成 => "ES世界牛逼搜索引擎"
3.经过分词的解析器
变成 => ['ES','世界','牛逼','搜索','引擎']
4.经过同义词添加的解析器
变成 => ['ES','ElasticSearch','世界','牛逼','厉害','狠','搜索','查找','引擎']
ES将经解析的词和句子做成倒排索引,然后通过上一节所讲的方式存入磁盘。
如何进行搜索(match)
这个问题看起来很难,实则很简单。
- 首先ES会将输入的句子,通过上一节讲的解析器,分解成多个词。
- 将每个词通过倒排索引找到包含的句子
- 将这些包含关键词的句子收集起来,通过词语命中次数,命中种类,词频,词权重等进行打分(ES提供了多种打分方法,但是常用的方法是词频/逆向文档频率(term frequency/inverse document frequency))
- 将打好分的句子,通过分数排序,然后取前N个返回给用户。
以上讲解的是对于match方法背后的步骤,当然实际并非这么简单,了解原理就好。
当然term搜索也是ES中常用的一种搜索方式,它与match不同,他必须精确匹配。ES优化term操作,为它添加了缓存,具体方法就是通过一个稀疏的数组来存储命中的term节点,在将这个数组存入缓存中
中文分词
IK 分词器,
1、词典树Tire Tree的构建,即将现在的词典加载到一个内存结构中去
2、词的匹配查找,就是切词
3、歧义判断,即对不同切分方式的判定,哪种应是更合理的
网友评论