基于ELK的数据分析实践——满满的干货送给你

很多人刚刚接触ELK都不知道如何使用它们来做分析,经常会碰到下面的问题:

  • 安装完ELK不知从哪下手
  • 拿到数据样本不知道怎么分解数据
  • 导入到elasticsearch中奇怪为什么搜不出来
  • 搜到结果后,不知道它还能干什么

本篇就以一个完整的流程介绍下,数据从 读取-->分析-->检索-->应用 的全流程处理。在阅读本篇之前,需要先安装ELK,可以参考之前整理安装文档:ELK5.0部署教程

在利用ELK做数据分析时,大致为下面的流程:

  • 1 基于logstash分解字段
  • 2 基于字段创建Mapping
  • 3 查看分词结果
  • 4 检索
  • 5 聚合
  • 6 高亮

可能会根据第4步重复第2步的工作,调整分词等规则。

为了便于理解,先说一下本文的业务背景:

我需要统计一个url对应的pv和uv,这个url需要支持全文检索。每天同一个url都会产生一条数据。最后会按照特定的日期范围对数据进行聚合。

下面就开始数据分析之路吧~

基于logstash分解字段

在使用logstash前,需要对它有一定的了解。logstash的组件其实很简单,主要包括input、filter、output、codec四个部分。

  • input 用于读取内容,常用的有stdin(直接从控制台输入)、file(读取文件)等,另外还提供了对接redis、kafka等的插件
  • filter 用于对输入的文本进行处理,常用的有grok(基于正则表达式提取字段)、kv(解析键值对形式的数据)、csv、xml等,另外还提供了了一个ruby插件,这个插件如果会用的话,几乎是万能的。
  • output 用于把fitler得到的内容输出到指定的接收端,常用的自然是elasticsearch(对接ES)、file(输出到文件)、stdout(直接输出到控制台)
  • codec 它用于格式化对应的内容,可以再Input和output插件中使用,比如在output的stdout中使用rubydebug以json的形式输出到控制台

理解上面的内容后,再看看logstash的使用方法。

首先需要定义一个配置文件,配置文件中配置了对应的input,filter,output等,至少是一个input,output。

如我的配置文件:

input {
    file {
        path => "C:\Users\Documents\workspace\elk\page.csv"
        start_position => "beginning"
    }
}
filter {
    grok {
        match => {
            "message" => "%{NOTSPACE:url}\s*%{NOTSPACE:date}\s*%{NOTSPACE:pvs}\s*%{NOTSPACE:uvs}\s*%{NOTSPACE:ips}\s*%{NOTSPACE:mems}\s*%{NOTSPACE:new_guests}\s*%{NOTSPACE:quits}\s*%{NOTSPACE:outs}\s*%{NOTSPACE:stay_time}"
        }
    }
}
output {
    stdout{codec => dots}
    elasticsearch {
        document_type => "test"
        index => "page"
        hosts => ["1.1.1.1:9200"]
    }
}

上面的配置最不容易理解的就是Grok,其实它就是个正则表达式而已,你可以把它理解成是一段正则表达式的占位。至于grok都有哪些关键字,这些关键字对应的正则都是什么,可以直接参考logstash的源码,目录的位置为:

logstash-5.2.2\vendor\bundle\jruby\1.9\gems\logstash-patterns-core-4.0.2\patterns

如果提供的话,可以直接在grokdebug上面进行测试:

另外一个技巧就是,如果开启stdout并且codec为rubydebug,会把数据输出到控制台,因此使用.代替,即可省略输出,又能检测到现在是否有数据正在处理。而且每个.是一个字符,如果把它输出到文件,也可以直接通过文件的大小,判断处理了多少条。

这样,数据的预处理做完了.....

基于字段创建Mapping

虽然说Es是一个文档数据库,但是它也是有模式的概念的。文档中的每个字段仍然需要定义字段的类型,使用者经常会遇到明明是数字,在kibana却做不了加法;或者明明是IP,kibana里面却不认识。这都是因为Mapping有问题导致的。

在Elasticsearch中其实是有动态映射这个概念的,在字段第一次出现时,ES会自动检测你的字段是否属于数字或者日期或者IP,如果满足它预定义的格式,就按照特殊格式存储。一旦格式设置过了,之后的数据都会按照这种格式存储。举个例子,第一条数据进入ES时,字段检测为数值型;第二条进来的时候,却是一个字符串,结果可能插不进去,也可能插进去读不出来(不同版本处理的方式不同)。

因此,我们需要事先就设定一下字段的Mapping,这样之后使用的时候才不会困惑。

另外,Mapping里面不仅仅有字段的类型,还有这个字段的分词方式,比如使用标准standard分词器,还是中文分词器,或者是自定义的分词器,这个也是很关键的一个概念,稍后再讲。

创建Mapping有两种方式:

第一种,直接创建索引并创建映射

创建索引时,可以直接指定它的配置和Mapping:

PUT index_name
{
    "settings" : {
        "number_of_shards" : 1
    },
    "mappings" : {
        "type_name" : {
            "properties" : {
                "field_name" : { "type" : "text" }
            }
        }
    }
}

第二种,先创建索引,再创建映射

# 先创建索引
PUT index_name
{}

# 然后创建Mapping
PUT /index_name/_mapping/type_name
{
  "properties": {
    "ip": {
      "type": "ip"
    }
  }
}

# 最后查询创建的Mapping
GET /index_name/_mapping/type_name

比如我们上面的URL场景,可以这么建立索引:

PUT  url/_mapping/test
{
  "properties": {
    "url": {
      "type": "string",
      "fields": {
            "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
    },
    "date": {
      "type": "date"
    },
    "pvs": {
      "type": "integer"
    },
    "uvs": {
      "type": "integer"
    }
  }
}

PS,在上面的例子中,url需要有两个用途,一个是作为聚合的字段;另一个是需要做全文检索。在ES中全文检索的字段是不能用来做聚合的,因此使用嵌套字段的方式,新增一个url.keyword字段,这个字段设置成keyword类型,不采用任何分词(这是5.0的新特性,如果使用以前版本,可以直接设置string对应的index属性即可);然后本身的url字段则采用默认的标准分词器进行分词。

这样,以后在搜索的时候可以直接以query string的方式检索url,聚合的时候则可以直接使用url.keyword

查看分词结果

如果字段为https://www.elastic.co/guide/en/elasticsearch/reference/5.2,使用standard标准分词器,输入elastic却收不到任何结果,是不是有点怀疑人生。

我们做个小例子,首先创建一个空的索引:

PUT test1/test1/1
{
  "text":"https://www.elastic.co/guide/en/elasticsearch/reference/5.2"
}

然后查询这个字段被分解成了什么鬼?

GET /test1/test1/1/_termvectors?fields=text

得到的内容如下:

{
  "_index": "test1",
  "_type": "test1",
  "_id": "1",
  "_version": 1,
  "found": true,
  "took": 1,
  "term_vectors": {
    "text": {
      "field_statistics": {
        "sum_doc_freq": 7,
        "doc_count": 1,
        "sum_ttf": 7
      },
      "terms": {
        "5.2": {
          "term_freq": 1,
          "tokens": [
            {
              "position": 6,
              "start_offset": 56,
              "end_offset": 59
            }
          ]
        },
        "elasticsearch": {
          "term_freq": 1,
          "tokens": [
            {
              "position": 4,
              "start_offset": 32,
              "end_offset": 45
            }
          ]
        },
        "en": {
          "term_freq": 1,
          "tokens": [
            {
              "position": 3,
              "start_offset": 29,
              "end_offset": 31
            }
          ]
        },
        "guide": {
          "term_freq": 1,
          "tokens": [
            {
              "position": 2,
              "start_offset": 23,
              "end_offset": 28
            }
          ]
        },
        "https": {
          "term_freq": 1,
          "tokens": [
            {
              "position": 0,
              "start_offset": 0,
              "end_offset": 5
            }
          ]
        },
        "reference": {
          "term_freq": 1,
          "tokens": [
            {
              "position": 5,
              "start_offset": 46,
              "end_offset": 55
            }
          ]
        },
        "www.elastic.co": {
          "term_freq": 1,
          "tokens": [
            {
              "position": 1,
              "start_offset": 8,
              "end_offset": 22
            }
          ]
        }
      }
    }
  }
}

看到了吧,没有elastic这个词,自然是搜不出来的。如果你不理解这句话,回头看看倒排索引的原理吧!或者看看我的这篇文章:分词器的作用

那么你可能很郁闷,我就是要搜elastic怎么办!没关系,换个分词器就行了~比如elasticsearch为我们提供的simple分词器,就可以简单的按照符号进行切分:

POST _analyze
{
  "analyzer": "simple",
  "text": "https://www.elastic.co/guide/en/elasticsearch/reference/5.2"
}

得到的结果为:

{
  "tokens": [
    {
      "token": "https",
      "start_offset": 0,
      "end_offset": 5,
      "type": "word",
      "position": 0
    },
    {
      "token": "www",
      "start_offset": 8,
      "end_offset": 11,
      "type": "word",
      "position": 1
    },
    {
      "token": "elastic",
      "start_offset": 12,
      "end_offset": 19,
      "type": "word",
      "position": 2
    },
    {
      "token": "co",
      "start_offset": 20,
      "end_offset": 22,
      "type": "word",
      "position": 3
    },
    {
      "token": "guide",
      "start_offset": 23,
      "end_offset": 28,
      "type": "word",
      "position": 4
    },
    {
      "token": "en",
      "start_offset": 29,
      "end_offset": 31,
      "type": "word",
      "position": 5
    },
    {
      "token": "elasticsearch",
      "start_offset": 32,
      "end_offset": 45,
      "type": "word",
      "position": 6
    },
    {
      "token": "reference",
      "start_offset": 46,
      "end_offset": 55,
      "type": "word",
      "position": 7
    }
  ]
}

这样你就可以搜索elastic了,但是前提是需要在Mapping里面为该字段指定使用simple分词器,方法为:

PUT  url/_mapping/test
{
  "properties": {
    "url": {
      "type": "string",
      "analyzer": "simple",
      "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
    },
    "date": {
      "type": "date"
    },
    "pvs": {
      "type": "integer"
    },
    "uvs": {
      "type": "integer"
    }
}

修改Mapping前,需要先删除索引,然后重建索引。删除索引的命令为:

DELETE url

不想删除索引,只想改变Mapping?想得美....你当ES是孙悟空会72变?不过,你可以创建一个新的索引,然后把旧索引的数据导入到新索引就行了,这也不失为一种办法。如果想这么搞,可以参考reindex api,如果版本是5.0之前,那么你倒霉了!自己搞定吧!

检索

ES里面检索是一个最基础的功能了,很多人其实这个都是一知半解。由于内容太多,我就结合Kibana讲讲其中的一小部分吧。

很多人安装完kibana之后,登陆后不知道该干啥。如果你的elasticsearch里面已经有数据了,那么此时你需要在Kiban新建对应的索引。

如果你的es的索引是name-2017-03-19,name-2017-03-20这种名字+时间后缀的,那么可以勾选1位置的选项,它会自动聚合这些索引。这样在这一个索引中就可以查询多个索引的数据了,其实他是利用了索引的模式匹配的特性。如果你的索引仅仅是一个简单的名字,那么可以不勾选1位置的选项,直接输入名字,即可。

然后进入Kibana的首页,在输入框里面就可以任意输入关键字进行查询了。

查询的词,需要是上面_termvectors分析出来的词,差一个字母都不行!!!!!

这个搜索框其实就是elasticsearch中的query string,因此所有的lucene查询语法都是支持的!

如果想要了解更多的查询语法,也可以参考我之前整理的文章,Lucene查询语法

另外,这个输入框,其实也可以输入ES的DSL查询语法,只不过写法过于蛋疼,就不推荐了。

自定义查询语法

如果不使用kibana,想在自己的程序里面访问es操作,也可以直接以rest api的方式查询。

比如查询某个索引的全部内容,默认返回10个:

GET /page/test/_search?pretty

再比如,增加一个特殊点的查询:

GET /page/test/_search?pretty
{
  "query": {
    "query_string" : {
      "default_field" : "url",
      "query" : "颜色"
    }
  },
  "size": 10,
}

聚合

在es中一个很重要的亮点,就是支持很多的聚合语法,如果没有它,我想很多人会直接使用lucene吧。在ES中的聚合,大体上可以为两类聚合方法,metric和bucket。metic可以理解成avg、sum、count、max、min,bucket可以理解为group by 。有了这两种聚合方法,就可以对ES中的数据做很多处理了。

比如在kibana中,做一个最简单的饼图:

其实它在后台发送的请求,就是这个样子的:

{
  "size": 0,
  "query": {
    "query_string": {
      "query": "颜色",
      "analyze_wildcard": true
    }
  },
  "_source": {
    "excludes": []
  },
  "aggs": {
    "2": {
      "terms": {
        "field": "url.keyword",
        "size": 5,
        "order": {
          "_count": "desc"
        }
      }
    }
  }
}

如果不适用kibana,自己定义聚合请求,那么可以这样写:

GET /page/test/_search?pretty
{
  "query": {
    "query_string" : {
      "default_field" : "url",
      "query" : "颜色"
    }
  },
  "size": 0,
    "aggs" : {
      "agg1" : {
        "terms" : {
          "field" : "url.keyword",
          "size" : 10
        },
        "aggs" : {
          "pvs" : { "sum" : { "field" : "pvs" } },
          "uvs" : { "sum" : { "field" : "uvs" } }
      }
    }
  }
}

另外,聚合也支持嵌套聚合,就是跟terms或者sum等agg并列写一个新的aggs对象就行。

高亮

如果是自己使用elasticsearch,高亮也是一个非常重要的内容,它可以帮助最后的使用者快速了解搜索的结果。

后台的原理,是利用ES提供的highlight API,针对搜索的关键字,返回对应的字段。该字段中包含了一个自定义的标签,前端可以基于这个标签高亮着色。

举个简单的例子:

GET /_search
{
    "query" : {
        "match": { "content": "kimchy" }
    },
    "highlight" : {
        "fields" : {
            "content" : {}
        }
    }
}

上面的请求会针对content字段搜索kimchy。并且返回对应的字段,比如原来的字段内容时hello kimchy,经过高亮后,会再搜索结果的hits中返回:

{
  "took": 3,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 30,
    "max_score": 13.945707,
    "hits": [
      {
        "_index": "page",
        "_type": "test",
        "_id": "AVrvHh_kvobeDQC6Q5Sg",
        "_score": 13.945707,
        "_source": {
          "date": "2016-03-14",
          "pvs": "3",
          "url": "hello kimchy",
          "@timestamp": "2017-03-21T04:29:07.187Z",
          "uvs": "1",
          "@version": "1"
        },
        "highlight": {
          "url": [
            "hello <em>kimchy</em>"
          ]
        }
      }
    ]
  }
}

这样就可以直接利用highlight中的字段做前端的显示了。

另外,上面的<em>标签可以自定义,比如:

GET /_search
{
    "query" : {
        "match": { "user": "kimchy" }
    },
    "highlight" : {
        "pre_tags" : ["<tag1>"],
        "post_tags" : ["</tag1>"],
        "fields" : {
            "_all" : {}
        }
    }
}

经过上面的一步一步的探索,你应该了解ELK的数据分析的流程与技巧了吧!如果有任何问题,也可以直接留言,可以再交流!

本文转自博客园xingoo的博客,原文链接:基于ELK的数据分析实践——满满的干货送给你,如需转载请自行联系原博主。

时间: 2024-10-09 06:42:34

基于ELK的数据分析实践——满满的干货送给你的相关文章

麻袋理财基于Docker的容器实践:互联网金融征信项目的微服务化之旅

FinTech第一期 征信是互联网金融的核心系统之一,在单体应用到服务化改造中,定义了API Gateway,Scheduler Service,Data Processing Service,Cache Service和Worker Service等服务,并实现了对基于Docker的微服务化. 本次分享的主题是<麻袋理财基于Docker的容器实践>--              征信要做的事情就是从内部外部获取数据,以此对用户的还款意愿进行甄别. 现在市场上也有很多第三方的征信公司,每家征信

DockOne微信分享(七十八):中英人寿保险有限公司基于容器技术的实践分享

本文讲的是DockOne微信分享(七十八):中英人寿保险有限公司基于容器技术的实践分享[编者的话] 中英人寿在移动应用开发与运维上引入DevOps,极大的提升了开发效率,进而实现持续交付能力.持续交付让移动应用上线的速度从以月为单位提升到周甚至到天. 通过在企业云上使用(Docker.Git.Jenkins etc)搭建自动化部署流水线, 使软件的构建.测试.部署的过程自动化实现.随着IT架构向云架构的转型,在架构级管理工具上采用虚拟化容器管理,实现从IaaS到PaaS的转变.对移动应用系统进行

BigInsights:解读IBM基于Hadoop的数据分析平台

毫无疑问,大数据成了2012年的热门词.根据国外统计机构的报告,大数据处理在今年的市场规模已经达到700亿美元并且正以每年15-20%的速度增长.几乎所有主要的大科技公司都对大数据感兴趣,对该领域的产品及服务进行了大量投入.其中包括了IBM.Oracel.EMC.HP.Dell.SGI.日立.Yahoo等,而且这个列表还在继续. IBM也在2011年中旬对外发布了针对大数据处理和分析技术:在SmartCloud平台上新增基于Apache Hadoop的服务InfoSphere BigInsigh

微信正式上线“微信指数”,基于微信大数据分析的移动端指数

昨日,微信正式上线"微信指数",这是微信官方提供的基于微信大数据分析的移动端指数.在移动互联网时代,社交数据越来越重要.热点,往往不仅只有一个人群在关注.作为一款月活跃用户达8.89亿的应用,微信已经成为人们日常生活中必不可少的工具."喜欢财经还是八卦""讨论买房还是卖房""爱好男还是爱好女","这段时间萨德如何了",每个人都有自己不同的偏好和习惯.你可能经常看到某个事件在"刷屏",但没

满满的干货 云计算平台构建与实践论坛纪实

ZD至顶网服务器频道 05月25日 新闻消息(文/于泽):2016年5月18日-20日,主题为"技术融合 应用创新"的第八届中国云计算大会在北京国家会议中心隆重召开.中国云计算大会迄今为止已有八年历史,是中国最大规模.最具影响力的年度云计算技术.产业.应用盛会.中国云计算大会由工业和信息化部.中国科学技术协会.北京市人民政府指导,中国电子学会主办,世界工程组织联合会创新专委会(WFEO-CEIT)协办,中国云计算技术与产业联盟.中国电子学会云计算专家委员会.中国大数据专家委员会承办,Z

阿里聚安全企业沙龙开启第一站——上海!满满的干货!

5月份的上海阴雨绵绵,基本每天都在下雨,小编还一直担心因为天气原因会影响小伙伴来现场参会,结果就在开会的当天上午报名人数还在不断增加!几十人的场地瞬间让小编变大.变大.再变大! 阿里巴巴5位大拿的精彩分享 阿里聚安全负责人习林介绍了以业务为中心的聚安全解决方案.站在业务的角度看,我们把一系列的问题划分成八个层次,每一层都有它代表性的核心安全问题.在面向这些八个层次的安全问题时,聚安全提供全链路的防护体系,基于大数据风险引擎,以它为中心,能够利用各个层次的安全能力去发现各种风险然后会聚起来.会聚之

企业大数据分析实践指南、总结与展望

数据无处不在 在我们身处的时代,数据无处不在.据IBM公司估算,我们每天产生约2.5万ZB的数据,这意味着世界上90%数据都是过去的两年中产生的. Gartner公司分析报告显示,在2015年财富500强的公司中百分之八十五的企业无法利用大数据来获取竞争优势. 到2020年,全世界将有上百万大数据相关的就业机会产生.这些庞大的数据蕴藏了宝贵财富,企业可以使用最先进的分析技术,利用这些数据更好地了解客户的行为,识别商业机会,制定运营战略. 让我们举几个例子: 金融机构每天通过信用评分模型,了解他们

企业大数据分析实践指南

数据无处不在 在我们身处的时代,数据无处不在.据IBM公司估算,人类每天产生约2.5万ZB的数据,这意味着世界上90%数据都是过去的两年中产生的.Gartner公司分析报告显示,在2015年财富500强的公司中百分之八十五的企业无法利用大数据来获取竞争优势. 到2020年,全世界将有上百万大数据相关的就业机会产生.这些庞大的数据蕴藏了宝贵财富,企业可以使用最先进的分析技术,利用这些数据更好地了解客户的行为,识别商业机会,制定运营战略. 让我们举几个例子,金融机构每天通过信用评分模型,了解他们的客

云上游戏数据分析实践

作者:上海驻云高级架构师 李俊涛 从游戏发展的角度来看,不管是端游.页游,还是现在发展迅猛的手游,其生命周期与盈利情况都与数据分析能力息息相关.同时数据分析对游戏的运维也起到了至关重要的作用.精确的数据分析有助于在做游戏运营时推出合理的新手引导,在及时的渠道推广和丰富的消费场景设计,这些将极大地影响游戏玩家对游戏的关注度,从而延长游戏的生命周期,并从中更好盈利.        游戏数据分析特点        分析是建立在数据上的,数据的特点决定了分析的方向和方法.游戏数据的特点主要表现在以下四个