Elasticsearch 的性能优化 (3)

适当的预分配是好的。但上千个分片就有些糟糕。我们很难去定义分片是否过多了,这取决于它们的大小以及如何去使用它们。 一百个分片但很少使用还好,两个分片但非常频繁地使用有可能就有点多了。 监控你的节点保证它们留有足够的空闲资源来处理一些特殊情况。

一个业务索引具体需要分配多少分片可能需要架构师和技术人员对业务的增长有个预先的判断,横向扩展应当分阶段进行。为下一阶段准备好足够的资源。 只有当你进入到下一个阶段,你才有时间思考需要作出哪些改变来达到这个阶段。

一般来说,我们遵循一些原则:

控制每个分片占用的硬盘容量不超过ES的最大JVM的堆空间设置(一般设置不超过32G,参加下文的JVM设置原则),因此,如果索引的总容量在500G左右,那分片大小在16个左右即可;当然,最好同时考虑原则2。

考虑一下node数量,一般一个节点有时候就是一台物理机,如果分片数过多,大大超过了节点数,很可能会导致一个节点上存在多个分片,一旦该节点故障,即使保持了1个以上的副本,同样有可能会导致数据丢失,集群无法恢复。所以, 一般都设置分片数不超过节点数的3倍。

主分片,副本和节点最大数之间数量,我们分配的时候可以参考以下关系:
节点数<=主分片数*(副本数+1)

创建索引的时候需要控制分片分配行为,合理分配分片,如果后期索引所对应的数据越来越多,我们还可以通过索引别名等其他方式解决。

以上是在创建每个索引的时候需要考虑的优化方法,然而在索引已创建好的前提下,是否就是没有办法从分片的角度提高了性能了呢?当然不是,首先能做的是调整分片分配器的类型,具体是在 elasticsearch.yml 中设置cluster.routing.allocation.type 属性,共有两种分片器even_shard,balanced(默认)。

even_shard 是尽量保证每个节点都具有相同数量的分片,balanced 是基于可控制的权重进行分配,相对于前一个分配器,它更暴漏了一些参数而引入调整分配过程的能力。

每次ES的分片调整都是在ES上的数据分布发生了变化的时候进行的,最有代表性的就是有新的数据节点加入了集群的时候。当然调整分片的时机并不是由某个阈值触发的,ES内置十一个裁决者来决定是否触发分片调整,这里暂不赘述。另外,这些分配部署策略都是可以在运行时更新的,更多配置分片的属性也请大家自行查阅网上资料。

索引优化 Mapping建模

尽量避免使用nested或 parent/child,能不用就不用;nested query慢, parent/child query 更慢,比nested query慢上百倍;因此能在mapping设计阶段搞定的(大宽表设计或采用比较smart的数据结构),就不要用父子关系的mapping。

如果一定要使用nested fields,保证nested fields字段不能过多,目前ES默认限制是50。参考:
index.mapping.nested_fields.limit :50
因为针对1个document, 每一个nested field, 都会生成一个独立的document, 这将使Doc数量剧增,影响查询效率,尤其是JOIN的效率。

避免使用动态值作字段(key), 动态递增的mapping,会导致集群崩溃;同样,也需要控制字段的数量,业务中不使用的字段,就不要索引。控制索引的字段数量、mapping深度、索引字段的类型,对于ES的性能优化是重中之重。以下是ES关于字段数、mapping深度的一些默认设置:
index.mapping.nested_objects.limit :10000 index.mapping.total_fields.limit:1000 index.mapping.depth.limit: 20

不需要做模糊检索的字段使用 keyword类型代替 text 类型。

索引设置

如果你的搜索结果不需要近实时的准确度,考虑把每个索引的 index.refresh_interval 改到 30s或者更大。 如果你是在做大批量导入,设置 refresh_interval 为-1,同时设置number_of_replicas 为0,通过关闭 refresh 间隔周期,同时不设置副本来提高写性能。
文档在复制的时候,整个文档内容都被发往副本节点,然后逐字的把索引过程重复一遍。这意味着每个副本也会执行分析、索引以及可能的合并过程。相反,如果你的索引是零副本,然后在写入完成后再开启副本,恢复过程本质上只是一个字节到字节的网络传输。相比重复索引过程,这个算是相当高效的了。

修改 index_buffer_size 的设置,可以设置成百分数,也可设置成具体的大小,最多给512M,大于这个值会触发refresh。默认值是JVM的内存10%,但是是所有切片共享大小。可根据集群的规模做不同的设置测试。
indices.memory.index_buffer_size:10%(默认) indices.memory.min_index_buffer_size: 48mb(默认) indices.memory.max_index_buffer_size

修改 translog 相关的设置:

a. 控制数据从内存到硬盘的操作频率,以减少硬盘IO。可将 sync_interval 的时间设置大一些。
index.translog.sync_interval:5s(默认)。

b. 控制 tranlog 数据块的大小,达到 threshold 大小时,才会 flush 到 lucene 索引文件。
index.translog.flush_threshold_size:512mb(默认)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpwgxd.html