日志领域是Elasticsearch(ES)最重要也是规模最大的应用场景之一。这得益于 ES 有高性能倒排索引、灵活的 schema、易用的分布式架构,支持高吞吐写入、高性能查询,同时有强大的数据治理生态、端到端的完整解决方案。但原生 ES 在高吞吐写入、低成本存储、高性能查询等方面还有非常大的优化空间,本文重点剖析腾讯云大数据 ES 团队在这三个方面的内核增强优化。
2. 日志领域的挑战
我们先来看看日志领域的挑战有哪些。
首先从日志本身的数据特点来看,主要以半结构化、非结构化为主,传统的数据库方案没法很好的解决解析、存储等问题。ES 支持 JSON 且支持动态映射,高版本还支持 Runtime Feilds,能在查询时动态提取字段,天然支持了日志场景复杂、灵活的数据结构。
日志数据进入 ES 则面临高并发、高吞吐的写入性能挑战。内核层面我们进行了定向路由、物理复制等重磅优化,有效解决日志入口吞吐瓶颈,提升写入性能一倍+。
日志数据的存储是另一大挑战,日志往往是海量的且往往价值不高,存储成本成为用户最顾虑的痛点之一。腾讯云 ES 一方面通过压缩编码优化来降低单位文档存储成本,另一方面我们通过基于云原生环境自研混合存储方案,实现存储与计算分离,降低存储成本 50% 以上。
日志数据的出口,查询性能也是一大挑战,海量数据场景下,大查询对资源的开销非常高,带来的查询延时也非常明显。ES 原生支持了倒排索引,点查过滤的性能非常好,但无法满足日志场景大范围查询、聚合分析等性能需求。对此,腾讯云 ES 进行了查询裁剪、查询并行化等一系列系统性优化,提升查询性能数十倍。
下面是日志领域的挑战总结,后面将针对高吞吐写入、低成本存储、高性能查询层面的优化进行详细分析。
日志领域的挑战3. 高吞吐写入
压缩编码优化压缩编码优化是在原始数据结构不变的前提下,降低单位文档存储成本非常有效的方式。上图中描述了 ES 底层 Lucene 的存储格式,以及这些格式所用到的压缩算法。其中列存压缩是由腾讯贡献给社区的。
4.1.1 列存压缩
列存压缩Lucene 列存存储分为两部分,term dictionary 和 term ords,每个字段值的原始内容存储在 term dictionary 中,实际编码、计算的时候为了避免冗余而采用 term ords,后者会随着新数据的持续写入而动态更新。优化的主要内容是对 term dictionary 中的原始字段字面内容进行压缩存储。从优化后的压缩效果对比来看,写入、merge 耗时基本不变的情况下,列存存储下降了 40%+。
4.1.2 扩展基础压缩算法
ES 有高效的倒排索引,点查的性能是非常强悍的。多索引或通过别名关联索引查询也是相对传统数据库的一个优势特性,而这一特性也会带来一些性能瓶颈问题。如上图所示,当我们查询的索引是一个星号,或者一个索引前缀匹配,或是一个别名的时候,底层可能关联多个物理索引,而我们的查询可能只有部分索引会有数据命中。而 ES 实际执行查询会将底层所有匹配的索引、包括每个索引底层的每个分片逐一遍历查询。这样会存在大量的无用索引、分片、segment 的查询空转扫描。
5.1.2 Segment 串行化执行
ES 底层分片之间是可以并行化的,但是单个分片内部多个 segment 之间是串行化的。混合存储引擎的底层是对象存储,多个 segment 串行化导致 IO 排队严重,查询效率低下,尤其是在大查询拉取数据较多的场景下。
5.2 索引分片级时序裁剪优化