es 插入数据_【ES 系列2】数据写入分析

14dac9ff05400a48dc4c0b7f90201610.png

文章简介

当出现文档写入请求时,ES 内部到底发生了哪些过程?面对大批量的写入请求,ES 如何可以做到近实时的可搜索?为了满足聚合分析的等功能,ES 又做了哪些事情?本文试图对这些问题进行回答,文章大纲如下所示:

  1. 文档写入操作
  2. ES 内部文档处理过程
  3. 文档最终数据格式

文档写入操作

创建索引

PUT twitter
{
    "settings" : {
        "number_of_shards" : 3,
        "number_of_replicas" : 2
    }
}

插入文档

PUT twitter/_doc/1
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}

ES 内部处理过程

ES 集群接收到文档写入的 rest 请求发送的数据后,首先会对数据进行 size、类型等进行检查校验,校验成功则进入如下的文档写入过程。

  1. 生成 docid
  2. 分配到指定分片
  3. 写入内存 buffer 形成 segment,并记录 translog
  4. segment 刷新到文件缓存
  5. segment 落盘,提交 commit point
  6. translog flush

生成 docId,docId 是文档在 ES 集群中的唯一标识,默认的生成策略是基于时间戳UUID的 Base64 编码,核心代码如下:

// org.elasticsearch.common.UUIDs
private static final UUIDGenerator TIME_UUID_GENERATOR = new TimeBasedUUIDGenerator();
TIME_UUID_GENERATOR.getBase64UUID();

docId 同样可以自己指定,但是需要考虑到 数据倾斜 的问题,因为下面的分片分配操作是基于 docId 进行的。

文档分配,文档获得 docId 之后 ES 会根据设置的分片数对 docId 进行 Hash 操作,确定将文档分配到哪个分片,从而保证每个分片上的文档数量均衡增长,不会使得哪个分片负载过重,并且在进行搜索时是对每个分片并行查找,将文档平均分配到不同的分片可以最大化的利用不同机器的性能,加快搜索过程。文档分配策略如下:

shard_num = hash(_id) % num_primary_shards

数据写入,ES 每次接收到的数据不会直接落盘,这样对磁盘 I/O 的压力太大。数据首先会写入内存 buffer 并同时记录一份 translog,当内存 buffer 积攒到一定量的数据会在内存 buffer 中形成一个 segment 并刷到 文件系统的缓存中 ,此时数据可以被检索,由于此过程并没有真的落盘,记录 translog 的目的是为了防止在此过程中机器出现故障导致数据的丢失。

数据落盘,通常 segment 在经过默认的 refresh_interval (1s) 之后会同步到磁盘同时会更新 commit 文件表示数据已经持久化存储,此时 translog 文件会进行 flush 操作,清空 translog 文件,如果 segment 落盘失败,就不会发生 commit 提交操作,ES 就会从 translog 的上一个 commit 点进行恢复。

一致性保证,translog 也是记录在内存中,为了保证 translog 的一致性,ES 默认情况下 5s 会对 translog 进行一次刷盘操作,或者每次发生请求操作时,translog 会采用同步的方式进行落盘。由于落盘是一个很耗时的过程,因此在数据写入时尽可能的采用 大批量写入 的方式一次发送多条数据,减少 translog 的落盘次数,或者当某些数据对一致性的要求不高时,我们可以调整 translog 落盘的方式为 异步刷盘,这样可以极大的提升数据写入的性能,但也不要过大的设置刷盘时间,在数据量较大的情况下可能会导致内存消耗过高。调整 translog 异步刷盘的操作如下:

PUT twitter
{
  "settings": {
    "index": {
      "translog": {
        "sync_interval": "5s",
        "durability": "async"
      }
    }
  }
}

文档持久化数据格式

文档在内存中会构建成 segment 的形式进行落盘,那 segment 的构成过程发生了什么?segment 最终又是以怎样的形式存储在磁盘的?segment 中主要包含 3 种数据结构,Inverted Index、Stored Fields、Document Values

Inverted Index 被称作 倒排索引,主要包含两部分:

  • 一个有序的数据字典Dictionary(包括单词Term和它出现的频率)。
  • 与单词Term对应的Postings(即存在这个单词的文件)。

Stored Fields 被称作 字段查找,主要用于查找包含某个特定标题内容的文件,其本质上是一个简单的键值对key-value,但官方并不推荐使用,默认情况下会关闭此功能,推荐使用 source filtering 功能来代替。

Document Values 是 ES 的 列式存储,用于分析和排序。简单理解DocValues的话,它是一个以DocID为键,以Value为值的Map。它存储DocID到文档的正向关系,在排序或者统计计算时,通过DocID可以迅速取字段的值进行二次计算。

这些数据结构对应存储在磁盘上的文件格式如下表所示:

表格引用: https://elasticsearch.cn/article/6178

79454a4a3047691436b361bdcd24ec77.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值