一、document增删改内核级原理
1、document 新增文档时es内部执行步骤
(1)数据写入服务器的内存缓冲器(buffer)和translog日志文件;
(2)每隔一秒钟,buffer中的数据被写入新的segment file,并进入os cache,此时segment被打开并供search使;
(3)index segment 直接把数据写入到cache缓存;
(4)os cache 存储数据后会返回结果给index segment,index segment 的查询开关会被打开;
(5)内存缓存器(buffer)会被清空;
2、写入流程实现NRT近实时(filesystem cache,refresh)
数据写入os cache,并被打开供搜索的过程,叫做refresh。默认是每隔1秒refresh一次。也就是说,每隔一秒就会将buffer中的数据写入一个新的index segment file,先写入os cache中。所以,es是近实时的,数据写入到可以被搜索,默认是1秒。
POST /my_index/_refresh命令可以手动refresh,一般不需要手动执行,没必要,让es自己搞就可以了
如果说我们对时效性要求比较低,只要求一条数据写入es一分钟以后能够让我们搜索到就可以了,那么就可以调整refresh interval
PUT /my_index
{
"settings": {
"refresh_interval": "30s"
}
}
3、写入流程实现durability可靠存储(translog,flush)
elasticsearch 内部是通过translog文件来实现持久化可靠存储的。其内部具体的执行流程如下:
- 当translog长度达到一定程度的时候,commit操作发生
- buffer中的所有数据写入一个新的segment,并写入os cache,同时打开index segment 开发供查询(search)使用
- buffer被清空
- 一个commit ponit被写入磁盘,标明了所有的index segment
- filesystem cache中的所有index segment file缓存数据,被fsync强行刷到磁盘上
- 现有的translog被清空,创建一个新的translog
elasticsearch 内部整个document 新增文档时es内部执行步骤(包含近实时、持久化可靠存储(translog,flush))图解说明如下:
2、document 修改和删除操作
每次commit point时,会有一个.del文件,标记了哪些segment中的哪些document被标记为deleted了
ps:上述的流程还只是一个相对来说考虑的比较少的流程,真正的es内部增删改还有很多其他的步骤来确保数据的及时性,比如es近实时的概念。
3、document 查询操作
搜索的时候会依次查询所有的segment,比如查询被修改过的document,在旧的segment中,会标记为deleted,在新的segment中会有其新的数据。
其查询逻辑遵循以下几点
(1)如果document没有被修改和删除过,搜索的时候会依次查询所有的segment找到这条数据后直接返回;
(2)如果document被删除了,当搜索时依次查询segment时,发现需要查询的数据已经被标记为deleted时,则不会返回该数据回去;
(3)如果document被更新了,这时搜索的时候会找到一个document的多个版本,但是只有最新的版本是正常的(其他的版本会被标记为deleted),则返回最新的版本数据;
二、基于translog和commit point,如何进行数据恢复
os cache存放一批数据,但是此时宕机了,导致os cache中的数据全部丢失了,那这个时候需要怎么才能够进行数据的修复呢?
解决办法:比较三种中的数据
- 磁盘中的数据:当服务器宕机时,磁盘(disk)中的数据并不会丢失,磁盘中存放了上一次commit point操作为止的所有数据(index segment通过fsync命令刷进去的数据)。
- os cache 中的数据:宕机后cache中的数据全部丢失了
- translog 文件:存放了上一次执行flush到最近的所有的数据
综合以上三个数据存放的地方比较,elasticsearch内部是直接把tarnslog文件中的记录进行回放,重新在(内存缓冲器)buffer中执行之前的各种操作,然后重新刷一个个的index segment到cache中,等待下一次的commit point操作执行。
三、写入流程实现海量磁盘文件合并(segment merge,optimize)
在上面讲的内容中,elasticsearch内部每秒一个index segment file,就会导致文件过多,而且每次search都要搜索所有的segment很耗时,所以elasticsearch内部默认会在后台执行segment merge操作,把多个大小相似的index segment文件合并成一个文件,并且在merge的时候被标记为deleted的document也会被彻底物理删除。
每次merge操作的执行流程如下:
(1)选择一些有相似大小的segment,merge成一个大的segment
(2)将新的segment flush到磁盘上去
(3)写一个新的commit point,包括了新的segment,并且排除旧的那些segment
(4)将新的segment打开供搜索
(5)将旧的segment删除
手动执行merge操作语句如下,但是尽量不要手动执行,让它自动默认执行就可以了
POST /my_index/_optimize?max_num_segments=1