二十七、ElasticSearch聚合分析中的算法讲解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二十七、ElasticSearch聚合分析中的算法讲解相关的知识,希望对你有一定的参考价值。

参考技术A 1、易并行聚合算法,三角选择原则,近似聚合算法
(1)、易并行聚合算法:比如max

(2)、不易的,如count(distinct)

(2)精准+大数据:hadoop,批处理,非实时,可以处理海量数据,保证精准,可能会跑几个小时
(3)大数据+实时:es,不精准,近似估计,可能会有百分之几的错误率
(4)、近似聚合算法
如果采取近似估计的算法:延时在100ms左右,0.5%错误
如果采取100%精准的算法:延时一般在5s~几十s,甚至几十分钟,几小时, 0%错误
2、cardinality去重及算法优化和HLL算法分析
es,去重,cartinality metric,对每个bucket中的指定的field进行去重,取去重后的count,类似于count(distcint)

precision_threshold优化准确率和内存开销可以提高去重性能
cardinality算法,会占用precision_threshold * 8 byte 内存消耗,100 * 8 = 800个字节
HyperLogLog++ (HLL)算法性能优化
默认情况下,发送一个cardinality请求的时候,会动态地对所有的field value,取hash值; 将取hash值的操作,前移到建立索引的时候

3、percentiles百分比算法以及网站访问时延统计
需求:比如有一个网站,记录下了每次请求的访问的耗时,需要统计tp50,tp90,tp99
tp50:50%的请求的耗时最长在多长时间
tp90:90%的请求的耗时最长在多长时间
tp99:99%的请求的耗时最长在多长时间

数据:

不同概率百分比之间的防问效率:

分组统计防问百分比,并计算平均值

4、percentile ranks网站访问时延SLA统计

SLA:就是你提供的服务的标准
例以地区分组,计算以不同时间的响应百分比

5、doc value原理
(1)index-time生成
PUT/POST的时候,就会生成doc value数据,也就是正排索引
(2)核心原理与倒排索引类似
正排索引,也会写入磁盘文件中,os cache先进行缓存,以提升访问doc value正排索引的性能,如果os cache内存大小不足够放得下整个正排索引,doc value,就会将doc value的数据写入磁盘文件中
(3)性能问题:
es官方是建议,es大量是基于os cache来进行缓存和提升性能的,不建议用jvm内存来进行缓存,那样会导致一定的gc开销和oom问题给jvm更少的内存,给os cache更大的内存。
(4)、column压缩
doc1: 550
doc2: 550
doc3: 500
合并相同值,550,doc1和doc2都保留一个550的标识即可
(1)所有值相同,直接保留单值
(2)少于256个值,使用table encoding模式:一种压缩方式
(3)大于256个值,看有没有最大公约数,有就除以最大公约数,然后保留这个最大公约数
(4)如果没有最大公约数,采取offset结合压缩的方式:
如果的确不需要doc value,比如聚合等操作,那么可以禁用,减少磁盘空间占用
PUT my_index

"mappings":
"my_type":
"properties":
"my_field":
"type": "keyword"
"doc_values": false





6、对于分词的field执行aggregation,发现报错。。。

如果直接对分词field执行聚合,报错,大概意思是说,你必须要打开fielddata,然后将正排索引数据加载到内存中,才可以对分词的field执行聚合操作,而且会消耗很大的内存

给分词的field,设置fielddata=true,发现可以执行

也可以用内置field不分词,对string field进行聚合

7、分词field+fielddata的工作原理
(1)、不分词的所有field,可以执行聚合操作 --> 如果你的某个field不分词,那么在index-time时,就会自动生成doc value --> 针对这些不分词的field执行聚合操作的时候,自动就会用doc value来执行
(2)、分词field,是没有doc value的。在index-time,如果某个field是分词的,那么是不会给它建立doc value正排索引的,因为分词后,占用的空间过于大,所以默认是不支持分词field进行聚合的
fielddata加载到内存的过程是lazy加载的,对一个analzyed field执行聚合时,才会加载,而且是field-level加载的。一个index的一个field,所有doc都会被加载,而不是少数doc,不是index-time创建,是query-time创建
为什么fielddata必须在内存?因为分词的字符串,需要按照term进行聚合,需要执行更加复杂的算法和操作,如果基于磁盘和os cache,那么性能会很差。

8、fielddata相关优化配置
(1)、内存限制
indices.fielddata.cache.size: 20%,超出限制,清除内存已有fielddata数据,fielddata占用的内存超出了这个比例的限制,那么就清除掉内存中已有的fielddata数据
默认无限制,限制内存使用,但是会导致频繁evict和reload,大量IO性能损耗,以及内存碎片和gc

(2)监控fielddata内存使用
GET /_stats/fielddata?fields=*
GET /_nodes/stats/indices/fielddata?fields=*
GET /_nodes/stats/indices/fielddata?level=indices&fields=*

(3)、circuit breaker断路器
如果一次query load的feilddata超过总内存,就会oom --> 内存溢出
circuit breaker会估算query要加载的fielddata大小,如果超出总内存,就短路,query直接失败
indices.breaker.fielddata.limit:fielddata的内存限制,默认60%
indices.breaker.request.limit:执行聚合的内存限制,默认40%
indices.breaker.total.limit:综合上面两个,限制在70%以内

(4)、fielddata filter的细粒度内存加载控制

min:仅仅加载至少在1%的doc中出现过的term对应的fielddata
比如说某个值,hello,总共有1000个doc,hello必须在10个doc中出现,那么这个hello对应的fielddata才会加载到内存中来
min_segment_size:少于500 doc的segment不加载fielddata
加载fielddata的时候,也是按照segment去进行加载的,某个segment里面的doc数量少于500个,那么这个segment的fielddata就不加载

(5)、fielddata预加载

query-time的fielddata生成和加载到内存,变为index-time,建立倒排索引的时候,会同步生成fielddata并且加载到内存中来,这样的话,对分词field的聚合性能当然会大幅度增强
(6)、global ordinal序号标记预加载

有很多重复值的情况,会进行global ordinal标记
doc1: status1
doc2: status2
doc3: status2
doc4: status1

status1 --> 0 status2 --> 1

doc1: 0
doc2: 1
doc3: 1
doc4: 0

建立的fielddata也会是这个样子的,这样的好处就是减少重复字符串的出现的次数,减少内存的消耗

BetaFlight模块设计之二十七:姿态更新任务分析

BetaFlight模块设计之二十七:姿态更新任务分析

基于BetaFlight开源代码框架简介的框架设计,逐步分析内部模块功能设计。

姿态更新任务

描述:主要用于计算更新当前机体姿态欧拉角。

 ├──> 初始化
 │   ├──> [x]硬件初始化
 │   └──> [x]业务初始化
 ├──> 任务
 │   ├──> [x]实时任务
 │   ├──> [x]事件任务
 │   └──> [v]时间任务[TASK_ATTITUDE] = DEFINE_TASK("ATTITUDE", NULL, NULL, imuUpdateAttitude, TASK_PERIOD_HZ(100), TASK_PRIORITY_MEDIUM),
 ├──> 驱动
 │   ├──> [x]查询
 │   └──> [x]中断
 └──> 接口
     ├──> void imuConfigure(uint16_t throttle_correction_angle, uint8_t throttle_correction_value)
     ├──> bool isUpright(void);
     └──> float getCosTiltAngle(void);

姿态欧拉角定义

\\src\\main\\flight\\imu.h
typedef union 
    int16_t raw[XYZ_AXIS_COUNT];
    struct 
        // absolute angle inclination in multiple of 0.1 degree    180 deg = 1800
        int16_t roll;
        int16_t pitch;
        int16_t yaw;
     values;
 attitudeEulerAngles_t;
#define EULER_INITIALIZE    0, 0, 0  
\\src\\main\\flight\\imu.c
// absolute angle inclination in multiple of 0.1 degree    180 deg = 1800
attitudeEulerAngles_t attitude = EULER_INITIALIZE;

主要函数分析

imuUpdateAttitude函数

imuUpdateAttitude
 ├──> <sensors(SENSOR_ACC) && acc.isAccelUpdatedAtLeastOnce>
 ├──> IMU_LOCK
 ├──> <SIMULATOR_BUILD><SIMULATOR_IMU_SYNC>
 │   ├──> <imuUpdated == false>
 │   │   ├──> IMU_UNLOCK
 │   │   └──> return
 │   └──> imuUpdated = false;
 ├──> imuCalculateEstimatedAttitude  //计算估计的姿态
 ├──> IMU_UNLOCK
 ├──> <throttleAngleValue && (FLIGHT_MODE(ANGLE_MODE) || FLIGHT_MODE(HORIZON_MODE)) && ARMING_FLAG(ARMED)> //自稳或者半自稳下,计算油门角度修正
 │   └──> throttleAngleCorrection = calculateThrottleAngleCorrection();
 ├──> mixerSetThrottleAngleCorrection(throttleAngleCorrection);
 └──> <!(sensors(SENSOR_ACC) && acc.isAccelUpdatedAtLeastOnce)>  // ACC数据从来没有更新过的情况下,只能默认设置零
     ├──> acc.accADC[X] = 0;
     ├──> acc.accADC[Y] = 0;
     ├──> acc.accADC[Z] = 0;
     └──> schedulerIgnoreTaskStateTime

注:ACC更新详见:BetaFlight模块设计之十一:Gyro&Acc任务分析

imuCalculateEstimatedAttitude函数

imuCalculateEstimatedAttitude
 ├──> <sensors(SENSOR_MAG) && compassIsHealthy() && !gpsRescueDisableMag()>
 │   └──> useMag = true;
 ├──> <!useMag && sensors(SENSOR_GPS) && STATE(GPS_FIX) && gpsSol.numSat >= 5 && gpsSol.groundSpeed >= GPS_COG_MIN_GROUNDSPEED>
 │   ├──> courseOverGround = DECIDEGREES_TO_RADIANS(gpsSol.groundCourse);
 │   ├──> useCOG = true;
 │   └──> <useCOG && shouldInitializeGPSHeading()>
 │       ├──> imuComputeQuaternionFromRPY(&qP, attitude.values.roll, attitude.values.pitch, gpsSol.groundCourse);
 │       └──> useCOG = false; // Don't use the COG when we first reinitialize.  Next time around though, yes.
 ├──> gyroGetAccumulationAverage(gyroAverage);
 ├──> <accGetAccumulationAverage(accAverage)>
 │   └──> useAcc = imuIsAccelerometerHealthy(accAverage);
 ├──> imuMahonyAHRSupdate
 └──> imuUpdateEulerAngles

注1:course over ground定义
注2:imuMahonyAHRSupdate有算法来计算姿态,后续有时间再做仔细研读。

以上是关于二十七、ElasticSearch聚合分析中的算法讲解的主要内容,如果未能解决你的问题,请参考以下文章

2021年大数据常用语言Scala(二十七):函数式编程 聚合操作

ElasticSearch实战(二十七)-可视化集群管理(head插件)

ElasticSearch实战(二十七)-可视化集群管理(head插件)

机器学习实战基础(二十七):sklearn中的降维算法PCA和SVDPCA对手写数字数据集的降维

机器学习实战基础(二十七):sklearn中的降维算法PCA和SVDPCA对手写数字数据集的降维

初级算法探索——动态规划篇(二十七)