forcemerge,类型选择和 oom

forcemerge,类型选择和 oom

最近太忙,没有时间写一些系统性的文章,但是有一些新的思考和认识和大家分享。

keyword 和 numeric 的选择

为字段选择哪种数据类型有很多讲究,尤其是数值类型的 bkd 索引在某些情况下有很高的代价,导致 CPU 负载很高:

  1. 为了做集合运算,bkd 只能把查询结果放到一个 size 为 maxDoc 的 bitset 中,构造这个 bitset 的代价可能很大,range 查询走 IndexOrDocValuesQuery 有机会走 docvalue 去查,但 term 查询只能构建 bitset,如果命中结果集很大,这个代价会非常大,而keyword 类型在可以在倒排链上直接执行 advance
  2. IndexOrDocValuesQuery有机会走docvalue避免查 bkd, 选择条件是如果bkd 的 cost 小于 leadcost 的 8 倍,则走 bkd,但是计算 bkd 的 cost 需要把它查一遍,所以数值类型的 range 查询也可能耗费大量 CPU,堆栈中可以看到大量 intersect 调用

keyword类型的主要缺点是在聚合的时候需要构建全局序数,而数值类型则不用。在聚合场景下,大部分情况下用 numeric 会好一些,但低基数字段通常会命中大量结果集,例如性别,如果使用 numeric则会在构建 bitset 上产生很高的代价,因此适合使用 keyword

综上所述,在类型选择上可以参考下面的原则:

  • 在仅查询的情况下,如果有 range 查询需求,使用 numeric,否则使用 keyword。
  • 在仅聚合的情况下,如果明确字段是低基数的,使用 keyword 配合 execution_hint:map,其他情况使用 numeric
  • 剩下 term查询+聚合的场景,需要综合考虑numeric类型term查询构建 bitset和 keyword 类型构建全局序数哪个代价更大,需要看实际场景,但是目前所知的最坏情况下,构建 bitset 会导致 cpu 跑满,构建全局序数的主要问题是带来的查询延迟,也会给 JVM 带来一些压力,但一般不会很恶略

forcemerge 后查询性能可能更差

通常我们认为一个 LSM 架构的系统,其文件数量 merge 到更少总会带来查询性能的提升,但Elasticsearch 和 lucene 确实有他的复杂之处,最近遇到一个案例,当索引 forcemerge 为 1 之后其查询延迟和查询 QPS都降低了,主要原因是, forcemerge 之后,查询语句构建 query cache的代价更大。

这个特殊场景是查询语句的 lead 子查询只在少数段上有命中。 绝大多数段上无命中,因此 leadCost 为 0,可以跳过构建 query cache 的过程。而 merge 为 1 之后 lead 条件必然是有命中的,有更大的几率要去构建 query cache。

可以跳过构建 query cache 的依据是子查询的 cost 除以 250 大于 leadCost,当 leadCost为 0 自然就不再构建了。

题外话:在 query cache 的 skip 机制是个很好的策略,但250并不适用所有场景,目前 Elasticsearch 没有可以调节的接口

另一种极端情况是 merge 为 1 之后文件数少了,如果有很高的并发读取单一的段文件,niofs 由于各线程使用同一个 FileChannel读文件,其线程安全特性会导致很多线程在等锁,但这种情况比较少见。
要确定一个查询语句是否只在少数分段有命中比较困难,如果你想要 forcemerge 的话,在现有机制下可以考虑两种方式可以避免这个问题,一是 merge 的目标段数量不再倾向于 merge 为尽量少的段,例如目标段数量可以按照每个段 1GB 来计算,第二种是如果 cache 命中率不高,可以考虑降低 250 这个数字。

节点被写入打挂的情况

一般来说节点被写入打挂的情况比较少,近期出现几次节点 OOM,起初怀疑是查询导致的,因为 write 队列只发生过个位数的积压,也没有 reject。但是mat 分析 dump 文件之后发现全是 bulk 请求堆积在内存,一个shard 级的请求大约 200M,并且重要的是系统 cpu 是 96c 的,这样如果所有 write 线程都在干活,即使没有进入队列,也要占用 20G 内存了!

关于磁盘水位线的设置

由于集群存在不同机型混部的情况,我一直倾向于将水位线设置为GB 值,而非百分比,但是在一些大存储的机型中并不合适,这样更容易触发磁盘空间不足的告警(内部的告警系统),与其按照固定的 GB 值自己换算告警值,还不如按百分比来配置。

关于 rebalance 的并发

rebalance的并发开多大是安全的值?这要取决于 master 的忙碌程度。在较低的版本(7.6之前)上master 存在一些已知的性能问题,shard-started等 PRC 处理慢,这种情况下,rebalance开 2 个并发都可能会导致 master 忙不过来,因为分片可能很小,很快就 move 完成了,但是触发的 shard-started RPC 却可能导致 master 处理几十秒的时间。这也和集群分片总数有关系。

特别感谢几位兄弟的支持,有些问题也不是一个人想明白的。

(转载请注明作者和出处 easyice.cn ,请勿用于任何商业用途)

1 Star2 Stars3 Stars4 Stars5 Stars (欢迎评分)
Loading...

发表评论

邮箱地址不会被公开。 必填项已用*标注