大规模时间序列索引 | Datadog

主要观点:

  • Datadog 每分钟收集数十亿事件,数据量增长迅速,查询类型也发生显著变化,给时间序列数据存储带来压力。
  • 介绍了 Datadog 时间序列数据库的架构,包括摄入、存储和查询三个主要组件。
  • 原有的索引服务基于自动生成索引,虽空间高效但对用户查询预测性差,常导致查询超时和用户体验不佳。
  • 下一代索引服务受搜索引擎倒排索引启发,简化了摄入和查询路径,减少了 CPU 消耗,但存在写放大和空间扩增问题。
  • 通过节点内分片提高了查询性能,将 Go 服务改为 Rust 后,CPU 密集型操作速度提高多达 6 倍,使查询性能大幅提升。

关键信息:

  • 架构组件:摄入通过 Kafka 接收数据并写入消息代理,存储分为短期指标存储层(包含时间序列数据库和时间序列索引服务),查询连接各个时间序列索引节点并组合结果。
  • 原索引服务:用 Go 实现,依赖 SQLite 和 RocksDB,根据查询日志自动生成索引,对程序式查询源有效但对用户查询效果不佳。
  • 下一代索引服务:设计更简单,依赖 RocksDB 且无条件索引每个摄入的标签,解决了原服务的一些问题,但有写放大和空间扩增问题,通过节点内分片和改用 Rust 提高性能。
  • 性能提升:在相同硬件上可查询 20 倍更高基数的指标,显著降低尾查询延迟,减少 99%的查询超时,使时间序列索引运行成本降低近 50%。

重要细节:

  • 摄入的数据点包含指标名、标签、时间戳和值,标签可用于过滤、聚合和比较。
  • 原索引服务中,Tagsets 数据库存储时间序列 ID 与标签的映射,Metrics 数据库存储每个指标的时间序列 ID 列表,Indexes 数据库存储资源消耗查询的索引。
  • 下一代索引服务中,索引数据库无条件索引每个摄入的标签,查询时通过单个键值查找获取相关时间序列 ID,然后根据查询进行集合操作。
  • 节点内分片将 RocksDB 索引分为多个隔离实例,根据哈希将时间序列分配到特定分片,并行获取数据并合并结果。
  • 在 Go 和 Rust 的性能对比中,Rust 在一些 CPU 密集型操作上表现更优,如分组和合并时间序列 ID 操作。
阅读 11
0 条评论