假设通过storm接入了每小时百万级的埋点数据(有userId和url字段),要求可以实现能够实时获取某个用户每天,每周或每月访问了某个url的累加值。读和写的量都较大且实时性要求比较高。hbase的话如何设计才能实现读写在时间上最优?
针对题目的pv,uv来说,假设需要求出单个url某天,某周,某月的pv和uv
一般来说这种需求如果查询时再计算就太慢了,需要提前进行预聚合,比如我们设计这么一个表
| url | timeRange | pv | uidSet |
把url和timeRange组合为rowkey
timeRange为统计的时间范围(跨度为所需的最小时间粒度,本问题中为一天,比如2018-10-11,2018-10-12)
pv为数值,uidSet为访问该url的userId集合
当一条记录来临时,storm处理之后,对对应的url和对应timeRange里面的pv值+1,uidSet执行uidSet.add(userId)操作
这样如果统计url1的2018-10-01到2018-10-07号的pv值与uv值,可以取出对应7行数据,执行如下计算
pv=pv1 + pv2 + ... + pv7
总uidSet = uidSet1.merge(uidSet2).merge(uidSet3)...... .merge(uidSet7)
uv = 总uidSet.cardinality()
上面方法中pv计算很简单,直接是值的相加,单条记录pv字段存储量为一个long的大小
uv的计算就会有些问题:uidSet的大小按照普通方法会随着userId的规模扩大而失控,merge操作耗时也会增加
解决方法有几种
如果不要求结果完全精确,能接受微小的误差的话,可以使用hyperloglog结构存储,这样的话uidSet的大小可控,merge操作的速度也很快
如果要求结果完全精确,可以参照druid的datasketches实现,来存储uidSet
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。