如何提高ElasticSearch 索引速度

我Google了下,大致给出的答案如下:

  1. 使用bulk API
  2. 初次索引的时候,把 replica 设置为 0
  3. 增大 threadpool.index.queue_size
  4. 增大 indices.memory.index_buffer_size
  5. 增大 index.translog.flush_threshold_ops
  6. 增大 index.translog.sync_interval
  7. 增大 index.engine.robin.refresh_interval 

这篇文章会讲述上面几个参数的原理,以及一些其他的思路。这些参数大体上是朝着两个方向优化的:

  1. 减少磁盘写入
  2. 增大构建索引处理资源

一般而言,通过第二种方式的需要慎用,会对集群查询功能造成比较大的影响。这里还有两种形态的解决方案:

  1. 关闭一些特定场景并不需要的功能,比如Translog或者Version等
  2. 将部分计算挪到其他并行计算框架上,比如数据的分片计算等,都可以放到Spark上事先算好

上面的参数都和什么有关

其中

5,6 属于 TransLog 相关。

4 则和Lucene相关

3 则因为ES里大量采用线程池,构建索引的时候,是有单独的线程池做处理的

7 的话个人认为影响不大

2 的话,能够使用上的场景有限。个人认为Replica这块可以使用Kafka的ISR机制。所有数据还是都从Primary写和读。Replica尽量只作为备份数据。

Translog

为什么要有Translog? 因为Translog顺序写日志比构建索引更高效。我们不可能每加一条记录就Commit一次,这样会有大量的文件和磁盘IO产生。但是我们又想避免程序挂掉或者硬件故障而出现数据丢失,所以有了Translog,通常这种日志我们叫做Write Ahead Log。

为了保证数据的完整性,ES默认是每次request结束后都会进行一次sync操作。具体可以查看如下方法:

org.elasticsearch.action.bulk.TransportShardBulkAction.processAfter

该方法会调用IndexShard.sync 方法进行文件落地。

你也可以通过设置index.translog.durability=async 来完成异步落地。这里的异步其实可能会有一点点误导。前面是每次request结束后都会进行sync,这里的sync仅仅是将Translog落地。而无论你是否设置了async,都会执行如下操作:

根据条件,主要是每隔sync_interval(5s) ,如果flush_threshold_ops(Integer.MAX_VALUE),flush_threshold_size(512m),flush_threshold_period(30m)  满足对应的条件,则进行flush操作,这里除了对Translog进行Commit以外,也对索引进行了Commit。 

所以如果你是海量的日志,可以容忍发生故障时丢失一定的数据,那么完全可以设置,index.translog.durability=async,并且将前面提到的flush*相关的参数调大。

而极端情况,你还可以有两个选择:

  1. 设置index.translog.durability=async,接着设置index.translog.disable_flush=true进行禁用定时flush。然后你可以通过应用程序自己手动来控制flush。
  2. 通过改写ES 去掉Translog日志相关的功能

当然,如果去掉Translog日志有两个风险点:

  1. Get最新数据会有点问题。因为根据ID Get最新数据是从Translog里拿的。
  2. 我们知道ES通过Shard Replication 保证Node节点出现故障时出现数据的完整性。在Relocating的时候,Replica 从Primary 进行Recover时,Primary会先Snapshot Lucene,然后拷贝数据到Replica,最后通过回放Translog 保证数据的一致性。

Version

 Version可以让ES实现并发修改,但是带来的性能影响也是极大的,这里主要有两块:

  1. 需要访问索引里的版本号,触发磁盘读写
  2. 锁机制

目前而言,似乎没有办法直接关闭Version机制。你可以使用自增长ID并且在构建索引时,index 类型设置为create。这样可以跳过版本检查。

这个场景主要应用于不可变日志导入,随着ES被越来越多的用来做日志分析,日志没有主键ID,所以使用自增ID是合适的,并且不会进行更新,使用一个固定的版本号也是合适的。而不可变日志往往是追求吞吐量。

当然,如果有必要,我们也可以通过改写ES相关代码,禁用版本管理。

分发代理

ES是对索引进行了分片(Shard),然后数据被分发到不同的Shard。这样 查询和构建索引其实都存在一个问题:

如果是构建索引,则需要对数据分拣,然后根据Shard分布分发到不同的Node节点上。如果是查询,则对外提供的Node需要收集各个Shard的数据做Merge

这都会对对外提供的节点造成较大的压力,从而影响整个bulk/query 的速度。

一个可行的方案是,直接面向客户提供构建索引和查询API的Node节点都采用client模式,不存储数据,可以达到一定的优化效果。

另外一个较为麻烦但似乎会更优的解决方案是,如果你使用类似Spark Streaming这种流式处理程序,在最后往ES输出的时候,可以做如下几件事情:

  1. 获取所有primary shard的信息,并且给所有shard带上一个顺序的数字序号,得到partition(顺序序号) -> shardId的映射关系
  2. 对数据进行repartition,分区后每个partition对应一个shard的数据
  3. 遍历这些partions,写入ES。方法为直接通过RPC 方式,类似transportService.sendRequest 将数据批量发送到对应包含有对应ShardId的Node节点上。

这样有三点好处:

  1. 所有的数据都被直接分到各个Node上直接处理。避免所有的数据先集中到一台服务器
  2. 避免二次分发,减少一次网络IO
  3. 防止最先处理数据的Node压力太大而导致木桶短板效应

场景

因为我正好要做日志分析类的应用,追求高吞吐量,这样上面的三个优化其实都可以做了。一个典型只增不更新的日志入库操作,可以采用如下方案:

  1. 对接Spark Streaming,在Spark里对数据做好分片,直接推送到ES的各个节点
  2. 禁止自动flush操作,每个batch 结束后手动flush。
  3. 避免使用Version

我们可以预期ES会产生多少个新的Segment文件,通过控制batch的周期和大小,预判出ES Segment索引文件的生成大小和Merge情况。最大可能减少ES的一些额外消耗

总结

大体是下面这三个点让es比原生的lucene吞吐量下降了不少:

  1. 为了数据完整性  ES额外添加了WAL(tanslog)
  2. 为了能够并发修改  添加了版本机制
  3. 对外提供服务的node节点存在瓶颈

ES的线性扩展问题主要受限于第三点,具体描述就是:

如果是构建索引,接受到请求的Node节点需要对数据分拣,然后根据Shard分布分发到不同的Node节点上。如果是查询,则对外提供的Node需要收集各个Shard的数据做Merge

另外,索引的读写并不需要向Master汇报。

时间: 2024-11-01 02:50:13

如何提高ElasticSearch 索引速度的相关文章

提高数据库查询速度的几个思路

提高数据库查询速度的几个思路 :1.缓存,在持久层或持久层之上做缓存;2.数据库表的大字段剥离,保证单条记录的数据量很小; 3.恰当地使用索引;4.必要时建立多级索引; 5.分析Oracle的执行计划,通过表数据统计等方式协助数据库走正确的查询方式,该走索引就走索引,该走全表扫描就走全表扫描; 6.表分区和拆分,无论是业务逻辑上的拆分(如一个月一张报表.分库)还是无业务含义的分区(如根据ID取模分区);7.RAC;8.字段冗余,减少跨库查询和大表连接操作; 9.数据通过单个或多个JOB生成出来,

android Html内容如何预先加载到缓存,提高webview刷新速度呢

问题描述 android Html内容如何预先加载到缓存,提高webview刷新速度呢 因为在webview加载html内容的时候,需要解析html内容,再加载到webview里面,导致显示速度比较慢,如何在得到html内容的前提下,预先加载到缓存,提高webview的显示速度呢? 解决方案 浏览器的作用就是将得到的数据显示出来,跟你得到文本流再在textview中显示一样,你说的渲染太耗时除非是你过去网络资源时没有开辟子线程,或者要显示的图形或者js太复杂.另外webview相当于你使用了一个

如何提高网站访问速度?

据Websense调查公司称多达70%的上网者表示不愿意在页面读取上超过8秒钟,超过70%的人会因为"慢悠悠的网页下载速度"而放弃在线浏览和购物行为.网站的访问速度问题已经直接影响到了网站的流量,而网站的访问量几乎与网站的利益直接挂钩,因此网站的速度问题成为企业及站长十分关注的问题.笔者就如何提高网站访问速度提出自己的看法,希望对大家有所帮助. 统计显示,在我国,90%的企业网站选择虚拟主机作为网站空间.因此,选择好的虚拟主机商是保证速度和稳定的关键.从目前国内IDC的发展发展来看,解

用GetString来提高ASP的速度(可以列入专栏的文章)

速度 用GetString来提高ASP的速度 许多ASP程序员都有过执行数据库查询,然后将查询结果用HTML表格的形式显示出来的经历吧. 通常我们是这么做的: < % 'Create connection / recordset 'Populate data into recordset object % > < TABLE > < % Do While not rs.EOF % > < TR > < TD >< %=rs("Fi

如何提高电脑开机速度

如何提高电脑开机速度 如何提高电脑开机启动速度的实用方法 1.取消开机获取IP地址 很多家庭采用ADSL方式上网的电脑在启动之后,右下角会出现一个带感叹号的本地连接标志,用鼠标指向它时,会显示"受限制或无连接"之类的话.这种情况的出现,是由于本地连接无法自动获得IP地址,而每次启动时,系统都要自动进行获得IP地址的尝试,导致在WINDOWS桌面已经出现后的一段时间里,对我们的操作没有响应,甚至双击"我的电脑"也没有反应,严重影响电脑启动速度. 解决办法是这样:右击&

用innerhtml提高页面打开速度的方法

这篇文章介绍了用innerhtml提高页面打开速度的方法,有需要的朋友可以参考一下   查看源代码,可以发现,页首的登陆代码位置,只有一行 复制代码 代码如下: <div id="headtop"></div> 而flash幻灯的位置,也只有一行 复制代码 代码如下: <div id="index_slide"></div> 对于这种需要耗时的代码,最好是放在页面最后面加载,然后用innerhtml的方法加载到对应位置

受欢迎网站的前提提高网页打开速度

  关于受欢迎网站用户体验的方法论有很多,最基本的:别让我等!!提高网页打开速度. 为什么迅雷在下载软件中独树一帜?为什么越来越多的用户在低画质的视频网站上在线观看连续剧,而不是下载更清晰的视频文件?答案是:用户的耐心非常有限,用户对速度的追求远远超过了对画质等因素的追求. 回到网站运营问题上,你是否有在全国各地都测试过,访问打开你的网站需要几秒? 曾有很多研究表明:用户最满意的打开网页时间是2-5秒,如果等待超过10秒,99%的用户会关闭这个网页.也许这样讲,各位还不会有太多感触,接下来,我列

学会清理恶意插件,提高上网浏览速度

电脑用多的人可能会知道,当你的电脑里面程序软件过多时候,你的电脑看网页的速度会越来越慢.按理来说,我们开网页的速度主要取决于网速的快慢,和电脑本身应该没多大关系!那么这到底是怎么一回事呢?其实这是因为现在网上的多数程序软件在下载时都捆绑了工具栏.插件等一系列东西,用户在安装时稍微不注意就会把这些东西安装到浏览器中,从而加重浏览器的负担.下面我就告诉大家如何清理这些恶意插件,提高浏览器开启速度. 操作步骤: 1.在网上下载一些比较知名的电脑保护软件,比如360安全卫士.金山等等; 2.打开360安

win7系统通过注册表提高宽带20%速度

  windows系统默认保留了一定的网络带宽可以通过注册表来修改限制来提高带宽网络速度!豆豆系统小编本文就和大家一起来看看如何通过注册表修改限制提高20%网络速度! 1.点击桌面开始 2.运行 3.输入"gpedit.msc"点击确定 4.计算机配置 5.管理模板 6.网络 7.Qos数据包计划程序 8.限制保留宽带 9.点击已启用--一将带宽限制改为20%. 选应用.确定即可 设置方法很简单,其他系统也可以根据这个方法来提高网络速度!