乐趣区

关于数据库:Elasticsearch如何保证数据不丢失

[TOC]

如何保证数据写入过程中不丢

数据写入申请达到时,以须要的数据格式组织并写入磁盘的过程叫做数据提交,对应 es 就是创立倒排索引,保护 segment 文件
如果咱们同步的形式,来解决上述过程,那么零碎的吞吐量将很低
如果咱们以异步的形式,先写入内存,而后再异步提交到磁盘,则有可能因为机器故障而而失落还未写入到磁盘中的数据

为了解决这个问题,个别的存储系统都会设计 transag log (事务日志)或这 write ahead log(预写式日志)。它的作用时,将最近的写入数据或操作以日志的模式间接落盘,从而使得即使零碎解体后,仍然能够基于这些磁盘日志进行数据恢复。

Mysql 有 redo undo log,而 HBASE、LevelDB,RockDB 等采纳的 LSM tree 则提供了 write ahead log 这样的设计,来保证数据的不失落

间接落盘的 translog 为什么不怕升高写入吞吐量?

上述阐述中,数据以同步形式落盘会有性能问题,为什么将 translog 和 wal 间接落盘不影响性能?起因如下:

  • 写的日志不须要保护简单的数据结构,它仅用于记录还未真正提交的业务数据。所以体量小
  • 并且以程序形式写盘,速度快

es 默认是每个申请都会同步落盘 translog,即配置 index.translog.durabilityrequest。当然对于一些能够丢数据的场景,咱们能够将index.translog.durability 配置为 async 来晋升写入 translog 的性能,该配置会异步写入 translog 到磁盘。具体多长时间写一次磁盘,则通过index.translog.sync_interval 来管制

后面说了,为了保障 translog 足够小,所以 translog 不能有限扩张,须要在一定量后,将其对应的实在业务数据以其最终数据结构 (es 是倒排索引) 提交到磁盘,这个动作称为 flush,它会理论的对底层 Lucene 进行一次 commit。咱们能够通过index.translog.flush_threshold_size 来配置 translog 多大时,触发一次 flush。每一次 flush 后,原 translog 将被删除,从新创立一个新的 translog

elasticsearch 自身也提供了 flush api 来触发上述 commit 动作,但无非凡需要,尽量不要手动触发

如何保障已写数据在集群中不丢

对每个 shard 采纳正本机制。保障写入每个 shard 的数据不丢

in-memory buffer

前述 translog 只是保证数据不丢,为了其记录的高效性,其自身并不保护简单的数据结构。理论的业务数据的会先写入到 in-memory buffer 中,当调用 refresh 后,该 buffer 中的数据会被清空,转而 reopen 一个 segment, 使得其数据对查问可见。但这个 segment 自身也还是在内存中,如果零碎宕机,数据仍然会失落。须要通过 translog 进行复原

其实这跟 lsm tree 十分类似,新写入内存的业务数据寄存在内存的 MemTable(对应 es 的 in-memory buffer),它对应热数据的写入,当达到一定量并保护好数据结构后,将其转成内存中的 ImmutableMemTable(对应 es 的内存 segment),它变得可查问。

总结

  • refresh 用于将写入内存 in-memory buffer 数据,转为查问可见的 segment
  • 每次一次写入除了写入内存外 in-memory buffer,还会默认的落盘 translog
  • translog 达到一定量后,触发 in-memory buffer 落盘,并清空本人,这个动作叫做 flush
  • 如遇以后写入的 shard 宕机,则能够通过磁盘中的 translog 进行数据恢复

LSM Tree 的具体介绍

https://www.cnblogs.com/nices…

参考资料

https://ezlippi.com/blog/2018…
https://stackoverflow.com/que…
https://qbox.io/blog/refresh-…
https://www.elastic.co/guide/…
https://www.elastic.co/guide/…

欢送关注我的集体公众号 ” 东南偏北 UP”,记录代码人生,行业思考,科技评论

退出移动版