创建新文档(indexing)的操作分为两步:refresh 和 flush。
Refresh:
- 新插入的文档存放在 in-memory buffer 中
- 默认每秒一次的 refresh,会将 in-memory buffer 写入 in-memory segment(到这一步后,新文档就可被检索了)
每一个 shard 都有多个连续的 segment 组成,segment 是不可变的,所以每一次的 update 都意味着两步:
- 写入新数据
- 将老数据标记为已删除(在 merged 的时候才会真正删除)
Flush:
- 文档在被写入 in-memory buffer 的同时,也会写入 shard 的 translog
- 每 30 分钟(或 translog 大小达到阈值),会促发 flush
- flush 会清空 in-memory buffer,并且将 in-memory segment 提交到磁盘,然后清空 translog
translog 每 5s 就被提交到磁盘一次,可以通过 index.translog.flush_threshold_size
调整 translog 刷新的大小阈值。
涉及的指标:
indices.indexing.index_total
indices.indexing.index_time_in_millis
indices.indexing.index_current
indices.refresh.total
indices.refresh.total_time_in_millis
indices.flush.total
indices.flush.total_time_in_millis
通过监控 indexing latency,可以了解 ES 是否逼近写入极限。
1、提高写入性能
适当的制定 shards 数,让 index 分散于各个 node 之上,提高并发性能。
关闭 merge throttling,如果 ES 发觉有 merging 操作失败,就会自动会 index 进行限流,可以通过将 indices.store.throttle.type
设置为 none
来关闭这一功能。
提高 index buffer,indices.memory.index_buffer_size
默认为 10%。
在初始化 index 并需要执行大量 index 的时候,可以先不要设置 replicas,等大批量写入完成后,再设置 replica,可以显著提高性能。
默认每秒执行一次 refresh,降低 refresh 频率可以提高写入性能。
ES 2.0 以后,会在每一次 request 后 flush translog,设置 index.translog.durability=async
可以将 flush 设置为异步,并通过 sync_interval
设置刷新间隔。
需要注意的是,primary shards 数仅在创建 index 时可以指定,之后无法修改。只能通过创建新 index 再 reindex 的方式来实现扩展。
2、Store
GET /_settings
创建 index 时,可以指定文件系统,可用选项有:
fs
:系统默认,系统兼容性好;simplefs
:并发性能差;niofs
:并发效率高,不支持 windows;mmapfs
:使用 mmap
推荐使用 niofs。