实时流计算与踩过的坑

0 概述

随着业务的推进,对数据的实时性要求更高,比如需要知道一个业务上线带来的实时流量,去衡量它上线之后的效果,实时的获取预算消耗情况,实时的掌握应用的响应情况,并且根据聚合结果再处理。
基于有一定实时流计算基础的情况,下面着重介绍设计过程中应该注意的地方。

1 设计方面

1.1 数据的倾斜、不平均

在APP中,统计一个活动区块的实时流量,区块可能被划分为多块,针对不同的用户,个性化推荐不同的活动,每个活动有bizId

比较简单的设计就是直接对bizId进行field grouping,然后统计bizId的PV,UV等。但是有些活动会被推荐给多个用户,有些活动只会推荐少数用户,导致每个逻辑统计bolt处理的数据不够平均

实时流计算与踩过的坑_第1张图片

上图中,bizdId为1的流量较大,对应的Task处理压力大,会有消息堆积的情况。

比较好的解决方法是:

  • 我们先进行一次散列(直接用Storm的shuffle grouping ),在第一层 bolt 中,保证每个task处理数据量大致相等,但是这样数据会分散到每个task。
    然后分发继续可以使用field grouping,对之前已经聚合过一次的结果,在第二层bolt中,进行汇总。
  • 也有第二种解决方法,就是设计比较好的fileding grouping字段,保证每个字段的数据量大致相等(也就是自己思考如何散列),需要具体情况,具体分析

1.2 计算结果的聚合/更新方式

计算结果的聚合方式有三种

  1. 一种是全量式,按照时间间隔进行聚合,比如我统计1分钟的PV,那我在内存中进行聚合计算,一分钟之后再进行存储,存在的问题是,如果这个Bolt挂了,被重启,那可能就丢了之前已经聚合的一部分数据
  2. 第二种覆盖式,我提高写入频率,比如虽然是统计1分钟的数据,我每10秒就写入一次,写入过程判断是否存在这分钟数据,如果存在就update,否则直接存储。
  3. 第三种中心式,利用Redis进行存储,因为我们基本上value都是一个int类型的值,所以对redis操作的,KV加起来的字节数很小,在W级别的QPS下,响应时间avg基本可以在5MS下(同机房),因此我们的统计可以直接对redis操作,但是这样的做法是比较土豪的方式,消耗redis资源比较厉害,但是只做短时间的存储,另外起一个bolt,对存储的key进行记录,周期性的,对已经存储过的key可以进行load form redis 再 save to db ,进行持久化。

1.3 延时数据的统计

在大多数的实时流计算中,我们监听的是kafka的消息,进行消息处理。
一般情况下,kafka的性能很高,partion的设计使得可以承担更高的QPS,所以消息的到达几乎是没有延时的。

但是我们的topology 是无状态的,在我们进行重启,部署的时候,我们可以从offset开始消费,但是消息已经不是实时的,而是之前一段时间的,可以理解为消息到达的延时
比较好的处理方法是,所有的日志都需要带上时间戳,消息处理的时候,应该以日志自带时间戳为准,而不是以消息处理的时间为准。

1.4 超大数据的去重统计

在统计UV的时候,我们是基于用户的ID统计的,如果用户量少,那么可以直接用set或者map之类的,但是对于一些百万级别的用户,特别是统计不同维度的访问用户,就会成倍增加数据量。
这里有两种方法:

  • 布隆过滤器,布隆过滤器是由K个散列函数和一个二进制向量组成,当一个元素加入时,K个散列函数将元素映射到二进制向量的的K个点,并且置为1。检索时就看这些点是不是都是1,这个方法是可行的,但是误差比较随机

  • HyperLogLog,这是用来做基数统计的算法,RedisAPI自带,因此在我们的项目中,我们实际使用的就是这种方法,当然它也是一种误差范围内的算法。一般误差是在0.81%下
    引用官方文档的说明

The HyperLogLog data structure can be used in order to count uniqueelements in a set using just a small constant amount of memory, specifically 12k bytes for every HyperLogLog (plus a few bytes for the key itself).
The returned cardinality of the observed set is not exact, but approximated with a standard error of 0.81%.

2 监控方面

2.1 kafka消息的堆积

kafka消息直接做法是利用现成的监控工具查看,可以看到消息到达量和消费量

2.2 StormUI

用storm自带的Storm-UI就可以比较清楚的知道自己拓扑的情况,注意它也是采样的,不是精确的。

2.3.1每个bolt的性能

UI中点入自己的topology

鼠标放到对应英文上面就可以知道每个指标的含义
比如Execute执行时间,处理时间等。

2.3.3bolt的消息堆积情况

在Topology Visualization中点开,可以看到每个bolt的球球,其中颜色的深浅说明了消息的堆积情况。

其中从上往下说明堆积越来越严重

你可能感兴趣的:(实时流计算与踩过的坑)