场景

k12在线教育公司的业务场景中,有一些业务场景需要实时统计和分析,如分析在线上课老师数量、学生数量,实时销售额,课堂崩溃率等,需要实时反应上课的质量问题,以便于对整个公司的业务情况有大致的了解。

方案对比

对比了很多解决方案,如下几种,列出来供参考。

方案 实时入库 SQL支持度
Spark+CarbonData 支持 Spark SQL语法丰富
Kylin 不支持 支持join
Flink+Druid 支持 0.15以前不支持SQL,不支持join
  1. 上一篇文章所示,使用Spark+CarbonData也是一种解决方案,但是他的缺点也是比较明显,如不能和Flink进行结合,因为我们整个的大数据规划的大致方向是,Spark用来作为离线计算,Flink作为实时计算,并且这两个大方向短时间内不会改变;
  2. Kylin一直是老牌OLAP引擎,但是有个缺点无法满足我们的需求,就是在技术选型的那个时间点kylin还不支持实时入库(后续2.0版本支持实时入库),所以就选择了放弃;
  3. 使用Flink+Druid方式实现,这个时间选择这个方案,简直是顺应潮流呀,Flink现在如日中天,各大厂都在使用,Druid是OLAP的新贵,关于它的文章也有很多,我也不赘述太多。有兴趣的可以看下这篇文章,我的博客其它文章也有最新版本的安装教程,实操方案哦。

设计方案

实时处理采用Flink SQL,实时入库Druid方式采用 druid-kafka-indexing-service,另一种方式入库方式,Tranquility,这种方式测试下来问题多多,放弃了。数据流向如下图。

场景举例

实时计算课堂连接掉线率。此事件包含两个埋点上报,进入教室和掉线分别上报数据。druid设计的字段

flink的处理

将上报的数据进行解析,上报使用的是json格式,需要解析出所需要的字段然后发送到kafka。字段包含如下

sysTime,DateTime格式
pt,格式yyyy-MM-dd
eventId,事件类型(enterRoom|disconnect)
lessonId,课程ID
Druid处理

启动Druid Supervisor,消费Kafka里的数据,使用预聚合,配置如下

{
"type": "kafka",
"dataSchema": {
"dataSource": "sac_core_analyze_v1",
"parser": {
"parseSpec": {
"dimensionsSpec": {
"spatialDimensions": [],
"dimensions": [
"eventId",
"pt"
]
},
"format": "json",
"timestampSpec": {
"column": "sysTime",
"format": "auto"
}
},
"type": "string"
},
"metricsSpec": [
{
"filter": {
"type": "selector",
"dimension": "msg_type",
"value": "disconnect"
},
"aggregator": {
"name": "lesson_offline_molecule_id",
"type": "cardinality",
"fields": ["lesson_id"]
},
"type": "filtered"
}, {
"filter": {
"type": "selector",
"dimension": "msg_type",
"value": "enterRoom"
},
"aggregator": {
"name": "lesson_offline_denominator_id",
"type": "cardinality",
"fields": ["lesson_id"]
},
"type": "filtered"
}
],
"granularitySpec": {
"type": "uniform",
"segmentGranularity": "DAY",
"queryGranularity": {
"type": "none"
},
"rollup": true,
"intervals": null
},
"transformSpec": {
"filter": null,
"transforms": []
}
},
"tuningConfig": {
"type": "kafka",
"maxRowsInMemory": 1000000,
"maxBytesInMemory": 0,
"maxRowsPerSegment": 5000000,
"maxTotalRows": null,
"intermediatePersistPeriod": "PT10M",
"basePersistDirectory": "/tmp/1564535441619-2",
"maxPendingPersists": 0,
"indexSpec": {
"bitmap": {
"type": "concise"
},
"dimensionCompression": "lz4",
"metricCompression": "lz4",
"longEncoding": "longs"
},
"buildV9Directly": true,
"reportParseExceptions": false,
"handoffConditionTimeout": 0,
"resetOffsetAutomatically": false,
"segmentWriteOutMediumFactory": null,
"workerThreads": null,
"chatThreads": null,
"chatRetries": 8,
"httpTimeout": "PT10S",
"shutdownTimeout": "PT80S",
"offsetFetchPeriod": "PT30S",
"intermediateHandoffPeriod": "P2147483647D",
"logParseExceptions": false,
"maxParseExceptions": 2147483647,
"maxSavedParseExceptions": 0,
"skipSequenceNumberAvailabilityCheck": false
},
"ioConfig": {
"topic": "sac_druid_analyze_v2",
"replicas": 2,
"taskCount": 1,
"taskDuration": "PT600S",
"consumerProperties": {
"bootstrap.servers": "bd-prod-kafka01:9092,bd-prod-kafka02:9092,bd-prod-kafka03:9092"
},
"pollTimeout": 100,
"startDelay": "PT5S",
"period": "PT30S",
"useEarliestOffset": false,
"completionTimeout": "PT1200S",
"lateMessageRejectionPeriod": null,
"earlyMessageRejectionPeriod": null,
"stream": "sac_druid_analyze_v2",
"useEarliestSequenceNumber": false
},
"context": null,
"suspended": false
}

最重要的配置是metricsSpec,他主要定义了预聚合的字段和条件。

数据查询

数据格式如下

pt eventId lesson_offline_molecule_id lesson_offline_denominator_id
2019-08-09 enterRoom "AQAAAAAAAA==" "AQAAAAAAAA=="
2019-08-09 disconnect "AQAAAAAAAA==" "AQAAAAAAAA=="

结果可以按照这样的SQL出

SELECT pt,CAST(APPROX_COUNT_DISTINCT(lesson_offline_molecule_id) AS DOUBLE)/CAST(APPROX_COUNT_DISTINCT(lesson_offline_denominator_id) AS DOUBLE) from sac_core_analyze_v1 group by pt

可以使用Druid的接口查询结果,肥肠的方便~

Flink+Druid构建实时OLAP的探索的更多相关文章

  1. druid.io 海量实时OLAP数据仓库 (翻译+总结) (1)

    介绍 我是NDPmedia公司的大数据OLAP的资深高级工程师, 专注于OLAP领域, 现将一个成熟的可靠的高性能的海量实时OLAP数据仓库介绍给大家: druid.io NDPmedia在2014年 ...

  2. druid.io 海量实时OLAP数据仓库 (翻译+总结) (1)——分析框架如hive或者redshift(MPPDB)、ES等

    介绍 我是NDPmedia公司的大数据OLAP的资深高级工程师, 专注于OLAP领域, 现将一个成熟的可靠的高性能的海量实时OLAP数据仓库介绍给大家: druid.io NDPmedia在2014年 ...

  3. DataPipeline丨构建实时数据集成平台时,在技术选型上的考量点

    文 | 陈肃 DataPipeline  CTO 随着企业应用复杂性的上升和微服务架构的流行,数据正变得越来越以应用为中心. 服务之间仅在必要时以接口或者消息队列方式进行数据交互,从而避免了构建单一数 ...

  4. OPPO数据中台之基石:基于Flink SQL构建实数据仓库

    小结: 1. OPPO数据中台之基石:基于Flink SQL构建实数据仓库 https://mp.weixin.qq.com/s/JsoMgIW6bKEFDGvq_KI6hg 作者 | 张俊编辑 | ...

  5. 唯品会海量实时OLAP分析技术升级之路

    本文转载自公众号 DBAplus社群 , 作者:谢麟炯 谢麟炯,唯品会大数据平台高级技术架构经理,主要负责大数据自助多维分析平台,离线数据开发平台及分析引擎团队的开发和管理工作,加入唯品会以来还曾负责 ...

  6. Demo:基于 Flink SQL 构建流式应用

    Flink 1.10.0 于近期刚发布,释放了许多令人激动的新特性.尤其是 Flink SQL 模块,发展速度非常快,因此本文特意从实践的角度出发,带领大家一起探索使用 Flink SQL 如何快速构 ...

  7. 腾讯云EMR大数据实时OLAP分析案例解析

    OLAP(On-Line Analytical Processing),是数据仓库系统的主要应用形式,帮助分析人员多角度分析数据,挖掘数据价值.本文基于QQ音乐海量大数据实时分析场景,通过QQ音乐与腾 ...

  8. ElasticSearch做实时OLAP框架~实时搜索、统计和OLAP需求,甚至可以作为NOSQL来使用(转)

    使用ElasticSearch作为大数据平台的实时OLAP框架 – lxw的大数据田地 http://lxw1234.com/archives/2015/12/588.htm 一直想找一个用于大数据平 ...

  9. 使用 Kafka 和 Spark Streaming 构建实时数据处理系统

    使用 Kafka 和 Spark Streaming 构建实时数据处理系统 来源:https://www.ibm.com/developerworks,这篇文章转载自微信里文章,正好解决了我项目中的技 ...

随机推荐

  1. leadcode的Hot100系列--104. 二叉树的最大深度

    依然使用递归思想. 思路: 1.树的深度 = max (左子树深度,右子树深度)+ 1 . ------> 这里的加1是表示自己节点深度为1. 2.如果当前节点为null,则说明它的左右子树深度 ...

  2. 常用的方法论-SWOT

  3. Ural 2064:Caterpillars(思维暴力)

    http://acm.timus.ru/problem.aspx?space=1&num=2064 题意:有n只虫子在爬树,每个虫子往上爬ti距离后会往下掉落ti距离,每爬一个单位距离耗费一个 ...

  4. webpack4基础入门操作(一)

    基于webpack4实践:开始:打开控制面板,制定到创建Webpack的文件夹. 并创建初始配置文件package.json 输入命令:npm init -y,在文件夹中出现一个package.jso ...

  5. 嵊州D3T3 light

    嵊州D3T3 light 光恰似水 兄弟俩曾经 k 次受到过父母的物质激励. 一开始,兄弟俩的能力值为 1,最后,兄弟俩的能力值是 1 + (2 ^k−1)/ n . 当兄弟俩受到价值为 mi 的物质 ...

  6. Java学习笔记之---入门

    Java学习笔记之---入门 一. 为什么要在众多的编程语言中选择Java? java是一种纯面向对象的编程语言 java学习起来比较简单,适合初学者使用 java可以跨平台,即在Windows操作系 ...

  7. aspnetcore 刷新Session Id总是改变

    public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; ...

  8. python介绍、安装及相关语法、python运维、编译与解释

    1.python介绍 Python(英国发音:/ˈpaɪθən/ 美国发音:/ˈpaɪθɑːn/)是一种广泛使用的解释型.高级编程.通用型编程语言,由吉多.范罗苏姆创造,第一版发布于1991年.可以视 ...

  9. python基础知识六 文件的基本操作+菜中菜

    基础知识六 文件操作 ​ open():打开 ​ file:文件的位置(路径) ​ mode:操作文件模式 ​ encoding:文件编码方式 ​ f :文件句柄 f = open("1.t ...

  10. python 面向对象编程 - 小游戏

    面向对象写的小游戏 欢迎玩耍 class Omnicience: camp = 'Omniscience' def __init__(self, name, atk=100, hp=1000, mp= ...