国家图书馆,学习流式计算是种怎样的体验

时间:2023-01-14 22:05:57

有点怀念起北京来。

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

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

一段在国家图书馆学习流式计算的经历 ,就如同刀刻斧凿一般,刻在我的脑中 。

写这篇文章,想和大家聊聊这段学习流式计算的经历,希望对大家有所启发。

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

中国国家图书馆前身是筹建于1909年9月9日的京师图书馆,1931年,文津街馆舍落成(现为国家图书馆古籍馆)。新中国成立后,更名为北京图书馆。1987年新馆落成,1998年12月12日经国务院批准,北京图书馆更名为国家图书馆,对外称中国国家图书馆。

中国国家图书馆总建筑面积28万平方米,图书馆分为总馆南区、总馆北区和古籍馆,馆藏文献3768.62万册,其中古籍文献近200万册,数字资源总量超过1000 TB,是亚洲规模最大的图书馆,居世界国家图书馆第三位。

国家图书馆,学习流式计算是种怎样的体验

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

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

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

2 优惠券计算服务

2014年,我在艺龙旅行网促销团队负责红包系统。彼时,促销大战如火如荼,优惠券计算服务也成为艺龙业务系统中最重要的系统之一。

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

何为流式计算 ?

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

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

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

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

国家图书馆,学习流式计算是种怎样的体验

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

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

CTO 几次找团队负责人,并严厉批责成他尽快优化。

没想到,经过一个半月几次优化,系统的瓶颈依然明显,时不时运营同事会走到我们的工位附近,催促我们:“系统生效了么? ”

每到这个时候,我都感到很疑惑:“难道优惠券计算服务真的那么复杂吗? Storm 框架真的那么难以维护么? ”

3 国图学习Storm

想要揭开 Storm 神秘面纱的探索欲,同时解决公司技术问题的渴望,让我好几天晚上没睡好。

于是周六上午9点半, 我背着笔记本电脑来到国家图书馆。

学习一门技术,首先需要了解 Storm 的整体概念。

当我在官网上看到 Storm 的逻辑流程图时, 做为程序员,我第一次感觉到抽象之美

国家图书馆,学习流式计算是种怎样的体验

从源头流下来的水通过水龙头( Spout ),再经过层层转接头( Bolt )过滤,不就是我们想要的纯净水吗?

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

国家图书馆,学习流式计算是种怎样的体验

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

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

国家图书馆,学习流式计算是种怎样的体验

整个下午,我一直在查阅相关的资料,并结合上图思考:Nimbus, Supervisor ,Worker ,Task 这些名词到底是什么概念。拓扑到底会启动几个进程,每个进程内部线程模型是怎样的,颇有些庖丁解牛的味道

等天色已黑,我走出国图的大门,内心里面,有莫名的自信,我相信自己可以解决优惠券计算服务的问题了。

感觉自己就像仙剑奇侠传里的酒剑仙,伴随着激昂的 BGM ,拔剑四顾,斩妖除魔。

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

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

4 推动重构优化

虽然我大体了解了 Storm 的机制,但是我还不太了解优惠券计算服务整体逻辑,所以我必须梳理流式计算的整体流程

国家图书馆,学习流式计算是种怎样的体验

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

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

我找到负责优惠券计算服务的同事,导出相关日志。

分析日志后,令人惊奇的是:一次全量计算需要耗时4个小时,但步骤1竟然需要2个多小时,因为我们需要找到性能最薄弱的点,攻坚解决。那么应该优先优化酒店拉取服务

之所以拉取慢,是因为它的线程模型不够好,部署多个节点,每个节点只能有两个线程执行拉取任务。而且老代码年久失修,维护成本颇高,于是和团队负责人沟通后,我决定重构该服务。

在重构工程里,我必须做到如下两点:

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

因为 RocketMQ 刚开源不久 , 我将 RocketMQ 如何创建线程的知识点正好也用了上去。

这次重构也非常成功,我们将原来的老服务替换后,部署了3个节点, 每个节点8个 worker 并行拉取酒店信息 。

惊喜的发现,原来需要4个小时的全量处理时间缩短成了1个半小时,看来我这次重构非常成功,而且没有出现一例 BUG 。

优化结束了吗? 没有,当步骤1优化后,我们还有步骤2,步骤3可以优化。

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

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

我提了两点建议:

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

步骤三也并行进行,一位研发同学将原来的单条数据入库修改成批量入库。

当所有的优化完成后,原来4个小时的全量计算已经缩短成四十多分钟了。 以后,运营小姐姐就很少来我们工位了。(^-^)V

5 写到最后

我至今都记得 :

当我第一次看到 Storm 的逻辑图时,感叹中间件设计的抽象之美 ;

当我走出国图门口,那么的意气风发,那么的舍我其谁 ,我就是酒剑仙,御剑乘风来,除魔天地间 ,那些技术问题算什么,我一一给你们铲除;

当我和技术负责人保证我可以解决这个问题时,他不情愿和难以置信的表情;

当我和同事做酒店拉取服务 Code Review 时,当讲到如何创建线程时,同事们目瞪口呆的表情,我暗自窃喜:那是我学习 RocketMQ 的效果;

当酒店拉取服务上线后,全量数据计算的时间从4个小时变成1个半小时,我兴奋着拍着桌子,旁边的同事都神奇的看着我;

当我指出Storm 拓扑的问题时,我是那么笃定 ,最后优化结果也和我预期的一样 。

当优惠券计算服务优化完毕,一切尘埃落定,却又好像什么都没发生。


时光荏苒,生命中遇到越来越多的挫折,有的时候也会让人低落,但一想到那个时候的一往无前,顿觉生命又充满了希望,对于人生也有了新的感悟。

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

国家图书馆,学习流式计算是种怎样的体验