记录一次es写数据延迟引发的问题 您所在的位置:网站首页 内网延迟高如何排查问题 记录一次es写数据延迟引发的问题

记录一次es写数据延迟引发的问题

2024-05-30 15:27| 来源: 网络整理| 查看: 265

背景

某天,项目中来了一个需求,简单描述下就是这样的:

全量查询业务系统mysql中某一张表的数据,灌入到es中

easy so much,索引设定一个字段versionTime,每天同步数据时塞入时间戳,之后根据条件,将不是这次的versionTime的数据删除,就完成了全量更新,并将这一天中业务系统可能发生的删除操作的数据在es中删除。

本以为结束了,但却忽略了一个问题,es有延迟,近实时搜索引擎不只是说说而已。结果就杯具了,60%以上的几率,最终存在于es中的数据只有一半左右,难以接受呀!接下来就是排查问题

排查问题的过程

因为数据量比较少,项目最近也要求轻量化,就没有部署到平台运行,而是用springboot整合的quartz框架完成,于是启动本地,打个断点,想看看批量写入后返回的啥(最初以为写数据出现了问题...),结果返回的正常,放掉断点,执行完后续代码后,一切正常,查看es,数据也对的上,一条没少。然后打着断点,试了个5 、6、 7、 8次之后,依然无法复现,最后排除了所有的可能,剩下唯一的不可能,难道断点有影响?

说干就干,去掉断点,试了两次之后,果然又出现了,es里面数据不全。

这下稍微想了想es的介绍,近实时搜索引擎,为啥是近实时而不是实时?这可真的有区别的,然后仔细查阅了资料,基本上可以断定,问题的原因就是es的更新延迟问题了。

接下来说下为啥有延时,延迟的本质在哪

延时的原因

首先要了解的一件事,ES的索引数据是写入到磁盘上的。但这个过程是分阶段实现的,因为IO的操作是比较费时的。整个过程大概如下:

写数据----->ES内存 buffer(缓存区)-------定期refresh成segment------>os系统文件缓冲区(在这里的数据对搜索可见)---->磁盘

而在这里还有个很重要的参数需要介绍一下,refresh_interval

refresh_interval默认为1s,可以通过 GET /index_name/_settings?include_defaults=true

命令查看,在返回中会看到类似这样的结果:

 (由于返回的数据太多,只截取了部分,各位看官可以自行实验)

这也就是本人这次创建的索引并未指定refresh_interval参数,使用了默认的1s,最终导致,在写操作结束后,立马执行删除操作,由于新的versionTime还没能被检索到,所以就删掉了一部分数据

如何解决

解决的思路在于es写入的过程,首先第一个想到的是sleep个 2s,反正是定时任务,而且还是在基本无人使用的时间段更新数据,程序执行慢点也无所谓,但是刚冒出来就否了,首先太挫,其次如果后续有人改了refresh_interval参数,sleep个 2s也没卵用,于是就使用了第二种办法,保证被索引的文档能够立即被搜索到

保证被索引的文档能够立即被搜索到, 有两种方法:_refresh 或者_flush。

调用_refresh就可以立即实现内存->文件系统缓存, 从而使文档可以立即被搜索到。

flush,flush是用于translog的。

这次用了refresh解决问题。以下列出了java版本常用API设置刷新策略的方法

java high level client中,为index、insert、update、bulk 提供了setRefreshPolicy方法,用于设置数据更改后的刷新策略。NONE("false"), // 默认;异步刷新,立即返回; IMMEDIATE("true"), // 立即刷新,对es集群压力会比较大 WAIT_UNTIL("wait_for"); // 等刷新时返回,响应性不太好,

io.serchbox中 Bulk.Builder Index.Builder 的 refresh()方法



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有