写在最前

prometheus断定高基数的三种办法

  1. prometheus tsdb的统计接口
  2. prometheus 能够依据query_log中的queryPreparationTime来定位
  3. prometheus 通过count by 统计

什么是高基数 high-cardinality

基数狭义上是指汇合中值的数量

在数据库畛域,基数是指数据库的特定列或字段中蕴含的惟一值的数量。

工夫序列数据集的基数通常由每个独自的索引列的基数的叉积定义

高基数示例:工业物联网

  • 设想一下一个IoT场景,其中某个采石场中有大量的重型设施在开采岩石,破碎岩石和分选岩石。
  • 假如有10,000件设施,每个设施带有100个传感器,运行10个不同的固件版本,散布在100个站点中:
timestamp  | temper | mem_f | equipm | senso | firmwar   | sit  | (lat,long)           | ature  | ree   | ent_id | r_id  | e_version | e_id |--------------------+-------+--------+-------------------+------+-----------2019-04-04 | 85.2   | 10.2  | 1      | 98    |  1.0      | 4    | (x,y) 09:00:00   |        |       |        |       |           |      | 2019-04-04 | 68.8   | 16.0  | 72     | 12    |  1.1      | 20   | (x1,y1)09:00:00   |        |       |        |       |           |      |     2019-04-04 | 100.0  | 0.0   | 34     | 58    |  2.1      | 55   | (x2,y2) 09:00:00   |        |       |        |       |           |      |      2019-04-04 | 84.8   | 9.8   | 12     | 75    |  1.4      | 81   | (x3,y3)09:00:00   |        |       |        |       |           |      |   2019-04-04 | 68.7   | 16.0  | 89     | 4     |  2.1      | 13   | (x4,y4)09:00:00   |        |       |        |       |           |      | ...        |        |       |        |       |           |      |       
  • 而后,此数据集的最大基数变为10亿[10,000 x 100 x 10 x 100]。
  • 当初,假如设施也能够挪动,并且咱们想存储准确的GPS地位(纬度,经度),并将其用作索引的元数据进行查问。因为(lat,long)是一个间断字段(与诸如equipment_id之类的离散字段绝对),所以通过在地位上建设索引,此数据集的最大基数当初无限大(无界)。

高基数查问

  • 艰深的说就是返回的series或者查问到的series数量过多
  • 查问体现进去返回工夫较长,对应调用服务端资源较多的查问
  • 数量多少算多 10w~100w
  • 个别咱们定义在1小时内的range_query 响应工夫超过3秒则认为较重了

prometheus断定高基数的三种办法

  1. prometheus tsdb的统计接口
  2. prometheus 能够依据query_log中的queryPreparationTime来定位
  3. prometheus 通过count by 统计

办法一 tsdb的统计接口

  • http://192.168.43.114:9090/ts...
  • 接口地址 /api/v1/status/tsdb
  • 是基于内存中的倒排索引 算最大堆取 top10
  • 10个最多的metric_name排序

    seriesCountByMetricName: [{name: "namedprocess_namegroup_memory_bytes", value: 245},…]0: {name: "namedprocess_namegroup_memory_bytes", value: 245}1: {name: "namedprocess_namegroup_states", value: 245}2: {name: "mysql_global_status_commands_total", value: 148}3: {name: "namedprocess_namegroup_context_switches_total", value: 98}4: {name: "namedprocess_namegroup_cpu_seconds_total", value: 98}5: {name: "node_scrape_collector_success", value: 80}6: {name: "node_scrape_collector_duration_seconds", value: 80}7: {name: "namedprocess_namegroup_threads_wchan", value: 73}8: {name: "namedprocess_namegroup_thread_cpu_seconds_total", value: 66}9: {name: "namedprocess_namegroup_thread_io_bytes_total", value: 66}
  • 思考采集器如果不是prometheus怎么办?

    • 比方m3db没有提供高基数查问的接口
  • 源码解析

    // Stats calculates the cardinality statistics from postings.func (p *MemPostings) Stats(label string) *PostingsStats {  const maxNumOfRecords = 10  var size uint64  p.mtx.RLock()  metrics := &maxHeap{}  labels := &maxHeap{}  labelValueLength := &maxHeap{}  labelValuePairs := &maxHeap{}  numLabelPairs := 0  metrics.init(maxNumOfRecords)  labels.init(maxNumOfRecords)  labelValueLength.init(maxNumOfRecords)  labelValuePairs.init(maxNumOfRecords)  for n, e := range p.m {      if n == "" {          continue      }      labels.push(Stat{Name: n, Count: uint64(len(e))})      numLabelPairs += len(e)      size = 0      for name, values := range e {          if n == label {              metrics.push(Stat{Name: name, Count: uint64(len(values))})          }          labelValuePairs.push(Stat{Name: n + "=" + name, Count: uint64(len(values))})          size += uint64(len(name))      }      labelValueLength.push(Stat{Name: n, Count: size})  }  p.mtx.RUnlock()  return &PostingsStats{      CardinalityMetricsStats: metrics.get(),      CardinalityLabelStats:   labels.get(),      LabelValueStats:         labelValueLength.get(),      LabelValuePairsStats:    labelValuePairs.get(),      NumLabelPairs:           numLabelPairs,  }}

办法二 query_log

  • 能够依据log中的queryPreparationTime来定位

办法三 通过count统计

topk(5,count({__name__=~".+"}) by(__name__) > 100 )
  • scrape_samples_scraped 能够阐明job的instance维度sample数量,也可能定位