聊一聊elastic search
今天聊一聊elastic search
首先说说正排索引和倒排索引,在我理解,正排索引就是知道了序号,根据序号查找到对应的内容,而倒排索引,就是根据内容锁定好序号,正排索引与倒排索引相结合的使用场景是,根据用户给的内容,根据倒排索引锁定内容的序号信息,然后根据序号,给出完整的内容。下面是一个简单的正排索引与倒排索引的例子:
es里的倒排索引:包括单词词典(Term Dictionary)和倒排列表(Posting List)。单词词典记录所有文档的单词,一般都比较大,还会记录单词到倒排列表的关联信息。单词词典一般用B+树的实现方式。倒排列表记录了单词对应的文档集合,由倒排索引项(posting)组成。
倒排索引项主要包含四个信息:
1,文档id,用于获取原始信息。
2,单词频率(TF,term frequency),记录该单词在该文档中出现的次数,用于后续相关性算分。
3,位置,记录单词在文档中的分词位置(多个),用于做词语搜索。
4,偏移量(offset),记录单词在文档的开始位置和结束位置,用于做高亮显示。
下面说说分词,分词就是简单来说就是把一句内容分成诸多单词。
分词器:分词器由三部分组成
1,character filters:针对原始文本进行处理,比如去除一些特殊标记符号。
2,tokenizer:将原始文本按照一定规则划分为单词。
3,token filters:针对上一步处理完的单词进行再加工,比如大小写转换,删除与新增等处理。
es的match query流程:es文档创建流程:
es文档读取流程:倒排索引一旦生成,不可更改。
优点:
1,不用考虑并发写文件的问题,杜绝了锁机制带来的性能问题。
2,由于文件不再更改,可以充分利用文件系统缓存,只需载入一次,只要内存足够,对该文件的读取都会从内存读取,性能高。
3,利于生成缓存数据。
4,利于对文件进行压缩存储,节省磁盘和内存存储空间。
缺点:需要写入新文档时,必须重新构建倒排索引文件,然后替换老文件后,新文档才能被检索,导致文档实时性差。
es文档搜索实时性问题
Lucene构建的单个倒排索引称为segment,合在一起称为index,es中的一个分片对应一个Lucene Index,Lucene会有一个专门的文件来记录所有的segment信息,称为commit point。
refresh:segment写入磁盘的过程很耗时,可以借助文件系统缓存的特性,先将segment在缓存中创建并开放查询来进一步提升实时性,该过程被称为refresh。在refresh之前文档会先存储在一个buffer中,refresh时将buffer中的所有文档清空并生成segment(在内存中)。es默认一秒执行一次refresh,因此文档的实时性被提高到1s,这是被称为近实时的原因。
translog:如果在内存中的segment还没有写入磁盘前发生了宕机,那么其中的文档就无法恢复了,如何解决这个问题。es引入了translog机制。写入文档到buffer时,同时将该操作写入translog。translog文件会即时写入磁盘,6.x后默认每个请求都会直接落盘,可以修改为每几秒写一次,这样的风险便是丢失几秒内的数据,相关配置为index.translog.*。es启动时会检查translog文件,并从中恢复数据。
flush:flush负责将内存中的segment写入磁盘,主要有以下工作:
1,将translog写入磁盘。
2,将index buffer清空,其中的文档生成一个新的segment,相当于一个refresh操作。
3,更新commit point并写入磁盘。
4,执行fsync操作,将内存中的segment写入磁盘。
5,删除旧的translog文件。
总结:先写index buffer,再写内存,再写磁盘,translog同时写磁盘保证数据不丢失。