ElasticSearch Rollup的那些事

近期,突然要做一个大量数据聚合的任务,由于原始数据在ES里面,所以针对ElasticSearch的聚合能力进行了一个研究,里面有些比较好玩的内容,这里分享给大家

ElasticSearch的聚合任务

由于是多个对大量表进行聚合的任务,且耗时长,数据量大,用传统的方法:

ElasticSearch查询后,再写入,需要进行两次IO,所以优先看看ES自己有没有这样的能力

看了一下果然有,叫rollup,看名字就是可以聚合

这里把网上的资料整理下:

这要分为两个方法,一个是用语句创建,一个是用kibana的IDE创建

先看第一种

语句创建

参考:通过RollUp实现流量汇总最佳实践 - 检索分析服务Elasticsearch版 - 阿里云

前提条件 

  • 确保您已拥有manage或manage_rollup权限。

    使用RollUp必须要有manage或manage_rollup权限,详情请参见Security Privileges

背景信息

本文的需求场景如下:

  • 每15分钟定时汇总整小时内instanceId的networkoutTraffic、networkinTraffic流量。
  • 通过Kibana大图展示指定instanceId的入口流量和出口流量。

本文以monitordata-logstash-sls-*为前缀的索引为例,该索引以每天创建一个索引的规则切分索引。索引的Mapping格式如下。

"monitordata-logstash-sls-2020-04-05" : {
    "mappings" : {
      "properties" : {
        "@timestamp" : {
          "type" : "date"
        },
        "__source__" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "disk_type" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "host" : {
          "type" : "keyword"
        },
        "instanceId" : {
          "type" : "keyword"
        },
        "metricName" : {
          "type" : "keyword"
        },
        "monitor_type" : {
          "type" : "keyword"
        },
        "networkinTraffic" : {
          "type" : "double"
        },
        "networkoutTraffic" : {
          "type" : "double"
        },
        "node_spec" : {
          "type" : "keyword"
        },
        "node_stats_node_master" : {
          "type" : "keyword"
        },
        "resource_uid" : {
          "type" : "keyword"
        }
      }
    }
  }
}

操作流程

  1. 步骤一:创建RollUp作业
  2. 步骤二:启动RollUp作业并查看作业信息
  3. 步骤三:查询汇总索引的数据
  4. 步骤四:创建Rollup索引模式
  5. 步骤五:创建Kibana流量监控大图
  6. 步骤六:创建Kibana流量监控仪表板

步骤一:创建RollUp作业

RollUp作业配置包含该作业如何运行、何时索引文档及将来对汇总索引执行哪些查询的详情信息。以下示例通过PUT _rollup/job命令定义1小时内汇总的作业。

PUT _rollup/job/ls-monitordata-sls-1h-job1
{
    "index_pattern": "monitordata-logstash-sls-*",
    "rollup_index": "monitordata-logstash-rollup-1h-1",
    "cron": "0 */15 * * * ?",
    "page_size" :1000,
    "groups" : {
      "date_histogram": {
        "field": "@timestamp",
        "fixed_interval": "1h"
      },
      "terms": {
        "fields": ["instanceId"]
      }
    },
    "metrics": [
        {
            "field": "networkoutTraffic",
            "metrics": ["sum"]
        },
        {
            "field": "networkinTraffic",
            "metrics": ["sum"]
        }
    ]
}
参数 是否必选 类型 说明
index_pattern string 汇总的索引或索引模式。支持通配符(*)。
rollup_index string 汇总结果的索引。不支持通配符,必须是一个完整的名称。
cron string 执行汇总作业任务的时间间隔。与汇总数据的时间间隔无关。
page_size integer 汇总索引每次迭代中处理的存储桶的结果数。值越大,执行越快,但是处理过程中需要更多的内存。
groups object 为汇总作业定义分组字段和聚合。
 date_histogram object 将date字段汇总到基于时间的存储桶中。
field string 需要汇总的date字段。
fixed_interval time units 数据汇总的时间间隔。例如设置为1h,表示按照1小时汇总field指定的时间字段。该参数定义了数据能够聚合的最小时间间隔。
terms object 无。
fields string 定义terms字段集。此数组字段可以是keyword也可以是numerics类型,无顺序要求。
metrics object 无。
field string 定义需要采集的指标的字段。例如以上示例是分别对networkoutTraffic、networkinTraffic进行采集。
metrics array 定义聚合算子。设置为sum,表示对networkinTraffic进行sum运算。仅支持min、max、sum、average、value count。
  • index_pattern中指定通配符时,请确保不会匹配到rollup_index指定的汇总索引名,否则报错。
  • 由于汇总索引的Mapping是object类型,请确保集群中不存在与汇总索引相匹配的索引模板,否则报错。
  • 字段分组聚合仅支持Date Histogram aggregation、Histogram aggregation、Terms aggregation,详细限制说明请参见Rollup aggregation limitations

步骤二:启动RollUp作业并查看作业信息

  1. 启动RollUp作业。
    POST _rollup/job/ls-monitordata-sls-1h-job1/_start
  2. 查看RollUp作业的配置、统计和状态信息。
    GET _rollup/job/ls-monitordata-sls-1h-job1/

    更多详细说明请参见Get rollup jobs API

    执行成功后,返回如下结果。
    {
         ........
          "status" : {
            "job_state" : "indexing",
            "current_position" : {
              "@timestamp.date_histogram" : 1586775600000,
              "instanceId.terms" : "ls-cn-ddddez****"
            },
            "upgraded_doc_id" : true
          },
          "stats" : {
            "pages_processed" : 3,
            "documents_processed" : 11472500,
            "rollups_indexed" : 3000,
            "trigger_count" : 1,
            "index_time_in_ms" : 766,
            "index_total" : 3,
            "index_failures" : 0,
            "search_time_in_ms" : 68559,
            "search_total" : 3,
            "search_failures" : 0
          }
    }

步骤三:查询汇总索引的数据

在Rollup内部,由于汇总文档使用的文档结构和原始数据不同,Rollup查询端口会将标准查询DSL重写为与汇总文档匹配的格式,然后获取响应并将其重写回给原始查询的客户端所期望的格式。

  1. 使用match_all获取汇总索引的所有数据。
    GET monitordata-logstash-rollup-1h-1/_search
    {
      "query": {
        "match_all": {}
      }
    }
    • 查询仅能指定一个汇总索引,即不支持模糊匹配。对实时索引数据查询没有限制要求,查询可指定多个索引。
    • 查询仅支持Term、Terms、Range query、MatchAll query、Any compound query(Boolean、Boosting、ConstantScore等),更多限制请参见Rollup search limitations
  2. 使用_rollup_search聚合出口流量总数据。
    GET /monitordata-logstash-rollup-1h-1/_rollup_search
    {
        "size": 0,
        "aggregations": {
            "sum_temperature": {
                "sum": {
                    "field": "networkoutTraffic"
                }
            }
        }
    }
    _rollup_search支持常规的Search API特性子集:_rollup_search不可用功能包括:
    • query:指定DSL查询参数,但受一些限制,详情请参见Rollup search limitationsRollup aggregation limitations
    • aggregations:指定聚合参数。
    • size:由于汇总适用于聚合数据,无法返回查询结果,因此将size设置为0或者完全省略。
    • 不支持highlighter、suggestors、post_filter、profile、explain等参数

UI创建

参考:喬叔教 Elastic - 12 - 管理 Index 的 Best Practice (4/7) - Rollup - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天

建立Rollup Job

首先,进入Kibana > Stack Management 后,点选左侧Data 区块中的Rollup Jobs。

kibana rollup job

点Create rollup job 之后,会进入设定页面:

create rollup job 1

这边的设定基本上都蛮直觉的,依照旁边的说明设定即可。

  • Name:帮Rollup Job取个名字。
  • Data flow:指定Index pattern以及Rollup产生的Index名字。
  • Schedule:这个Rollup Job执行的频率。
  • Ho manay documents do you want to roll up at a time:执行时批次处理的大小,数字愈来处理速度愈快,但记忆体也耗的愈多。
  • How long should the rollup job wait before rolling up new data:在执行Rollup时,可以设定一个Latency执,这个Latency指的是资料在ingest进入ES时,有可能会有一些延迟,一但设了这个Latency, Rollup Job就会多等到Latency的时间过了之后,才会处理这部份的资料。

这边有个要注意的Index pattern不应该包含到Rollup index name,上图就是一个错误的例子,这样会造成处理逻辑上的错误,如果你设定了这样的配置,最终会看到以下这样的错误画面。

create rollup job error

接下来要分别设定Date histogram 的时间颗粒度:

create rollup job 2

设定有哪些栏位会使用到Term bucketing:

create rollup job 3

哪些栏位可能会进行Histogram 的aggregation:

create rollup job 4

哪些栏位会使用到Metrics,这边请依照资料的特性来判断,有些没必要的就不用勾选了。

create rollup job 5

最后Review 完没问题时,就可以直接建立。

create rollup job 6

查看Rollup Jobs

当建立完成后,在Rollup Jobs 的选单中可以看到我们建立的这个Job。

view rollup jobs

点开后也可以看到他的Stats,包含目前已经处理了多少Documents、Pages、以及执行过多少次。

image-20200927200414569

这时到Index Management 来查看Elasticsearch 中的Index,就可以看到由这个Rollup Job 所产生的Index 了。

记得要把上面Include rollup indices打勾,才会看得到。

rollup index

这时Rollup Job 产生的资料已经可以使用了。

而且我们可以看到,rollup-logstash-daily占用的是446mb的空间,比起整体logstash-1~logstash-10的总量,大约只占了1/10

不足

这里这么好用,那岂不是都可以用了?!

不是的!

仔细研究发现这个功能有几个比较大的不足:

实验性质的功能

1.从Elasticsearch6.4开始,这个功能作为试验性的功能开发,一直到目前即Elasticsearch7.14,依然是实验性质的,所以会有这么一段话:

这意味着,平时玩一下可以,但用在生产项目上就不好了,而且,一个实验室的项目这么多年没有转正,只是库的位置换了一下( 即从商业版的X-Pack组件包里变为REST组件,变成了免费用品),这里的风险比较大

无法复杂正则匹配index

下图可以看到,正则只能用*,不能用其他的内容,很多时候项目数据按天/周/月分索引,但聚合的数据并不是这样,比如按天分索引的数据想聚合成周数据,就不能支持了,只能先创建周表,把数据迁移过来,再进行聚合任务,这里比较坑。。。

不能预先筛选

这里非常的坑,比如我只要原始表中的网络状态为200的数据作为待聚合数据,这里不支持。。。

本来我看到下图:

以为新的版本可以支持筛选了

但仔细一看,居然是吐槽的内容,

再向下看:

官方接受了这个建议?

打开issue看下

好吧,好消息是官方确实重视这个问题了,并重新开放了问题

坏消息是官方的开发者表示目前没什么思路。。。

坐等吧 

ps:最后吐槽一下 

Elasticsearch 7.14这种先发文档不给安装包的操作确实有点。。。 

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=15mgfwpmnek25

猜你喜欢

转载自blog.csdn.net/killer1989/article/details/118916969