ES 写入原理

探讨Elasticsearch文档写入流程,包括buffer、translog、commitpoint机制,及如何通过调整refresh interval实现近实时搜索,同时介绍fsync、flush、segment merge等关键操作对性能的影响。

document写入原理
1. 数据写入es中是首先写到内存buffer缓存中
2. 每隔一段时间执行commit point
3. 执行commit操作后,buffer中的数据写入新的index segment中
4. 等待在os cache中的index segment被fync强制刷到磁盘上
5. 新的index segement被打开,供search使用
6. buffer被清空

每次commit point时,会有一个.del文件,标记了哪些segment中的哪些document被标记为deleted了
搜索的时候,会依次查询所有的segment,从旧的到新的,比如被修改过的document,在旧的segment中,会标记为deleted
在新的segment中会有新的数据

 

现在流程的问题,每次都必须等待fsync将segment刷入磁盘,才能将segement打开供search使用,这样的话,从一个document写入,到
它可以被搜索,可能会超过1分钟!!这就不是近实时的搜索了!!!!!主要瓶颈在于fsync实际发生磁盘ID写数据进磁盘,是很耗时
的。
写入流程改进如下:
1. 数据写入buffer
2. buffer满后,buffer的数据被写入segment文件,但是先写入os cache
3. 只要segment写入os cache,那就直接打开供search使用,不立即执行commit

数据写入os cache,并被打开供搜索的过程,叫做refresh,默认是每隔1秒refresh一次,也就是说,每隔一秒就会将buffer中的数据写
入一个新的index segment file,先写入os cache中。所以,es是近实时的,数据写入到可以被搜索默认是1s

POST /myindex/_refresh可以手动refresh

 

如果我们要求的时效性比较低,只要求一条数据写入es,一分钟以后才让我们搜索就可以了,那么就可以调整refresh interval

PUT /myindex
{
    "settings":{
        "refresh_interval":"30s"
    }
}

 

再次优化写入流程
1. 数据写入buffer缓存和translog日志文件
2. 每隔一秒种,buffer中的数据被写入新的segment file,并写入os cache,此时segment被打开并供search使用
3. buffer被清空
4. 重复1-3,新的segment不断添加,buffer不断被清空,而translog中的数据不断累加
5. 当translog长度达到一定程度的时候,commit操作发生
    1. buffer中的所有数据写入一个新的segment,并写入 os cache,打开供使用
    2. buffer被清空
    3. 一个commit point被写入磁盘,标明了所有的index segment
    4. filesystem cache中所有index segment file缓存数据,被fsync强行刷到磁盘上
    5. 现有的translog被清空,创建一个新的translog

基于translog和commit point,如何进行数据恢复
机器被重启,disk上的数据并没有丢失,此时就会将translog文件中的变更记录进行回访,重新执行之前的各种操作,在buffer中
执行,再重新刷一个一个的segment到os cache中,等待下一次commit发生即可
fsync+清空translog,就是flush,默认每隔30分钟flush一次,或者当translog过大的时候,也会flush

translog,每隔5s被fsync一次到磁盘上,在一次增删改操作后,当fsync在primary shard和replica shard都成功之后,那么增删
该操作才会成功

但是这种在一次增删改时强行fsync translog可能会导致部分操作比较耗时,也可以允许部分数据丢失,设置成异步fsync translog
PUT /index/_settings
{
    "index.translog.durability":"async",
    "index.translog.sync_interval":"5s"
}

每秒一个segment file,文件过多,而却每次search都要搜索所有的segment,很耗时,默认会在后台执行segment merge操作,在merge
的时候,被标记为deleted的document也会被彻底物理删除,每次merge操作执行流程

1. 选择一些有相似大小的segment,merge成一个大的segment
2. 将新的segment flush到磁盘上
3. 写一个新的segment flush到磁盘上去
4. 将新的segment打开供搜索
5. 将旧的segment删除
 

Elasticsearch 是一个分布式的搜索引擎,其数据写入机制设计兼顾了性能与可靠性。数据写入 Elasticsearch 的流程涉及多个组件和阶段,包括索引文档、写入缓冲、事务日志(translog)、刷新(refresh)、合并(flush)等步骤。 ### 数据写入的基本流程 1. **客户端请求**:客户端向 Elasticsearch 发送一个写入请求,例如 `index` 或 `create` 操作。请求可以发送到集群中的任意节点,该节点将作为协调节点(coordinating node)处理该请求。 2. **路由文档到分片**:协调节点根据文档的 `_id` 和索引的分片配置,确定该文档应被写入哪个主分片。Elasticsearch 使用哈希算法将文档分配到特定的主分片上。 3. **写入主分片**:协调节点将写入请求转发到对应的主分片所在的节点。主分片接收到请求后,会先将数据写入内存缓冲区(in-memory buffer),并记录到事务日志(translog)中。translog 是一个持久化的日志文件,用于在发生故障时恢复未持久化的数据。 4. **写入副本分片**:主分片成功写入后,会将写入请求复制到所有副本分片。副本分片同样会先将数据写入内存缓冲区,并更新 translog。只有当所有副本分片都确认写入成功后,主分片才会向协调节点返回写入成功的响应。 5. **刷新(Refresh)**:默认情况下,Elasticsearch 每秒会执行一次刷新操作,将内存缓冲区中的数据生成新的段(segment),并使其对搜索可见。这意味着数据在写入后大约 1 秒内可以被搜索到,这也是 Elasticsearch 被称为“准实时”搜索引擎的原因之一。 6. **合并(Flush)**:当 translog 达到一定大小或经过一定时间间隔时,Elasticsearch 会执行一次合并操作(flush)。合并操作会将内存中的段持久化到磁盘,并清空 translog。这一过程确保了数据的持久性,即使在发生故障时也不会丢失数据。 ### 数据一致性和可靠性 Elasticsearch 通过多种机制来保证数据的一致性和可靠性: - **事务日志(Translog)**:每次写入操作都会被记录到 translog 中。即使在数据尚未被刷新到磁盘的情况下发生故障,Elasticsearch 也可以通过重放 translog 中的操作来恢复数据。默认情况下,translog 每 5 秒或在每次操作后(取决于配置)会被同步到磁盘,以减少数据丢失的风险[^3]。 - **副本机制**:Elasticsearch 通过副本机制来提高数据的可用性和容错能力。每个主分片可以有多个副本分片,副本分片不仅提高了读取性能,还确保了在某个节点故障时,数据仍然可以从其他副本中获取。 - **写一致性设置**:Elasticsearch 提供了 `write consistency` 设置,允许用户控制写入操作必须成功的分片数量。默认情况下,写入操作只需要在主分片上成功即可返回成功状态,但可以通过设置 `consistency` 参数为 `all`,要求所有副本分片也必须成功写入,从而提高数据一致性[^2]。 ### 性能优化与权衡 Elasticsearch 在数据写入过程中提供了多种性能优化策略,但也需要在性能与可靠性之间进行权衡: - **刷新间隔(Refresh Interval)**:默认情况下,Elasticsearch 每秒刷新一次内存缓冲区中的数据,使其对搜索可见。如果需要更高的搜索实时性,可以缩短刷新间隔,但这会增加 I/O 负载。相反,如果对实时性要求不高,可以延长刷新间隔以减少资源消耗。 - **Translog 同步策略**:Elasticsearch 允许配置 translog 的同步策略。默认情况下,translog 每 5 秒同步一次到磁盘,这意味着在极端情况下可能会丢失最多 5 秒的数据。如果希望确保每次写入都立即持久化,可以将 `index.translog.durability` 设置为 `request`,但这会显著降低写入性能[^3]。 - **批量写入(Bulk API)**:为了提高写入效率,Elasticsearch 推荐使用批量写入(Bulk API)来一次性插入多条文档。批量写入可以减少网络往返次数和 I/O 操作,从而提升整体写入吞吐量。 ### 示例代码:使用 Bulk API 批量写入数据 以下是一个使用 Python 的 `elasticsearch` 客户端库进行批量写入的示例: ```python from elasticsearch import Elasticsearch, helpers # 连接到本地 Elasticsearch 集群 es = Elasticsearch(hosts=["http://localhost:9200"]) # 定义要写入的文档列表 actions = [ { "_index": "my-index-00001", "_id": i, "_source": { "title": f"Document {i}", "content": f"This is the content of document {i}.", }, } for i in range(1, 101) ] # 使用 helpers.bulk 进行批量写入 helpers.bulk(es, actions) ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值