让Druid实现事件设备数留存数的精准计算
2018-04-03 16:23
369 查看
我们在产品中有很多这样的指标需要计算:
每天登陆的用户数(设备数)
次日留存数(昨天的激活设备而且今天该设备还活跃),七日留存数,自定义日子的留存数。
诸如此类根据设备数来算的指标,如何实现?
我们之前是将设备ID转换为offset,再将offset转化为bitmap,并将其根据不同维度存在MySQL中。由于每天的写入和查询量太大,MySQL经受了严峻的考验。分库又面临着数据倾斜等各种问题。
我们后来准备将其迁入Druid中,但Druid天生并不支持这种运算。我们能不能增加一个bitmap的自定义扩展,使Druid也能够进行bitmap相关的聚合和查询运算呢?答案是可以的。
为了实现这个功能扩展,我们有两部分需要实现:
实现bitmap作为Druid的metric,存到Druid中。
定义规则,可以根据json查询bitmap计算以后的值,并返回客户端。
定义Module定义BitmapDruidModule implements DruidModule
在src/main/resources目录下创建目录和文件:META-INF/services/io.druid.initialization.DruidModule
在以上文件内写入Module的定义类:io.druid.query.aggregation.bitmap.BitmapDruidModule
实现bitmap作为Druid的metric,存到Druid中
实现BitmapCubeComplexMetricSerde extends ComplexMetricSerde。
其中:
1> TypeName: bitmapCube
2> 实现其他相关方法。
ComplexMetricExtractor getExtractor()
ObjectStrategy getObjectStrategy()
deserializeColumn(ByteBuffer byteBuffer, ColumnBuilder columnBuilder)
将该Serde注册到ComplexMetrics中:
ComplexMetrics.registerSerde(BITMAP_CUBE, new BitmapCubeComplexMetricSerde());
实现BitmapCubeAggregator implements Aggregator
主要实现aggregate()方法。
实现 BitmapCubeAggregatorFactory extends AggregatorFactory
类注解:@JsonTypeName("bitmapCube")
实现combine等相关方法。
在BitmapCubeDruidModule中的getJacksonModules() 方法里注册BitmapCubeAggregatorFactory类
@Override
public List<? extends Module> getJacksonModules() {
return ImmutableList.of(
new SimpleModule().registerSubtypes(
new NamedType(io.druid.query.aggregation.bitmapcube.BitmapCubeCubeAggregatorFactory.class, BITMAP_CUBE),
......
}
定义查询规则查询条件变为一个Queries的list,完整查询示例如下:{
"dataSource": "login_user",
"queries": {
"459068#SRC": {
"filter": {
"fields": [
{
"dimension": "dim1",
"value": "BBDB6E271AFE4E5587892165205A20B1",
"type": "selector"
},
{
"dimension": "dim2",
"value": "459068",
"type": "selector"
}
],
"type": "and"
},
"intervals": [
"2018-03-06T00:00:00/2018-03-07T00:00:00"
],
"granularity": "all",
"aggregations": [
{
"fieldName": "offsetBitmap",
"name": "offsetBitmap",
"type": "bitmapCube"
}
],
"queryType": "groupBy",
"limitSpec": {
"type": "default"
},
"dataSource": "login_user"
}
},
"postAggregations": [
{
"field": "459068#SRC",
"func": null,
"name": "459068",
"fields": null,
"type": "bitmapCubeSize"
}
],
"intervals": [
"2018-03-06T00:00:00/2018-03-07T00:00:00"
],
"queryType": "bitmapCube"
}查询过程可使用线程池将每个子查询进行并行查询,然后将每个子查询的bitmap结果返回给Broker,然后Broker再根据Aggregator规则分别进行聚合,将聚合结果返回客户端。
然后根据Druid提供的接口实现Jersey的Resource,以及各种BitmapCubeQuery,Chest,Aggregator等各种类。
然后按照标准的Druid Extension进行部署。
此处不在详述。
每天登陆的用户数(设备数)
次日留存数(昨天的激活设备而且今天该设备还活跃),七日留存数,自定义日子的留存数。
诸如此类根据设备数来算的指标,如何实现?
我们之前是将设备ID转换为offset,再将offset转化为bitmap,并将其根据不同维度存在MySQL中。由于每天的写入和查询量太大,MySQL经受了严峻的考验。分库又面临着数据倾斜等各种问题。
我们后来准备将其迁入Druid中,但Druid天生并不支持这种运算。我们能不能增加一个bitmap的自定义扩展,使Druid也能够进行bitmap相关的聚合和查询运算呢?答案是可以的。
为了实现这个功能扩展,我们有两部分需要实现:
实现bitmap作为Druid的metric,存到Druid中。
定义规则,可以根据json查询bitmap计算以后的值,并返回客户端。
定义Module定义BitmapDruidModule implements DruidModule
在src/main/resources目录下创建目录和文件:META-INF/services/io.druid.initialization.DruidModule
在以上文件内写入Module的定义类:io.druid.query.aggregation.bitmap.BitmapDruidModule
实现bitmap作为Druid的metric,存到Druid中
实现BitmapCubeComplexMetricSerde extends ComplexMetricSerde。
其中:
1> TypeName: bitmapCube
2> 实现其他相关方法。
ComplexMetricExtractor getExtractor()
ObjectStrategy getObjectStrategy()
deserializeColumn(ByteBuffer byteBuffer, ColumnBuilder columnBuilder)
将该Serde注册到ComplexMetrics中:
ComplexMetrics.registerSerde(BITMAP_CUBE, new BitmapCubeComplexMetricSerde());
实现BitmapCubeAggregator implements Aggregator
主要实现aggregate()方法。
实现 BitmapCubeAggregatorFactory extends AggregatorFactory
类注解:@JsonTypeName("bitmapCube")
实现combine等相关方法。
在BitmapCubeDruidModule中的getJacksonModules() 方法里注册BitmapCubeAggregatorFactory类
@Override
public List<? extends Module> getJacksonModules() {
return ImmutableList.of(
new SimpleModule().registerSubtypes(
new NamedType(io.druid.query.aggregation.bitmapcube.BitmapCubeCubeAggregatorFactory.class, BITMAP_CUBE),
......
}
定义查询规则查询条件变为一个Queries的list,完整查询示例如下:{
"dataSource": "login_user",
"queries": {
"459068#SRC": {
"filter": {
"fields": [
{
"dimension": "dim1",
"value": "BBDB6E271AFE4E5587892165205A20B1",
"type": "selector"
},
{
"dimension": "dim2",
"value": "459068",
"type": "selector"
}
],
"type": "and"
},
"intervals": [
"2018-03-06T00:00:00/2018-03-07T00:00:00"
],
"granularity": "all",
"aggregations": [
{
"fieldName": "offsetBitmap",
"name": "offsetBitmap",
"type": "bitmapCube"
}
],
"queryType": "groupBy",
"limitSpec": {
"type": "default"
},
"dataSource": "login_user"
}
},
"postAggregations": [
{
"field": "459068#SRC",
"func": null,
"name": "459068",
"fields": null,
"type": "bitmapCubeSize"
}
],
"intervals": [
"2018-03-06T00:00:00/2018-03-07T00:00:00"
],
"queryType": "bitmapCube"
}查询过程可使用线程池将每个子查询进行并行查询,然后将每个子查询的bitmap结果返回给Broker,然后Broker再根据Aggregator规则分别进行聚合,将聚合结果返回客户端。
然后根据Druid提供的接口实现Jersey的Resource,以及各种BitmapCubeQuery,Chest,Aggregator等各种类。
然后按照标准的Druid Extension进行部署。
此处不在详述。
相关文章推荐
- android设备外接键盘实现监听事件
- js实现对Android设备物理返回键单击/双击事件处理(Framework7框架)
- 【android学习】安卓设备实现触摸事件的监听,跨进程事件注入
- 配置IIS--通过多台设备之间建立局域网--测试Application_onStart事件计算当前网站程序在线人数
- 在GridView控件内文本框实现TextChanged事件,勾选复选框时 :textbox文本框可编辑,编辑文本框的数字后 总金额会重新计算并统计
- 安全设备能否实现弹性计算
- BigDecimal实现精准计算
- 【Code】JS-propertychange事件,实现实时金额计算
- iOS:CAKeyframeAnimation实现UIImageView精准时间的动画结束事件
- 基于ARM的I2C设备控制方法的实现
- 使用UE4实现HTC Vive设备的简单操作
- 实现购物车多物品数量 总价计算
- VB.NET实现DirectPlay(1)枚举设备
- JS实现监听事件,添加删除显示控件
- LeNet-5卷积神经网络的网络结构(参数计算)及tensorflow实现
- js原生touch事件实现微信语音按住录音,上滑取消。
- 主流框架中DOMContentLoaded事件的实现
- 用方法来实现:计算两个数的最大值。思考:方法的参数?返回值?扩展(*):计算任意多个数间的最大值(提示:params)
- C#实现的根据年月日计算星期几的函数 选择自 fanz2000 的 Blog
- C#里的委托和事件实现Observer (转)