本文来自作者 jason 在 GitChat 上分享 「大数据项目性能优化实战分享」
编辑 | 琦玉
领导:项目 X 二期接近交付,目前性能问题比较严重,解决一下;原因可能是 kafka 单线程效率不足。
客户:该模块每 2 分钟经清洗计算生成的处理结果量应该在 13 万,实际查询到的数量只有 7 万。
原研发:可能是 kafka 性能问题,因为硬件上不足以修改多进程,多线程版本应该可以。
该模块数据流是读取 kafka--> 过滤 --> 写入 snappy。
git 私服下载项目代码后,整个人都不好了。两个模块,32 个工程,文档没有,注释没有,天了噜~
面对如此境遇,还是选择了优先踩在前人的肩膀上来实现(偷懒还是需要付出代价的~)。找到 kafka 单线程数据流所涉及的模块,准备进行多线程改造。
查看对应工程代码,数据流大致如图一:
众所周知,kafka partition 和消费者的关系是一个 partition 只能由一个消费者进行消费,而一个消费者可以消费多个 partition。
鉴于目标是确认性能问题点,便将单线程版本改为 8 线程,每个线程处理一个固定 partition 的数据。
然并卵,修改后的版本性能并没有提升,果然事情不会这么简单~转而询问研发得知由于项目周期紧,并未对 snappy 的性能进行过测试。好吧,测试走起。
在测试环境中进行基准测试,按照原代码中 2000 条每次批量写入的方式,发现单线程写入每次的耗时约 150-200ms。所以保守估计可以支撑 8000/s。
如此看来 snappy 也并未达到瓶颈。这一眼就能看穿的数据流,还能灵异事件了不成?
那么问题来了,这个性能问题是如何得出的?问题的本身是可靠的么?
再次询问客户,性能问题是怎么判断出现在模块 A?
场景还原:
图一为正常数据流;
为验证数据准确性,客户另开一条数据流,数据写入 redis,数据过期时间设置为 2 分钟:
现象:
新增测试方案:
记录阻塞队列读出的数据量,实际为每 2 分钟为 8 万左右;与 snappy 的数据量大致相同,而 redis 的数据量此时仍为 13 万左右。
那么问题来了,这是为啥子?
看一下 redis 官网的数据过期清除机制:
如上图,redis 的过期数据并不会实时全部删除,而是按照采样删除策略进行的。看一下 redis 中文网的翻译吧:
真相大白:验证方式不可靠。只是因为 redis 过期策略被误以为是过期便删除而导致。(ps:有兴趣的小伙伴对应中英文翻译一下,有木有发现中文版最后的翻译有 bug?-_-)
问题到此并未终止。客户说,我们做这个测试的原因是 snappy 中的存在超时数据。我们的验证方式有问题,那你们出方案解决数据延时问题吧。故事由此正式开始。
不知各位小伙伴有木有读开源项目或者类似工程代码,工作中的不少小伙伴每遇及此都很头痛。
其实不管是读优秀的开源项目还是一般的开发代码,都是一件有意思的事情。取其精华去其糟粕的过程是能力提升的良方。
讲个 demo 吧:
不知各位小伙伴有木有踩到过天天见的 if&else 的坑,是不是在写 if&else 的时候会不会关注只有 if 没有 else 可能导致的 bug。
在此次代码阅读过程中发现一个 if&else 导致的困扰许久的问题。伪代码场景还原一下:
子进程与调度进行心跳,心跳的同时进行时间同步。
由于篇幅所限