blink+tablestore实现无限扩展性,高实时汇总计算及排行榜

问题背景

最近开始了一个全新的ugc项目,要求对用户的点赞,评论,转发等等的数据进行统计按权重进行积分,并进行排序。要求排行榜的实时性在5分钟内,最好能进行全实时的计算,要求高度的准确性。
实际工作中这样的场景是非常多的,主要是各种数据的实时汇总,比如用户购买总量,用户点赞总量,
商品销售总量,不是要历史的数据而是要现在最新的总量数据,这个数据可能是1天的汇总,也可能是数年的汇总。另一方面是进一步依靠这些数据进行排行榜和推荐,将最热最火的信息推送给用户。
现在这样的数据汇总计算排行通常的方案是Lambda架构,用户数据既需要进入消息队列系统(New Data Stream如metaq)作为实时计算任务的输入源,又需要进入数据库系统(All Data如HBASE)来支持批处理系统,最终两者的结果写入数据库系统(MERGED VIEW),展示给用户。如下图
blink+tablestore实现无限扩展性,高实时汇总计算及排行榜
实质是使用odps等离线工具跑出T-1天的数据,使用flink,storm跑实时计算的数据,然后再将两个数据进行累加,这样就可以算出当前实时总量的数据。
一般的数据如下图这样储存,之后再和实时数据聚合
blink+tablestore实现无限扩展性,高实时汇总计算及排行榜

Lambda问题

但是
第一这样的框架有两套系统需要进行维护,如果有业务逻辑的变更需要修改两个地方的业务逻辑。需要申请两套资源,并且还需要编写数据汇聚的相关程序,实现比较复杂,也比较浪费资源。
第二在跑离线计算时候,如果出现t-1天计算任务没有及时跑完的情况,或者因为某些原因离线汇总没及时将数据汇总,那么实时计算的数据将是错误的。虽然这种情况比较少见,但是如果是某些推荐排行榜,影响是很大的。
集团内部也有一些相关的方案,比如批流一体的解决方案,传送门,虽然进行了不少的优化,但是维护两套存储结构,历史数据和实时数据的问题还是存在。
那么有没有只用流式计算就可以解决掉历史数据和实时数据的问题呢?当然是有的,通过整合集团两大大数据神器,完全可以做到实时历史数据排行。

Table Store

表格存储(Table Store)是阿里云自研的NoSQL多模型数据库,提供PB级结构化数据存储、千万TPS以及毫秒级延迟的服务能力。在实时计算场景里,表格存储强大的写入能力和多模型的存储形态,使其不仅可以作为计算结果表,同时也完全具备作为实时计算源表的能力。
通道服务是表格存储提供的全增量一体化数据消费功能,为用户提供了增量、全量和增量加全它量三种类型的分布式数据实时消费通道。实时计算场景下,通过为数据表建立数据通道,用户可以以流式计算的方式对表中历史存量和新增数据做数据消费。利用表格存储存储引擎强大的写入能力和通道服务完备的流式消费能力,用户可以轻松做到数据存储和实时处理all in one!传送门

Blink

Blink是阿里云在Apache Flink基础上深度改进的实时计算平台,同Flink一致Blink旨在将流处理和批处理统一,但Blink相对于社区版Flink,在稳定性上有很多优化,在某些场景特别是在大规模场景会比Flink更加稳定。Blink的另一个重大改进是实现了全新的 Flink SQL 技术栈,在功能上,Blink支持现在标准 SQL 几乎所有的语法和语义,在性能上,Blink也比社区Flink更加强大,特别是在批 SQL 的性能方面,当前 Blink 版本是社区版本性能的 10 倍以上,跟 Spark 相比,在 TPCDS 这样的场景 Blink 的性能也能达到 3 倍以上。[传送门]
(https://yuque.antfin-inc.com/rtcompute/doc/kknfig)

思考

从理论上考虑批处理数据只是流数据的有边界数据。如果blink的state能存储无限时长的数据,是完全可以做历史数据和实时数据的累加的。然而现在blink的state的默认时间是1.5天,就算通过配置延长,也不能无限的延长,这样代价太大了。
那么能不能将blink实时计算的数据存储到某个地方,然后累加的时候再拿出来进行累加呢。
blink的维表似乎提供了类似的存储能力,但是很遗憾经过测试,blink的维表数据更新是非实时的,这样对于实时计算的系统累加的数据将不准确。

解决问题

在这样的情况下,我们发现了TableStore,TableStore在4.10.0版本,提供了一个非常有趣的功能,原子计数器。可以在原数据的基础上进行累加计算。[传送门]
(https://help.aliyun.com/document_detail/89014.html?spm=5176.10695662.1996646101.searchclickresult.3986295a6qfhM7)
如果我们获取增量数据,再在blink中进行count和sum的计算,然后按照秒,分钟纬度进行开窗,然后将结果传入tablestore的原子计数器,那样不就是保证了在历史数据之上可以进行累加了吗?
因此现在我们的系统架构变成了这样
blink+tablestore实现无限扩展性,高实时汇总计算及排行榜
对比
lambda架构
blink+tablestore实现无限扩展性,高实时汇总计算及排行榜
将Lambda架构的2套复杂系统,变成了一套流程非常简单的系统。业务逻辑,资源全部都在一套系统中实现,存储也只有一个地方,大大减少了架构的复杂度和资源的消耗,做到了真正的批流一体。
使用这套系统有两个重点

1.需要在blink中进行开窗的聚合计算,tablestore原子计数器,单热点的性能巅峰在300tps,如果使用5s一个开窗计算,测试100万数据情况下,2cu情况下blink处理毫无压力,平均在13000tps左右。tabletstore因为5s才一次写入更是毫无压力。因为tablestore和blink都可以进行无限制扩展,实际处理能力其实是无上限的,实际上你想要它多快它就有多快,想要它吞吐量多大就吞吐量就有多大。极度适合ugc场景,无限多商品场景,极度舒适。
2.blink的源表最好使用系统时间开窗,这样不会因为使用业务数据,而业务数据延时到达而丢弃数据,造成数据不准确。传送门
代码如下:
blink+tablestore实现无限扩展性,高实时汇总计算及排行榜
3.blink结果表要使用tablestore的原子计数器能力,需要写自定义结果表,传送门
下面是自定义结果表中间使用原子计数器的核心代码
blink+tablestore实现无限扩展性,高实时汇总计算及排行榜

最后的总结

老板交待的事情都办完了,超额完成任务。那么有哪些值得思考和改进的呢?
1.自定义结果表现在采取的是逐条写入,如果改成批量写入那肯定还要更快,数据快来吧
2.其实tablestore的原子计数器就是一个处理累加并发的函数功能,那么有哪些存储提供类似的功能呢?
redis,mysql update set x=x+1 for update,等等。只要你敢想,这些都不是问题。因为我们是ugc的性质,所以推荐使用Tablestore来实现,扩展实在太方便了。但是如果使用mysql等数据库,路径要比tablestore更复杂些。比如mysql如果同步源表需要的路径如下
blink+tablestore实现无限扩展性,高实时汇总计算及排行榜
对比 tablestore到blink只需要
blink+tablestore实现无限扩展性,高实时汇总计算及排行榜
tablestore把全量,增量的事情全做了,真正和blink是无缝集成的。
3.blink的结果表可以自定义其实提供了很多的扩展性,有兴趣的同学可以去实现mysql的事务操作,这样可以很多涉及强事务的处理任务都可以用blink来完成了。
据说好的架构都要起个响亮的好名字,我就把这个架构叫kurry,改变NBA的男人?
在实现这套架构过程中,得到了@大辂,@周灿 ,@纯庚,@王玖的热情帮助,特别感谢@张冉在blink和tablestore集成调试中帮忙解决的各类问题,大大节省了调试的时间。

上一篇:Kafka单机模式和集群模式环境搭建


下一篇:两会总结 智慧城市应该怎么逐步落地