烽火连三月,家书抵万金。
1 前言
最近在工作中接触到了 Elasticsearch
数据存储,对其近实时的查询很感兴趣,于是自己研究了一番其工作原理。在本文中将从 Elasticsearch
的索引工作机制来剖析 translog
、refresh
、flush
在数据存储中的作用和特点。
2 基本概念
我们都知道 ES
的存储基本单元为 shard
, 是基于 Lucence
做的索引, 一个 Index
中有多个 shard
, 每个 Index
是由多个 Segment
组成的。每个 Segment
都是一些倒排索引的集合,每次创建一个文档 Document
,都会归属到一个新的 Segment
, 而不是去修改原来的 Segment
。每次文档的删除只是将文档添加删除标记而不是真正的物理删除。每当修改文档时,也是将旧文档标识为删除,新建一个文档存储修改后的内容,删除的数据在 .del
文件中会有标记在查询数据时会过滤删除的数据。
ES
的 index
是一个逻辑的抽象概念,ES
会固定时间生成一个新的 Segment
文件,当 Segment
文件过多时会进行合并 merge
操作, 合并时会将标识为删除的文档物理删除。
3 参数解析
refresh
是指在 ES
中,将缓存中的文档写入 segment
,并打开 segment
使之可以被搜索的过程。
ini
# refresh 的刷新频率
# 近实时的操作就在于此,默认数据写入 segment 到数据可查询的间隔
index.refresh_interval=1s
commit point
这个是和数据库事务操作类似的,也是为了数据的安全,每次索引变更都会立即刷盘,这个动作会将 Segment 进行合并并写盘,保证内存中的数据尽量不丢失。刷盘 flush 是很重的io 操作,为了保证机器的性能并保证搜索的近实时性,通常 flush 操作不会那么频繁。
flush
的概念: ES
间隔 30 min
或者数据量达到 512MB
时,会将内存 buffer
数据全部写入新的 segment
中,内存 buffer
被清空,一个 commit point
被写入磁盘,并将 filesystem cache
中的数据通过 fsync
刷入磁盘,同时清空 translog
日志文件。
fsync
fsync 是 linux
系统的调用函数,是将内存 buffer
中的数据存储到文件系统中, 这里是将 filesystem cache
中的所有 segment
刷新到磁盘的操作。
translog
的概念:translog
的概念和 mysql 数据库的两次写类似,都是采用了 WAL (write ahead of log)
技术, 提供所有还没有刷到磁盘的操作的一个持久化记录。
ini
# translog 的刷新频率
index.translog.sync_interval=5s
# 同步方式:异步、同步、每次请求都处理
index.translog.durability=async|fsync|request
# translog 的默认大小
index.translog.flush_threshold_size=512MB
在 ES
启动时,它会从磁盘中使用最后一个提交点去恢复已知的 Segment
, 并且重做 translog
中所有的变更操作。为了防止 ES
宕机所造成的的数据丢失、保证数据的可靠性。ES
的每次操作不仅要写入内存 buffer
, 还会被写入到 translog
文件,每个 shard
都对应一个 translog
, translog
间隔 5s
会异步执行或者每个请求完成后执行一次 fsync
操作,将 translog
从缓存写入磁盘,这样的操作比较耗时,如果对数据实时性要求不高可以改为 async
方式,否则节点宕机会有 5s
的数据丢失。
4 总结
在本文中,主要介绍了 ES
的近实时操作的实现原理,介绍了 flush
、refresh
、translog
的基本概念和实现,并且介绍了对应的参数配置。 ES
在搜索方面的使用十分广泛,特别是在非结构化数据的场景。在项目中,如果是结构化数据可以采用 ES
或者 云数据库来解决,两种的性能不相上下,但是云数据库成本相对更低,但是对于非结构化的数据搜索,特别是日志搜索系统,ES
的作用会更大一点,在实际开发中要结合应用场景来选择对应的存储设备。