elasticsearch 桶聚合2.3.5 聚合无法起作用,求助

elasticsearch5.2.2安装elasticsearch-head-爱编程
elasticsearch5.2.2安装elasticsearch-head
1&下载:https://www.elastic.co/downloads/elasticsearch & 5.2.2
2&解压后直接启动 我是在windows上搞的,直接打开&elasticsearch.bat
PS:安装java jdk1.8, & &&1.7没试,应该跑不起来.
3:浏览器访问http://localhost:9200/看到以下信息就说明启动成功了
"name" : "HwBUKHJ",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "dYC7YLWBRDGmjidzlOIUwA",
"version" : {
"number" : "5.2.2",
"build_hash" : "f9d9b74",
"build_date" : "T17:26:45.835Z",
"build_snapshot" : false,
"lucene_version" : "6.4.1"
"tagline" : "You Know, for Search"
4&安装elasticsearch-head插件
这里需要注意下,之前的安装方式是 plugin -install xxx &5.2.2变成elasticsearch-plugin install XX
这个方法不能安装elasticsearch-head,需要作为一个单独的服务器启动
git clone git:///mobz/elasticsearch-head.git //下载
cd elasticsearch-head
npm install
npm install -g grunt-cli(安装过请忽略)
在elasticsearch-head目录下node_modules/grunt下如果没有grunt二进制程序,需要执行
cd elasticsearch-head
npm install grunt --save
grunt server
open http://localhost:9100/
浏览器可以看到head提供的页面,但是连接不上elasticsearch.需要在elasticsearch5.2.2的配置里增加一下参数
http.cors.enabled: true
http.cors.allow-origin: "*"
重启elasticsearch后,刷新elasticsearch-head的页面(http://localhost:9100/),发现链接正常了.
接下来分享下java操作elasticsearch
版权所有 爱编程 (C) Copyright 2012. . All Rights Reserved.
闽ICP备号-3
微信扫一扫关注爱编程,每天为您推送一篇经典技术文章。elasticsearch(4)
1、启动 elasticsearch 如出现异常
can not run elasticsearch as root
解决方法:创建elasticsearch 账户,修改文件夹 文件 所属用户 组
2、启动异常:ERROR: bootstrap checks failed
system call filte check the logs and fix your configuration or disable system call filters at your own risk
问题原因:因为Centos6不支持SecComp,而ES5.2.1默认bootstrap.system_call_filter为true进行检测,所以导致检测失败,失败后直接导致ES不能启动。详见 :
解决方法:在elasticsearch.yml中配置bootstrap.system_call_filter为false,注意要在Memory下面:
bootstrap.memory_lock: false
bootstrap.system_call_filter: false
3、启动后,如果只有本地可以访问,尝试修改配置文件 elasticsearch.yml
中network.host(注意配置文件格式不是以 # 开头的要空一格, : 后要空一格)
为 network.host: 0.0.0.0
默认端口是 9200
注意:关闭防火墙 或者开放9200端口
4、ERROR: bootstrap checks failed
max file descriptors [4096] for elasticsearch process likely too low, increase to at least [65536]
max number of threads [1024] for user [lishang] likely too low, increase to at least [2048]
解决方法:切换到root用户,编辑limits.conf 添加类似如下内容
vi /etc/security/limits.conf
添加如下内容:
soft nofile 65536
hard nofile 131072
soft nproc 2048
hard nproc 4096
5、max number of threads [1024] for user [lish] likely too low, increase to at least [2048]
解决:切换到root用户,进入limits.d目录下修改配置文件。
vi /etc/security/limits.d/90-nproc.conf
修改如下内容:
soft nproc 1024
soft nproc 2048
6、max virtual memory areas vm.max_map_count [65530] likely too low, increase to at least [262144]
解决:切换到root用户修改配置sysctl.conf
vi /etc/sysctl.conf
添加下面配置:
vm.max_map_count=655360
并执行命令:
然后,重新启动elasticsearch,即可启动成功。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:837次
排名:千里之外Elasticsearch(50)
聚合的测试数据(Aggregation Test-Drive)
我们将学习各种聚合以及它们的语法,但是最好的学习方法还是通过例子。一旦你了解了如何思考聚合以及如何对它们进行合适的嵌套,那么语法本身是不难的。
让我们从一个例子开始。我们会建立一个也许对汽车交易商有所用处的聚合。数据是关于汽车交易的:汽车型号,制造商,销售价格,销售时间以及一些其他的相关数据。
首先,通过批量索引(Bulk-Index)来添加一些数据:
POST /cars/transactions/_bulk
{ &index&: {}}
{ &price& : 10000, &color& : &red&, &make& : &honda&, &sold& : && }
{ &index&: {}}
{ &price& : 20000, &color& : &red&, &make& : &honda&, &sold& : && }
{ &index&: {}}
{ &price& : 30000, &color& : &green&, &make& : &ford&, &sold& : && }
{ &index&: {}}
{ &price& : 15000, &color& : &blue&, &make& : &toyota&, &sold& : && }
{ &index&: {}}
{ &price& : 12000, &color& : &green&, &make& : &toyota&, &sold& : && }
{ &index&: {}}
{ &price& : 20000, &color& : &red&, &make& : &honda&, &sold& : && }
{ &index&: {}}
{ &price& : 80000, &color& : &red&, &make& : &bmw&, &sold& : && }
{ &index&: {}}
{ &price& : 25000, &color& : &blue&, &make& : &ford&, &sold& : && }
现在我们有了一些数据,来创建一个聚合吧。一个汽车交易商也许希望知道哪种颜色的车卖的最好。这可以通过一个简单的聚合完成。使用terms桶:
GET /cars/transactions/_search?search_type=count
&aggs& : {
&colors& : {
&terms& : {
&field& : &color&
因为我们并不关心搜索结果,使用的search_type是count,它的速度更快。 聚合工作在顶层的aggs参数下(当然你也可以使用更长的aggregations)。 然后给这个聚合起了一个名字:colors。 最后,我们定义了一个terms类型的桶,它针对color字段。
聚合是以搜索结果为上下文而执行的,这意味着它是搜索请求(比如,使用/_search端点)中的另一个顶层参数(Top-level Parameter)。聚合可以和查询同时使用,这一点我们在后续的中介绍。
接下来我们为聚合起一个名字。命名规则是有你决定的; 聚合的响应会被该名字标记,因此在应用中你就能够根据名字来得到聚合结果,并对它们进行操作了。
然后,我们开始定义聚合本身。比如,我们定义了一个terms类型的桶。terms桶会动态地为每一个它遇到的不重复的词条创建一个新的桶。因为我们针对的是color字段,那么terms桶会动态地为每种颜色创建一个新桶。
让我们执行该聚合来看看其结果:
&hits&: []
&aggregations&: {
&colors&: {
&buckets&: [
&key&: &red&,
&doc_count&: 4
&key&: &blue&,
&doc_count&: 2
&key&: &green&,
&doc_count&: 2
因为我们使用的search_type为count,所以没有搜索结果被返回。 每个桶中的key对应的是在color字段中找到的不重复的词条。它同时也包含了一个doc_count,用来表示包含了该词条的文档数量。
响应包含了一个桶列表,每个桶都对应着一个不重复的颜色(比如,红色或者绿色)。每个桶也包含了“掉入”该桶中的文档数量。比如,有4辆红色的车。
前面的例子是完全实时(Real-Time)的:如果文档是可搜索的,那么它们就能够被聚合。这意味着你能够将拿到的聚合结果置入到一个图形库中来生成实时的仪表板(Dashboard)。一旦你卖出了一台银色汽车,在图形上关于银色汽车的统计数据就会被动态地更新。
瞧!你的第一个聚合!
添加一个指标(Metric)
从前面的例子中,我们可以知道每个桶中的文档数量。但是,通常我们的应用会需要基于那些文档的更加复杂的指标(Metric)。比如,每个桶中的汽车的平均价格是多少?
为了得到该信息,我们得告诉ES需要为哪些字段计算哪些指标。这需要将指标嵌套到桶中。指标会基于桶中的文档的值来计算相应的统计信息。
让我们添加一个计算平均值的指标:
GET /cars/transactions/_search?search_type=count
&colors&: {
&terms&: {
&field&: &color&
&avg_price&: {
&field&: &price&
我们添加了一个新的aggs层级来包含该指标。然后给该指标起了一个名字:avg_price。最后定义了该指标作用的字段为price。.
正如你所看到的,我们向前面的例子中添加了一个新的aggs层级。这个新的聚合层级能够让我们将avg指标嵌套在terms桶中。这意味着我们能为每种颜色都计算一个平均值。
同样的,我们需要给指标起一个名(avg_price)来让我们能够在将来得到其值。最后,我们指定了指标本身(avg)以及该指标作用的字段(price):
&aggregations&: {
&colors&: {
&buckets&: [
&key&: &red&,
&doc_count&: 4,
&avg_price&: {
&value&: 32500
&key&: &blue&,
&doc_count&: 2,
&avg_price&: {
&value&: 20000
&key&: &green&,
&doc_count&: 2,
&avg_price&: {
&value&: 21000
现在,在响应中多了一个avg_price元素。
尽管得到的响应只是稍稍有些变化,但是获得的数据增加的了许多。之前我们只知道有4辆红色汽车。现在我们知道了红色汽车的平均价格是32500刀。这些数据你可以直接插入到报表中。
桶中的桶(Buckets inside Buckets)
当你开始使用不同的嵌套模式时,聚合强大的能力才会显现出来。在前面的例子中,我们已经知道了如何将一个指标嵌套进一个桶的,它的功能已经十分强大了。
但是真正激动人心的分析功能来源于嵌套在其它桶中的桶。现在,让我们来看看如何找到每种颜色的汽车的制造商分布信息:
GET /cars/transactions/_search?search_type=count
&colors&: {
&terms&: {
&field&: &color&
&avg_price&: {
&field&: &price&
&terms&: {
&field&: &make&
此时发生了一些有意思的事情。首先,你会注意到前面的avg_price指标完全没有变化。一个聚合的每个层级都能够拥有多个指标或者桶。avg_price指标告诉了我们每种汽车颜色的平均价格。为每种颜色创建的桶和指标是各自独立的。
这个性质对你的应用而言是很重要的,因为你经常需要收集一些互相关联却又完全不同的指标。聚合能够让你对数据遍历一次就得到所有需要的信息。
另外一件重要的事情是添加了新聚合make,它是一个terms类型的桶(嵌套在名为colors的terms桶中)。这意味着我们会根据数据集创建不重复的(color, make)组合。
让我们来看看得到的响应(有省略,因为响应太长了):
&aggregations&: {
&colors&: {
&buckets&: [
&key&: &red&,
&doc_count&: 4,
&buckets&: [
&key&: &honda&,
&doc_count&: 3
&key&: &bmw&,
&doc_count&: 1
&avg_price&: {
&value&: 32500
该响应告诉了我们如下信息:
有4辆红色汽车。红色汽车的平均价格是32500美刀。红色汽车中的3辆是Honda,1辆是BMW。
最后的一个修改(One Final Modification)
在继续讨论新的话题前,为了把问题讲清楚让我们对该例子进行最后一个修改。为每个制造商添加两个指标来计算最低和最高价格:
GET /cars/transactions/_search?search_type=count
&colors&: {
&terms&: {
&field&: &color&
&avg_price&: { &avg&: { &field&: &price& }
&make& : {
&terms& : {
&field& : &make&
&aggs& : {
&min_price& : { &min&: { &field&: &price&} },
&max_price& : { &max&: { &field&: &price&} }
我们需要添加另一个aggs层级来进行对min和max的嵌套。
得到的响应如下(仍然有省略):
&aggregations&: {
&colors&: {
&buckets&: [
&key&: &red&,
&doc_count&: 4,
&buckets&: [
&key&: &honda&,
&doc_count&: 3,
&min_price&: {
&value&: 10000
&max_price&: {
&value&: 20000
&key&: &bmw&,
&doc_count&: 1,
&min_price&: {
&value&: 80000
&max_price&: {
&value&: 80000
&avg_price&: {
&value&: 32500
在每个make桶下,多了min和max的指标。
此时,我们可以得到如下信息:
有4辆红色汽车。红色汽车的平均价格是32500美刀。红色汽车中的3辆是Honda,1辆是BMW。红色Honda汽车中,最便宜的价格为10000美刀。最贵的红色Honda汽车为20000美刀。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:148449次
积分:3159
积分:3159
排名:第9544名
原创:147篇
转载:75篇
译文:16篇
评论:41条
文章:50篇
阅读:44046
(5)(7)(3)(3)(7)(5)(8)(21)(7)(8)(7)(3)(9)(9)(4)(4)(8)(12)(21)(10)(7)(25)(11)(12)(22)如果所有的数据都在一台机器上,那么生活会容易许多,CS201 课商教的经典算法就足够应付这些问题。但如果所有的数据都在一台机器上,那么就不需要像 Elasticsearch 这样的分布式软件了。不过一旦我们开始分布式数据存储,算法的选择就需务必小心。
elasticsearch版本: elasticsearch-2.x
如果所有的数据都在一台机器上,那么生活会容易许多,CS201 课商教的经典算法就足够应付这些问题。但如果所有的数据都在一台机器上,那么就不需要像 Elasticsearch 这样的分布式软件了。不过一旦我们开始分布式数据存储,算法的选择就需务必小心。
有些算法可以分布执行,到目前为止讨论过的所有聚合都是单次请求获得精确结果的。这些类型的算法通常是高度并行的,因为它们无须任何额外代价,就能在多台机器上并行执行。比如当计算 max 度量时,以下的算法就非常简单:
请求广播到所有分片。
查看每个文档的 price 字段。如果 price & current_max,将 current_max 替换成 price。
返回所有分片的最大 price 并传给协调节点。
找到从所有分片返回的最大 price 。这是最终的最大值。
这个算法可以随着机器数的线性增长而横向扩展,无须任何协调操作(机器之间不需要讨论中间结果),而且内存消耗很小(一个整型就能代表最大值)。
不幸的是,不是所有的算法都像获取最大值这样简单。更加复杂的操作则需要在算法的性能和内存使用上做出权衡。对于这个问题,我们有个三角因子模型:大数据、精确性和实时性。
我们需要选择其中两项:
精确 + 实时
数据可以存入单台机器的内存之中,我们可以随心所欲,使用任何想用的算法。结果会 100% 精确,响应会相对快速。
大数据 + 精确
传统的 Hadoop。可以处理 PB 级的数据并且为我们提供精确的答案,但它可能需要几周的时间才能为我们提供这个答案。
大数据 + 实时
近似算法为我们提供准确但不精确的结果。
Elasticsearch 目前支持两种近似算法(cardinality(基数) 和 percentiles(百分位数))。它们会提供准确但不是 100% 精确的结果。以牺牲一点小小的估算错误为代价,这些算法可以为我们换来高速的执行效率和极小的内存消耗。
对于大多数应用领域,能够实时返回高度准确的结果要比 100% 精确结果重要得多。乍一看这可能是天方夜谭。有人会叫“我们需要精确的答案!”。但仔细考虑 0.5% 错误所带来的影响:
99% 的网站延时都在 132ms 以下。
0.5% 的误差对以上延时的影响在正负 0.66ms 。
近似计算会在毫秒内放回结果,而“完全正确”的结果就可能需要几秒,甚至无法返回。
只要简单的查看网站的延时情况,难道我们会在意近似结果是在 132.66ms 内返回而不是 132ms?当然,不是所有的领域都能容忍这种近似结果,但对于绝大多数来说是没有问题的。接受近似结果更多的是一种文化观念上的壁垒而不是商业或技术上的需要。
查找唯一值的数目(Finding Distinct Counts)
Elasticsearch 提供的首个近似聚合是基数度量。它提供一个字段的基数,即该字段的唯一值的数目。可能会对 SQL 形式比较熟悉:
SELECT DISTINCT(color)
Distinct 计数是一个普通的操作,可以回答很多基本的商业问题:
网站的独立访问用户(UVs)是多少?
卖了多少种汽车?
每月有多少独立用户购买了商品?
我们可以用基数度量确定经销商销售汽车颜色的种类:
GET /cars/transactions/_search
&size& : 0,
&aggs& : {
&distinct_colors& : {
&cardinality& : {
&field& : &color&
返回的结果表明已经售卖了三种不同颜色的汽车:
&aggregations&: {
&distinct_colors&: {
&value&: 3
可以让我们的例子变得更有用:每月有多少颜色的车被售出?为了得到这个度量,我们只需要将一个 cardinality 度量嵌入一个 date_histogram:
GET /cars/transactions/_search
&size& : 0,
&aggs& : {
&months& : {
&date_histogram&: {
&field&: &sold&,
&interval&: &month&
&distinct_colors& : {
&cardinality& : {
&field& : &color&
学会权衡(Understanding the Trade-offs)
正如我们本章开头提到的,cardinality 度量是一个近似算法。它是基于 (HLL)算法的,HLL 会先对我们的输入作哈希运算,然后根据哈希运算的结果中的 bits 做概率估算从而得到基数。
我们不需要理解技术细节(如果确实感兴趣,可以阅读这篇论文),但我们最好应该关注一下这个算法的特性:
可配置的精度,用来控制内存的使用(更精确 = 更多内存)。
对于低基数集能够达到高准确度。
固定的内存使用。即使有几千或甚至上百亿的唯一值,内存的使用也只是依赖于配置里的精度要求。
要配置精度,我们必须指定 precision_threshold 参数的值。这个阀值定义了在何种基数水平下我们希望得到一个近乎精确的结果。参考以下示例:
GET /cars/transactions/_search
&size& : 0,
&aggs& : {
&distinct_colors& : {
&cardinality& : {
&field& : &color&,
&precision_threshold& : 100 #1
#1 precision_threshold 接受 0–40,000 之间的数字,更大的值还是会被当作 40,000 来处理。
示例会确保当字段唯一值在 100 以内时会得到非常准确的结果。尽管算法是无法保证这点的,但如果基数在阀值以下,几乎总是 100% 正确的。高于阀值的基数会开始节省内存而牺牲准确度,同时也会对度量结果带入误差。
对于指定的阀值,HLL 的数据结构会大概使用内存 precision_threshold * 8 字节,所以就必须在牺牲内存和获得额外的准确度间做平衡。
在实际应用中,100 的阀值可以在唯一值为百万的情况下仍然将误差维持 5% 以内。
速度优化(Optimizing for Speed)
如果想要获得唯一数目的值,通常需要查询整个数据集合(或几乎所有数据)。所有基于所有数据的操作都必须迅速,原因是显然的。HyperLogLog 的速度已经很快了,它只是简单的对数据做哈希以及一些位操作。
但如果速度对我们至关重要,可以做进一步的优化,因为 HLL 只需要字段内容的哈希值,我们可以在索引时就预先计算好。就能在查询时跳过哈希计算然后将数据信息直接加载出来。
预先计算哈希值只对内容很长或者基数很高的字段有用,计算这些字段的哈希值的消耗在查询时是无法忽略的。
尽管数值字段的哈希计算是非常快速的,存储它们的原始值通常需要同样(或更少)的内存空间。这对低基数的字符串字段同样适用,Elasticsearch 的内部优化能够保证每个唯一值只计算一次哈希。
基本上说,预先计算并不能保证所有的字段都快,它只对那些具有高基数和内容很长的字符串字段有作用。需要记住的是预先计算也只是简单地将代价转到索引时,代价就在那里,不增不减。
To do this, we need to add a new multifield to our data. We’ll delete our index, add a new mapping that includes the hashed field, and then reindex:
要想这么做,我们需要为数据增加一个新的多值字段。我们先删除索引,再增加一个包括哈希值字段的映射,然后重新索引:
DELETE /cars/
PUT /cars/
&mappings&: {
&transactions&: {
&properties&: {
&color&: {
&type&: &string&,
&fields&: {
&type&: &murmur3& #1
POST /cars/transactions/_bulk
{ &index&: {}}
{ &price& : 10000, &color& : &red&, &make& : &honda&, &sold& : && }
{ &index&: {}}
{ &price& : 20000, &color& : &red&, &make& : &honda&, &sold& : && }
{ &index&: {}}
{ &price& : 30000, &color& : &green&, &make& : &ford&, &sold& : && }
{ &index&: {}}
{ &price& : 15000, &color& : &blue&, &make& : &toyota&, &sold& : && }
{ &index&: {}}
{ &price& : 12000, &color& : &green&, &make& : &toyota&, &sold& : && }
{ &index&: {}}
{ &price& : 20000, &color& : &red&, &make& : &honda&, &sold& : && }
{ &index&: {}}
{ &price& : 80000, &color& : &red&, &make& : &bmw&, &sold& : && }
{ &index&: {}}
{ &price& : 25000, &color& : &blue&, &make& : &ford&, &sold& : && }
#1 多值字段的类型是 murmur3,这是一个哈希函数。
现在当我们执行聚合时,我们使用 color.hash 字段而不是 color 字段:
GET /cars/transactions/_search
&size& : 0,
&aggs& : {
&distinct_colors& : {
&cardinality& : {
&field& : &color.hash& #1
#1 注意我们指定的是哈希过的多值字段,而不是原始字段。
现在 cardinality 度量会读取 &color.hash& 里的值(预先计算的哈希值),并将它们作为原始值的动态哈希值。
每个文档节省的时间有限,但如果哈希每个字段需要 10 纳秒而我们的聚合需要访问一亿文档,那么每个查询就需要多花 1 秒钟的时间。如果我们发现自己在很多文档都会使用 cardinality 基数,可以做些性能分析看是否有必要在我们部署的应用中采用预先计算哈希的方式。
百分计算(Calculating Percentiles)
Elasticsearch 提供的另外一个近似度量就是 percentiles 百分位数度量。百分位数展现某以具体百分比下观察到的数值。例如,第95个百分位上的数值,是高于 95% 的数据总和。
百分位数通常用来找出异常。在(统计学)的正态分布下,第 0.13 和 第 99.87 的百分位数代表与均值距离三倍标准差的值。任何处于三倍标准差之外的数据通常被认为是不寻常的,因为它与平均值相差太大。
更具体的说,假设我们正运行一个庞大的网站,而我们的任务是保证用户请求能得到快速响应,因此我们就需要监控网站的延时来判断响应是否能达到目标。
在此场景下,一个常用的度量方法就是平均响应延时,但这是一个不好的选择(尽管很常用),因为平均数通常会隐藏那些异常值,中位数有着同样的问题。我们可以尝试最大值,但这个度量会轻而易举的被单个异常值破坏。
在图 Figure 40, “Average request latency over time” 查看问题。如果我们倚靠如平均值或中位数这样的简单度量,就会得到像这样一幅图 Figure 40, “Average request latency over time”.
Figure 40. Average request latency over time
一切正常。图上有轻微的波动,但没有什么值得关注的。但如果我们加载 99 百分位数时(这个值代表最慢的 1% 的延时),我们看到了完全不同的一幅画面,如图Figure 41, “Average request latency with 99th percentile over time” 所示。
Figure 41. Average request latency with 99th percentile over time
令人吃惊!在上午九点半时,均值只有 75ms。如果作为一个系统管理员,我们都不会看他第二眼。一切正常!但 99 百分位告诉我们有 1% 的用户碰到的延时超过 850ms,这是另外一幅场景。在上午4点48时也有一个小波动,这甚至无法从平均值和中位数曲线上观察到。
这只是百分位的一个应用场景,百分位还可以被用来快速用肉眼观察数据的分布,检查是否有数据倾斜或双峰甚至更多。
百分位度量(Percentile Metric)
让我加载一个新的数据集(汽车的数据不太适用于百分位)。我们要索引一系列网站延时数据然后运行一些百分位操作进行查看:
POST /website/logs/_bulk
{ &index&: {}}
{ &latency& : 100, &zone& : &US&, &timestamp& : && }
{ &index&: {}}
{ &latency& : 80, &zone& : &US&, &timestamp& : && }
{ &index&: {}}
{ &latency& : 99, &zone& : &US&, &timestamp& : && }
{ &index&: {}}
{ &latency& : 102, &zone& : &US&, &timestamp& : && }
{ &index&: {}}
{ &latency& : 75, &zone& : &US&, &timestamp& : && }
{ &index&: {}}
{ &latency& : 82, &zone& : &US&, &timestamp& : && }
{ &index&: {}}
{ &latency& : 100, &zone& : &EU&, &timestamp& : && }
{ &index&: {}}
{ &latency& : 280, &zone& : &EU&, &timestamp& : && }
{ &index&: {}}
{ &latency& : 155, &zone& : &EU&, &timestamp& : && }
{ &index&: {}}
{ &latency& : 623, &zone& : &EU&, &timestamp& : && }
{ &index&: {}}
{ &latency& : 380, &zone& : &EU&, &timestamp& : && }
{ &index&: {}}
{ &latency& : 319, &zone& : &EU&, &timestamp& : && }
数据有三个值:延时、数据中心的区域以及时间戳。让我们对数据全集执行百分位操作以获得数据分布情况的直观感受:
GET /website/logs/_search
&size& : 0,
&aggs& : {
&load_times& : {
&percentiles& : {
&field& : &latency& #1
&avg_load_time& : {
&field& : &latency& #2
#1 percentiles 度量被应用到 latency 延时字段。
#2 为了比较,我们对相同字段使用 avg 度量。
默认情况下,percentiles 度量会返回一组预定义的百分位数值:[1, 5, 25, 50, 75, 95, 99]。它们表示了人们感兴趣的常用百分位数值,极端的百分位数在范围的两边,其他的一些处于中部。在返回的响应中,我们可以看到最小延时在 75ms 左右,而最大延时差不多有 600ms。与之形成对比的是,平均延时在 200ms 左右,信息并不是很多:
&aggregations&: {
&load_times&: {
&values&: {
&1.0&: 75.55,
&5.0&: 77.75,
&25.0&: 94.75,
&50.0&: 101,
&75.0&: 289.75,
&95.0&: 489.85,
&99.0&: 596.2
&avg_load_time&: {
&value&: 199.34
所以显然延时的分布很广,然我们看看它们是否与数据中心的地理区域有关:
GET /website/logs/_search
&size& : 0,
&aggs& : {
&zones& : {
&terms& : {
&field& : &zone& #1
&aggs& : {
&load_times& : {
&percentiles& : { #2
&field& : &latency&,
&percents& : [50, 95.0, 99.0] #3
&load_avg& : {
&field& : &latency&
#1 首先根据区域我们将延时分到不同的桶中。
#2 再计算每个区域的百分位数值。
#3 percents 参数接受了我们想返回的一组百分位数,因为我们只对长的延时感兴趣。
在响应结果中,我们发现欧洲区域(EU)要比美国区域(US)慢很多,在美国区域(US),50 百分位与 99 百分位十分接近,它们都接近均值。
与之形成对比的是,欧洲区域(EU)在 50 和 99 百分位有较大区分。现在,显然可以发现是欧洲区域(EU)拉低了延时的统计信息,我们知道欧洲区域的 50% 延时都在 300ms+。
&aggregations&: {
&zones&: {
&buckets&: [
&key&: &eu&,
&doc_count&: 6,
&load_times&: {
&values&: {
&50.0&: 299.5,
&95.0&: 562.25,
&99.0&: 610.85
&load_avg&: {
&value&: 309.5
&key&: &us&,
&doc_count&: 6,
&load_times&: {
&values&: {
&50.0&: 90.5,
&95.0&: 101.5,
&99.0&: 101.9
&load_avg&: {
&value&: 89.67
百分位等级(Percentile Ranks)
这里有另外一个紧密相关的度量叫 percentile_ranks。百分位度量告诉我们落在某个百分比以下的所有文档的最小值。例如,如果 50 百分位是 119ms,那么有 50% 的文档数值都不超过 119ms。percentile_ranks 告诉我们某个具体值属于哪个百分位。119ms 的 percentile_ranks 是在 50 百分位。这基本是个双向关系,例如:
50 百分位是 119ms。
119ms 百分位等级是 50 百分位。
所以假设我们网站必须维持的服务等级协议(SLA)是响应时间低于 210ms。然后,开个玩笑,我们老板警告我们如果响应时间超过 800ms 会把我开除。可以理解的是,我们希望知道有多少百分比的请求可以满足 SLA 的要求(并期望至少在 800ms 以下!)。
为了做到这点,我们可以应用 percentile_ranks 度量而不是 percentiles 度量:
GET /website/logs/_search
&size& : 0,
&aggs& : {
&zones& : {
&terms& : {
&field& : &zone&
&aggs& : {
&load_times& : {
&percentile_ranks& : {
&field& : &latency&,
&values& : [210, 800] #1
#1 percentile_ranks 度量接受一组我们希望分级的数值。
在聚合运行后,我们能得到两个值:
&aggregations&: {
&zones&: {
&buckets&: [
&key&: &eu&,
&doc_count&: 6,
&load_times&: {
&values&: {
&210.0&: 31.443,
&800.0&: 100
&key&: &us&,
&doc_count&: 6,
&load_times&: {
&values&: {
&210.0&: 100,
&800.0&: 100
这告诉我们三点重要的信息:
在欧洲(EU),210ms 的百分位等级是 31.94% 。
在美国(US),210ms 的百分位等级是 100% 。
在欧洲(EU)和美国(US),800ms 的百分位等级是 100% 。
通俗的说,在欧洲区域(EU)只有 32% 的响应时间满足服务等级协议(SLA),而美国区域(US)始终满足服务等级协议的。但幸运的是,两个区域所有响应时间都在 800ms 以下,所有我们还不会被炒鱿鱼(至少目前不会)。
percentile_ranks 度量提供了与 percentiles 相同的信息,但它以不同方式呈现,如果我们对某个具体数值更关心,使用它会更方便。
学会权衡(Understanding the Trade-offs)
和基数一样,计算百分位需要一个近似算法。朴素的实现会维护一个所有值的有序列表,但当我们有几十亿数据分布在几十个节点时,这几乎是不可能的。
取而代之的是 percentiles 使用一个 TDigest 算法(由 Ted Dunning 在
里面提出的)。有了 HyperLogLog,就不需要理解完整的技术细节,但有必要了解算法的特性:
百分位的准确度与百分位的极端程度相关,也就是说 1 或 99 的百分位要比 50 百分位要准确。这只是数据结构内部机制的一种特性,但这是一个好的特性,因为多数人只关心极端的百分位。
对于数值集合较小的情况,百分位非常准确。如果数据集足够小,百分位可能 100% 精确。
随着桶里数值的增长,算法会开始对百分位进行估算。它能有效在准确度和内存节省之间做出权衡。不准确的程度比较难以总结,因为它依赖于聚合时数据的分布以及数据量的大小。
与基数类似,我们可以通过修改参数 compression 来控制内存与准确度之间的比值。
TDigest 算法用节点近似计算百分比:节点越多,准确度越高(同时内存消耗也越大),这都与数据量成正比。compression 参数限制节点的最大数目为 20 * compression。
因此,通过增加压缩比值,我们可以提高准确度同时也消耗更多内存。更大的压缩比值会使算法运行更慢,因为底层的树形数据结构的存储也会增长,也导致操作的代价更高。默认的压缩比值是 100。
一个节点粗略计算使用 32 字节的内存,所以在最坏的情况下(例如,大量数据有序存入),默认设置会生成一个大小约为 64KB 的 TDigest。在实际应用中,数据会更随机,所以 TDigest 使用的内存会更少。
阅读(...) 评论()

我要回帖

更多关于 elasticsearch head 的文章

 

随机推荐