bulk批量写入
如果业务场景支持将一批数据聚合起来,一次性写入Elasticsarch,那么尽量采用bulk的方式,bulk批量写入的速度远高于一条一条写入大量document的速度。
并不是bulk size越大越好,而是根据写入数据量具体来定的,因为越大的bulk size会导致内存压力过大,因此最好一个请求不要发送超过10MB的数据量,以5-10MB为最佳值。计算公式为:
一次bulk写入的数据量大小=一次bulk批量写入的文档数*每条数据量的大小。
多线程写入
单线程发送bulk请求是无法最大化Elasticsearch集群写入的吞吐量的。如果要利用集群的所有资源,就需要使用多线程并发将数据bulk写入集群中。多线程并发写入同时可以减少每次底层磁盘fsync的次数和开销。
一旦发现ES返回了TOO_MANY_REQUESTS的错误,JavaClient也就是EsRejectedExecutionException。此时说明Elasticsearch已经达到了一个并发写入的最大瓶颈了。
推荐使用CPU核数的2倍线程数。
修改索引刷新时间及副本数
默认“index.refresh_interval”为“1s”,即每秒都会强制生成1个新的segments文件,增大索引刷新时间,可以生成更大的segments文件,有效降低IO并减少segments merge的压力,该配置项可以建索引时指定(或者配置到template里去)。
如果只是单纯导入数据,不需要做实时查询,可以把refresh禁用(即设置index.refresh_interval为-1),并设置“index.number_of_replicas”为“0”,当然这样设置会有数据丢失风险。等到数据完成导入后,再把参数设置为合适的值。
命令为单索引下操作如下所示,同时也支持多索引(索引名按逗号分隔)和全索引(用*通配符)操作。
curl -XPUT --tlsv1.2 --negotiate -k -v -u : "https://ip:httpport/myindex/_settings" -H 'Content-Type: application/json' -d'
{
"number_of_replicas": 0,
"refresh_interval": "180s"
}'
修改事务日志translog参数
默认设置下,translog 的持久化策略是每个请求都flush(durability参数值为request),这样能保证写操作的可靠性,但是对性能会有很严重的影响,实际测试发现如果使用默认设置进行导数据磁盘IO会持续占满。如果系统可以接受一定几率的数据丢失(或有手段补录丢失数据),可以通过调整 translog 持久化策略、周期性和一定大小的时候 flush,能大大提升导入性能。该配置项可以建索引时指定(或者配置到template里去)。执行命令如下所示:
curl -XPUT --tlsv1.2 --negotiate -k -v -u : "https://ip:httpport/myindex/_settings" -H 'Content-Type: application/json' -d'
{
"index": {
"translog": {
"flush_threshold_size": "1GB",
"sync_interval": "180s",
"durability": "async"
}
}
}'
注意:数据丢失风险
修改merge参数以及线程数
Elasticsearch写入数据时,refresh刷新会生成1个新的segment,segments会按照一定的策略进行索引段合并merge。merge的频率对写入和查询的速度都有一定的影响,如果merge频率比较快,会占用较多的IO,影响写入的速度,但同时segment个数也会比较少,可以提高查询速度。所以merge频率的设定需要根据具体业务去权衡,同时保证写入和查询都相对快速。Elasticsearch默认使用TieredMergePolicy,可以通过参数去控制索引段合并merge的频率:
1)参数“index.merge.policy.floor_segment”,Elasticsearch避免产生很小的segment,小于这个阀值的所有的非常小的segment都会merge直到达到这个floor的size,默认是2MB。
2)参数“index.merge.policy.max_merge_at_once”,一次最多只merge多少个segments,默认是10。
3)参数“index.merge.policy.max_merged_segment”,超过多大size的segment不会再做merge,默认是5g。
4)参数“index.merge.policy.segment_per_tier”默认为10,表示每个tier允许的segment个数,注意这个值要大于等于“index.merge.policy.max_merge_at_once”值,否则这个值会先于最大可操作数到达,就会立刻做merge,这样会造成频繁merge。
5)参数“ index.merge.scheduler.max_thread_count ”,单个shard上可能同时合并的最大线程数。默认会启动 Math.max(1, Math.min(4, Runtime.getRuntime().availableProcessors() / 2)) 个线程进行merge操作,适用于SSD固态硬盘。但是如果硬盘是机械硬盘,很容易出现IO阻塞,将线程数设置为1。
一般情况下,通过调节参数“index.merge.policy.max_merge_at_once”和“index.merge.policy.segment_per_tier”去控制merge的频率。
参数修改 | 好处 | 坏处 |
---|---|---|
提高“index.merge.policy.max_merge_at_once” 和“index.merge.policy.segment_per_tier”参数值(eg :50) | 提升indexing速度 | 减少了segment merge动作的发生,意味着更多的segments,会降低searching速度 |
降低“index.merge.policy.max_merge_at_once” 和“index.merge.policy.segment_per_tier”参数值(eg :5) | Segments更少,即能够提升searching速度 | 更多的segments merge操作,会花费更多系统资源(CPU/IO/RAM),会降低indexing速度 |
修改参数命令如下示例:
curl -XPUT --tlsv1.2 --negotiate -k -v -u : "https://ip:httpport/myindex-001/_settings?pretty" -H 'Content-Type: application/json' -d'
{
"merge": {
"scheduler": {
"max_thread_count": "1"
},
"policy": {
"segments_per_tier": "20",
"max_merge_at_once": "20",
"floor_segment": "2m",
"max_merged_segment": "5g"
}
}
}
禁用Doc Values
默认情况下,支持doc values 的所有字段都是开启的。因为 Doc Values 默认启用,可以选择对数据集里面的大多数字段进行聚合和排序操作。但是如果确定不需要在字段上进行排序和聚合,或从脚本中访问字段值,则可以禁用 doc values 来节省磁盘空间。
要禁用 Doc Values ,在字段的映射(mapping)设置 “doc_values”为“false”即可。例如,这里我们创建了一个新的索引,字段 “session_id” 禁用了 Doc Values:
curl -XPUT --tlsv1.2 --negotiate -k -v -u : "http://ip:httpport/myindex" -H 'Content-Type: application/json' -d'
{
"mappings": {
"my_type": {
"properties": {
"session_id": {
"type": "keyword",
"doc_values": false
}
}
}
}
}'
禁用_source字段
“_source”字段包含在索引时传递的原始JSON文档正文。该“_source”字段本身不被索引(因此是不可搜索的),但它被存储,以便在执行撷取请求时可以返回,例如get或search。
虽然很方便,但是“_source”字段确实在索引中有不小的存储开销。因此,可以使用如下方式禁用:
curl -XPUT --tlsv1.2 --negotiate -k -v -u : 'https://ip:httpport/tweets?pretty' -H 'Content-Type: application/json' -d'
{
"mappings": {
"tweet": {
"_source": {
"enabled": false
}
}
}
}'
说明: 在禁用_source 字段之前请注意:如果_source字段不可用,则不支持以下功能:
1)update,update_by_query,reindex APIs.
2)高亮
3)将索引从一个Elasticsearch索引reindex(重索引)到另一个索引的能力,以便更改映射或分析,或将索引升级到新的主要版本。
4)通过查看索引时使用的原始文档来调试查询或聚合的能力。
5)潜在的未来可能会自动修复索引损坏的能力。