分段存储
Elasticsearch底层属于分段存储,何为段?索引文件被拆分为多个子文件,则每个子文件叫做段,每一个段本身都是一个倒排索引,并且段具有不变性,一旦索引的数据被写入硬盘,就不可再修改。
段被写入到磁盘后会生成一个提交点,提交点是一个用来记录所有提交后段信息的文件。一个段一旦拥有了提交点,就说明这个段只有读的权限,失去了写的权限。相反,当段在内存中,就只有写的权限,而不具备读数据的权限,意味着不能被检索。
索引文件分段存储并且不可修改,那么新增、更新和删除如何处理呢?
新增,只需要对当前文档新增一个段就可以了
删除,由于不可修改,所以对于删除操作,不会把文档从旧的段中移除而是通过新增一个.del文件,文件中会列出这些被删除文档的段信息。这个被标记删除的文档仍然可以被查询匹配到,但它会在最终结果被返回前从结果集中移除。
更新,不能修改旧的段来进行反映文档的更新,其实更新相当于是删除和新增这两个动作组成。会将旧的文档在.del文件中标记删除,然后文档的新版本被索引到一个新的段中。可能两个版本的文档都会被一个查询匹配到,但被删除的那个旧版本文档在结果集返回前就会被移除。
写入原理
buffer:内存缓冲区
segment file:存储逆向索引的文件,每个segment本质上就是一个逆向索引,每秒都会生成一个segment文件,当文件过多时ES会自动进行segment merge(合并文件),合并时会同时将已经标注删除的文档物理删除。
commit point:记录当前所有可用的segment,每个commit point都会维护一个.del文件(ES删除数据本质上不属于物理删除),当ES做删改操作时首先会在.del文件中声明某个document已经被删除,文件内记录了在某个segment内某个文档已经被删除,当查询请求过来时在segment中被删除的文件是能够查出来的,当时当返回结果时会根据commit point维护的那个.del文件把已经删除的文档过滤掉。
translog日志文件:为了防止ES宕机造成数据丢失保证可靠存储,ES会将每次写入数据同时写到translog日志中。
ES数据写入流程:
1、数据写入buffer缓存和translog日志文件
2、buffer满了或者每隔1秒钟,refresh将mem buffer中的数据生成index segment文件并写入os cashe,此时segment可被打开以供search查询读取,这样文档就可以被搜索到了(此时文档还没有写到磁盘上);然后清空mem buffer供后续使用。可见,refresh实现的是文档从内存移到文件系统缓存的过程。
3、buffer被清空
4、重复1~3,新的segment不断增加,buffer不断被清空,而translog中的数据不断累加
5、当translog长度达到一定程度的时候,就会触发flush操作,否则默认每隔30分钟也会定时flush,其主要过程
5.1执行refresh操作将mem buffer中的数据写入到新的segment并写入os cache,然后打开本segment以供search使用,最后再次清空mem buffer。
5.2一个commit point被写入磁盘,这个commit point中标明所有的index segment。
5.3filesystem cache(os cache)中缓存的所有的index segment文件被fsync强制刷到磁盘os disk,当index segment被fsync强制刷到磁盘上以后,就会被打开,供查询使用。
5.4translog被清空和删除,创建一个新的translog。