我与流式计算的故事

简介: 聊聊流式计算吧 , 那一段经历于我而言很精彩,很有趣,想把这段经历分享给大家。

聊聊流式计算吧 , 那一段经历于我而言很精彩,很有趣,想把这段经历分享给大家。

1 背景介绍

2014年,我在艺龙旅行网促销团队负责红包系统。

彼时,促销大战如火如荼,优惠券计算服务也成为艺龙促销业务中最重要的服务之一。

而优惠券计算服务正是采用当时大名鼎鼎的流式计算框架 Storm

流式计算是利用分布式的思想和方法,对海量“流”式数据进行 实时处理的系统,它源自对海量数据 “时效”价值上的挖掘诉求。

优惠券计算服务的逻辑是:每个城市每个酒店的使用优惠券的规则并不相同,当运营人员修改规则之后,触发优惠券计算服务,计算完成之后,用户下单时在使用优惠券时会呈现最新的规则。

优惠券计算服务是我们团队的明星项目,很多研发的同学都对 Storm 特别感兴趣 , 因为 Storm 的核心开发语言是 clojure , 比较小众。

于是,在团队内部,发现一个很有趣的现象:很多同学的办公桌上放着《clojure in Action 》这本书

clojure in  Action

艺龙开始发力移动互联网,业务量的激增,优惠券计算服务开始遇到了瓶颈。

比如运营人员修改全量规则时,整个计算流程要耗时一上午,也就谈不上实时计算了。

CTO 几次找团队负责人,并严厉批责成他尽快优化。经过一个半月几次优化,系统的瓶颈依然明显,时不时运营同事会走到我们的工位附近,催促我们:“系统生效了么? ”

我并不负责计算服务,每当同事被质疑时,我都感到很疑惑:“优惠券计算服务真的那么复杂吗? ” , 同时也跃跃欲试:“ Storm 真有那么难搞吗?”

我心中暗暗下定了决心,一定要弄清楚优惠券计算服务的逻辑 。

2 国图学习

北京有很多景点都让我流连忘返,比如史铁生小说里的地坛,满山枫叶的香山,如诗如画的颐和园,美仑美奂的天坛 。

在我心里,有一处很神圣的地方,它是知识和希望的象征,那就是国家图书馆

中国国家图书馆位于北京市中关村南大街33号,与海淀区白石桥高粱河、紫竹院公园相邻。它是国家总书库,国家书目中心,国家古籍保护中心,同时也是世界最大、最先进的国家图书馆之一

每到周末,当我想安静下来,专注思考时,我就会背着笔记本电脑来到国家图书馆。

选择自己喜欢的书,然后将笔记本电脑打开,一边看书,一边在电脑上写点笔记。

偶尔抬起头,望着那些正在阅读的读者,心里面感觉很阳光,觉得生命充满了希望。

我并不负责流式计算服务,但想要揭开 Storm 神秘面纱的探索欲,同时探寻优惠券计算服务为什么会这么慢的渴望,让我好几天晚上没睡好。

于是周六上午9点半, 我来到国家图书馆 ,想让自己安静下来,思考如何解决这个问题。解决问题的快感,是我一直追求的。

当我把笔记本电脑放平在桌上,我很兴奋,同时灵台一片澄清:优惠券计算服务的核心是 Storm ,那么我需要先了解 Storm 的整体概念

打开官网,浏览官网的文档,第一次看到 Storm 的逻辑流程图时, 做为程序员,我第一次竟然感受到抽象之美:从源头流下来的水通过水龙头( Spout ),再经过层层转接头( Bolt )过滤,不就是我们想要的纯净水吗?

storm逻辑图,已授权

其实我们原来都是 CRUD boy ,机械的使用那些框架,只会做增删改查,并不会思考框架背后的设计思路。 但框架到底是什么?从来没有思考过。 我一直觉得我很笨拙,学什么都很慢,但那一刻我突然恍然大悟:框架本身是将解决问题的思路抽象化,从而便于研发人员使用,把复杂的问题抽象成有美感,是需要功底的。

了解完 Storm 整体概念 , 下一步也就是大家熟知的写 Hello World 阶段了 。

我参考教程写了一个简单的 Storm 应用(简称:拓扑),在部署后,程序正常跑了起来。

我脑海里一直有一个疑问:“是不是优惠券计算服务的 storm 集群的配置没有调优,才导致计算的性能太差 ? ” 所以我必须去理解 storm 的并发度是如何计算的

整个下午,我一直在查阅相关的资料,并结合下图思考:Nimbus, Supervisor ,Worker ,Task 这些名词到底是什么概念,以及他们之间是如何交互的。

进而思考:拓扑到底会启动几个进程,每个进程内部线程模型是怎样的,颇有些庖丁解牛的味道。

这个习惯一直保持到现在,当我看到一个系统,我会下意思的去思考:“这个系统的线程模型如何,每次操作有哪些线程参于,他们之间如何交互”。我知道有更厉害的大牛,运行一行代码就知道 CPU 会运行的哪些指令,我做不到,但我觉得那就更加深刻了。

不管怎样,这一天,我的思绪经过多次的变化,兴奋,犹疑,放弃,阳光,激动。畏难心理一直存在,很多次想放弃,但好奇心一直鼓励着我。

等天色已黑,我走出国图的大门,脑子里全部都是 Storm 进程,线程模型,内心里面,有了莫名的自信。感觉自己就像仙剑奇侠传里的酒剑仙,伴随着激昂的 BGM ,拔剑四顾,斩妖除魔。

御剑乘风来,除魔天地间,有酒乐逍遥,无酒我亦癫。

一饮尽江河,再饮吞日月,千杯醉不倒,唯我酒剑仙。

3 找到瓶颈

当我理解了 Storm 的整体概念,接下来我需要去找到优惠券计算服务的性能瓶颈。这个时候,梳理计算服务整体流程非常关键。

优惠券流式计算拓扑

计算服务整体流程分为三个步骤 :

  1. 抽取数据:酒店信息拉取服务拉取酒店信息,并存储到水源头( Redis A/B 集群 ) ;
  2. 计算过程:Storm 拓扑从水源头获取酒店数据,通过运营配置的规则对数据进行清洗 ,将计算好的数据存储到水存放池 ( Redis C 集群) ;
  3. 入库阶段:入库服务水存放池获取数据,将计算结果存储到数据库 。

当我们把整个计算的过程拆分成 抽取-->计算 --> 存储 三个阶段的时候,计算服务的架构就变得异常清晰,那到底在哪个阶段最耗时 ,也成为我追查的目标。

优惠券计算服务当时没有详细的性能监控体系,所以我只能先从日志着手。 在运营同事触发全量计算后,分别观察三个阶段对应服务的日志:

  • 抽取数据:酒店信息拉取服务
  • 计算过程: Storm 拓扑
  • 入库阶段: 入库服务

令人惊讶的现象:一次全量计算需要耗时4个多小时,但抽取数据的任务竟然跑了2个多小时,和我预期完全不一样。

抽水泵

假如我把酒店信息拉取服务比作抽水泵,那么整个系统最大的问题竟然是抽水泵抽水马力不足

4 推进重构

为什么抽水泵抽水马力不足 ?

通过阅读源码,我发现因为线程模型不够好,应用在部署多个节点后,每个节点只能有两个线程执行拉取酒店信息。

怎么处理呢? 在原有代码上优化可行吗? 好像也不太容易,因为老代码最初是一个 C# 研发同事写的,他当时也不熟悉 JAVA ,从设计层面来讲,有很多冗余且不合理的代码,而且经过3年左右的维护,代码老化严重,于是我只能想到重构。

当我把想法和团队负责人沟通后,他有点半信半疑,他认为我的判断没有问题,但不确定我是否可以将系统重构好。 我那时候信心爆棚,主动请缨,打包票不会出问题的。可能是由于 CTO 逼的太紧了,他同意了。

在重构之前,梳理好系统的整体逻辑。

酒店拉取服务逻辑图

重构的重点原则有两条:

  1. 拉取服务可水平扩展,若性能不足时,增加服务节点即可提升性能;
  2. 配置文件可配置 worker 线程数量。

那思想层面,我已经做好准备了,那硬实力层面我有没有做好准备吗? 非常自信的讲,准备好了,因为我遇到了 RocketMQ

我在《我与消息队列的八年情缘》这篇文章写到:

2014年,我搜罗了很多的淘宝的消息队列的资料,我知道MetaQ的版本已经升级MetaQ 3.0,只是开源版本还没有放出来。

大约秋天的样子,我加入了RocketMQ技术群。誓嘉(RocketMQ创始人)在群里说:“最近要开源了,放出来后,大家赶紧fork呀”。他的这句话发在群里之后,群里都炸开了锅。我更是欢喜雀跃,期待着能早日见到阿里自己内部的消息中间件。

终于,RocketMQ终于开源了。我迫不及待想一窥他的风采。

因为我想学网络编程,而RocketMQ的通讯模块remoting底层也是Netty写的。所以,RocketMQ的通讯层是我学习切入的点。

我模仿RocketMQ的remoting写了一个玩具的rpc,这更大大提高我的自信心。正好,艺龙举办技术创新活动。我想想,要不尝试一下用Netty改写下Cobar的通讯模块。于是参考Cobar的源码花了两周写了个netty版的proxy,其实非常粗糙,很多功能不完善。后来,这次活动颁给我一个鼓励奖,现在想想都很好玩。

在重构酒店信息拉取服务时,我将 RocketMQ 如何创建线程的知识点正好也用了上去,并学习如何将模块拆分得更加合理。同时在重构过程中,不断 Review 新老代码的差别,确保核心逻辑正确。

非常幸运,大概一周时间,我就重构完了。

重构完成并不意味着结束,怎么验证呢 ? 我当时采取了两种方式:

  • 代码评审

    我拉着优惠券计算服务的同事,一起 review 代码 。整个过程,大家也并没有提出异议,并对我创建线程的技巧感到很好奇。我心中窃喜:”那是学习 RocketMQ 的“。

  • 测试环境数据验证

    我们将新旧两版服务同时触发,比对两个版本的数据的异同,将比对结果输出到日志文件,然后从中找到差异的地方,修复重构版的 BUG 。 然后在测试环境部署重构版,观察一段时间,确保无异常。

从编写第一行代码,三周时间,重构版终于上线了。 我将原来的老服务替换后,部署了3个节点, 每个节点8个 worker 并行拉取酒店信息 。

令人开心和激动的是,重构是非常成功的。 因为业务给我们的时间需求也是1个小时左右。一次全量计算从原来4个小时急速缩减到1小时15分钟,整个酒店拉取服务耗时40分钟左右。

我心里长舒一口气,内心吟诵李白的诗:"十步杀一人,千里不留行。事了拂衣去,深藏身与名。"

5 向前一步

前 Facebook COO 谢丽尔·桑德伯格写了一本书《向前一步》,我特别喜欢这本书的书名 。

在优化优惠券计算服务的前期,团队经过一个多月的时间,也没有什么成效。 我自己也犹豫:”我能不能解决这个问题?“ ,但最终我还是向前一步,并帮助团队大大提升了服务的性能,负责人也有了信心,他也敢投入资源优化Storm 拓扑入库流程

在阅读优惠券计算服务的代码中,我发现两个问题:

  1. 流式计算逻辑中有大量网络 IO 请求,主要是查询特定的酒店数据,用于后续计算;
  2. 每次计算时需要查询基础配置数据,它们都是从数据库中获取。

对于Storm 拓扑优化,我提了两点建议:

  1. 流式计算拓扑和酒店拉取服务各司其职,将流式计算中的网络 IO 请求挪到酒店拉取服务,将数据前置准备好;
  2. 基础配置缓存化,引入读写锁(也是 RocketMQ 名字服务的技巧)。

对于入库流程,一位研发同学将原来的单条数据入库修改成批量入库。

经过大家一起努力 ,优惠券计算服务的整体性能大大提升了,全量计算耗时已经变成40分钟了,再也不会有运营同事在我们的工位附近吐槽系统慢了。

6 写到最后

2014年,我向前一步推动了公司流式计算服务的优化,并取得了一点点进步。

时光荏苒,我已中年,生命中遇到越来越多的挫折,有的时候也会让人低落,但每当想起这个故事,我会深深感动于当时的一往无前。

当再次面临选择时,我希望自己也能够向前一步,想着如何帮助读者成长,或是实现一个产品帮助更多的人。


如果我的文章对你有所帮助,还请帮忙点赞、在看、转发一下,你的支持会激励我输出更高质量的文章,非常感谢!

相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
8月前
|
机器学习/深度学习 搜索推荐 算法
优秀的推荐系统架构与应用:从YouTube到Pinterest、Flink和阿里巴巴
优秀的推荐系统架构与应用:从YouTube到Pinterest、Flink和阿里巴巴
225 0
|
存储 消息中间件 缓存
腾讯看点基于 Flink 的实时数仓及多维实时数据分析实践
当业务发展到一定规模,实时数据仓库是一个必要的基础服务。从数据驱动方面考虑,多维实时数据分析系统的重要性也不言而喻。但是当数据量巨大的情况下,拿腾讯看点来说,一天上报的数据量达到万亿级的规模,要实现极低延迟的实时计算和亚秒级的多维实时查询是有技术挑战的。
腾讯看点基于 Flink 的实时数仓及多维实时数据分析实践
|
5月前
|
消息中间件 数据挖掘 Kafka
揭秘数据洪流中的救世主:Confluent与Flink的实时分析奇迹!
【8月更文挑战第9天】在现代数据处理中,实时数据分析至关重要。Confluent Platform与Apache Flink的组合提供了一套高效的数据流处理方案。Confluent Platform基于Apache Kafka构建,负责数据的收集、传输及管理;而Flink则擅长实时处理这些数据流,进行复杂分析。首先需配置Confluent Platform,包括设置Zookeeper、Kafka brokers及相关服务。
99 1
|
5月前
|
消息中间件 数据挖掘 Kafka
揭秘大数据时代的极速王者!Flink:颠覆性流处理引擎,让实时数据分析燃爆你的想象力!
【8月更文挑战第29天】Apache Flink 是一个高性能的分布式流处理框架,适用于高吞吐量和低延迟的实时数据处理。它采用统一执行引擎处理有界和无界数据流,具备精确状态管理和灵活窗口操作等特性。Flink 支持毫秒级处理和广泛生态集成,但学习曲线较陡峭,社区相对较小。通过实时日志分析示例,我们展示了如何利用 Flink 从 Kafka 中读取数据并进行词频统计,体现了其强大功能和灵活性。
98 0
|
5月前
|
监控 大数据 API
震撼来袭!Apache Flink:实时数据流处理界的超级巨星,开启全新纪元,让你的数据飞起来!
【8月更文挑战第6天】随着大数据时代的到来,企业急需高效处理实时数据流。Apache Flink作为一款开源流处理框架,以高性能、可靠性及易用性脱颖而出。Flink能无缝处理有界和无界数据流,支持低延迟实时分析,适用于实时推荐、监控及风控等场景。例如,在实时风控系统中,Flink可即时分析交易行为以检测欺诈。以下示例展示了如何使用Flink实时计算交易总额,通过定义Transaction类和使用DataStream API实现数据流的实时处理和聚合。Flink正以其强大的实时处理能力和高度可扩展性引领实时数据流处理的新时代。
75 0
|
8月前
|
SQL 数据挖掘 关系型数据库
实时计算 Flink版产品使用合集之有什么方法可以提高数据挖掘的速度
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
机器学习/深度学习 数据采集 自然语言处理
解密大数据分析:数据背后的故事
解密大数据分析:数据背后的故事
95 1
|
存储 消息中间件 SQL
看场景、重实操,实时数仓不是“纸上谈兵”
Hologres产品负责人合一谈谈他眼中的实时数仓!
2199 4
看场景、重实操,实时数仓不是“纸上谈兵”
|
数据安全/隐私保护 流计算