本文作者:易小华
最近我的团队将报表计算引擎从阿里的ads迁移到了kylin上,解决了非常多的问题,将一些我们的解决方案分享出来,希望对读者或者在用kylin的人有所帮助。
之前我们系统的报表都是基于阿里的rocketmq和ADS开发的,业务系统在业务代码中将数据同步到rocketmq中,然后ads再从rocketmq同步数据,再基于ads提供的api开发查询逻辑,前端还要开发报表展示的代码。这种方式上线以后,随着数据量的不断增长暴露出了很多缺陷。
基于以上问题我们觉得再继续用阿里的ads作为我们的报表计算引擎,后续问题会越来越多。因此我们尝试使用新的报表引擎,这个报表引擎对我们一定不是一个黑盒。
基于以上几个问题,在对tidb,druid,kylin,mdrill等各种开源系统进行调研以后,最终选择了kylin作为我们的报表计算引擎,一方面是sql支持度相对来说比其他系统好比如精确distinct功能,一方面是和hadoop的几个组件集成得非常好,tidb和已有hadoop组件集成得不大好,需要重新搭建集群代价很大。还有就是基于java开发很符合团队的技能特点,可以根据业务特点定制我们自己的版本。
选好了kylin这个报表计算引擎后,还需要解决的就是我们报表计算的数据延迟最大也要到分钟级别,这个可以通过kylin的kafka数据源来实现,配置方式见下面的链接。
http://kylin.apache.org/cn/docs/tutorial/cube_streaming.html
但是使用kafka还有一个问题就是业务系统的数据怎么实时的传输到kafka呢,之前都是在业务系统中编写数据发送逻辑到消息队列中,这种方式和业务系统耦合非常大,随便改点逻辑都需要依赖于业务系统上版本周期很长,沟通成本很大。因此我们采取了用阿里巴巴开源的canal抓取mysql binlog的方式,实时的去抓取mysql的增删改查数据,这种方式要开启mysql的binlog。Canal项目的主页:
https://github.com/alibaba/canal
有了canal抓取并解析binlog以后,还有一个问题要解决的是怎么让canal抓取到的数据可靠的传输到kafka中,基于canal和kafka的api自己开发的方式,成本很大,而且要考虑高可用,容错,扩展性等问题,再者我们的时间和开发资源也非常有限,因此我们基于flume的接口开发了一个canal source,充分利用flume的灵活性,扩展性,高可用,负载均衡和容错等特性,同时也可以和已有的source,channel和sink组件随意组合。
这样通过 canal+flume+kafka 和 kylin的streamingcube 特性,我们就很好的解决了数据分钟级别的延迟问题。
下一个要解决的问题就是数据的更新和删除的问题,这个我们是基于业务逻辑来解决的,当然我们在实现上会考虑好业务场景的通用性,每次更新和删除数据我们都不会去修改原来的数据,而是往kafka中插入新的数据并标记这条数据是删除,还是更新,并记录前后值的变化,同时在接入层面尽可能对数据进行去重处理,降低后续cube构建和sql编写的难度。
由于我们在数据层面和原来的变化了,因此我们还需要在sql层面进行改写,当然改写后的sql肯定要利用上kylin的预计算特性,否则查询速度很慢。
在解决数据实时更新和删除问题上,耗费了我们大量的时间,前后也讨论过很多种方案,而且实现起来需要对kylin的预计算特性有深入的了解,对维度设计要利用kylin的特性充分的进行精简,否则会走弯路。
下面是我们的model和cube界面:
五、 并发查询问题
接下来就是并发查询的问题了,由于kylin本身就带有cache特性,负载均衡而且采用的是预计算模式,因此应付并发上很好办,负载均衡这一块开始准备用nginx做负载均衡,后来觉得自己维护还是很麻烦,而且我们其他系统已经在使用阿里的SLB做负载均衡了,因此最终我们还是用SLB来做负载均衡。
最终我们做到了能够将数据在5分钟以内延迟下,支持实时的删除和更新操作,对报表各个维度的数据进行查询,汇总在1秒以内返回,明细在1到3秒内返回。
六、 使用superset报表开发方式
最后要解决的一个问题就是开发效率的问题了,之前我们的报表开发后台首先要手工编写大量的sql,然后使用spring和mybatis编写大量的业务逻辑,并通过微服务的方式暴露接口,然后前端再根据接口,编写前端展示代码,而且移动端,电脑端都要写一套。
这种方式开发周期长,耗费人力大,而且工作挑战不大也比较枯燥,大家都很痛苦,产品等得痛苦,开发开发得痛苦。
因此我们调研了几个前端的工具,后来发现了airbnb开源的superset这个好东西,操作简单,图表美观,而且单表不支持的情况可以通过自定义sql来支持。最关键的是kylin对它进行了很好的集成,链接如下:
http://kylin.apache.org/blog/2018/01/01/kylin-and-superset/
还有一个关键点是superset的图表可以通过iframe嵌入到网页中数据不是静态的而是随时更新的,还支持在电脑端和手机端展示,对数据和图表的权限控制也做得非常到位。基本满足了自助开发,然后嵌入到页面中展示的要求,可以大大节省我们的报表开发周期和开发工作量,甚至可以做到让产品自助拖拽式开发。
Superset Kylin数据源配置:
图表开发:
Iframe嵌入:
七、 最终的架构
八、 一些实现细节
跨站访问修改这个配置:
HTTP_HEADERS = {'X-Frame-Options': ' '}
免登录访问加入以下配置:
PUBLIC_ROLE_LIKE_GAMMA = True
Public 角色的permissions里把以下三个加上
can explore on Superset
can explore json on Superset
all database access on all_database_access
8.使用多个kylin实例的时候,会存在多台服务器上session信息不一致问题,,可以通过配置Kylin将Session信息保存到Redis中(或MySQL、MemCache等),实现多个Kylin实例的Session共享。
时间仓促,整体方案写出来了,具体细节和遇到的问题写得不够详细或者写得不对的对方,有需要进一步了解的可以留言交流。后续报表这一块我们会进一步做到自定义报表到时的维度挑战是一个更大的问题,肯定需要进一步的优化当前方案。