一次性集中处理大量数据的定时任务,如何缩短执行时间?

简介: 处理亿级数据的“定时任务”,如何缩短执行时间?

作者:58沈剑

问题抽象:
(1)用户会员系统;
(2)用户会有分数流水,每个月要做一次分数统计,对不同分数等级的会员做不同业务处理;
数据假设:

image

(1)假设用户在100w级别;
(2)假设用户日均1条流水,也就是说日增流水数据量在100W级别,月新增流水在3kW级别,3个月流水数据量在亿级别;
常见解决方案:
用一个定时任务,每个月的第一天计算一次。

//(1)查询出所有用户
uids[] = select uid from t_user;
//(2)遍历每个用户
foreach $uid in uids[]{
         //(3)查询用户3个月内分数流水
        scores[]= select score from t_flow
                  where uid=$uid and time=[3个月内];
         //(4)遍历分数流水
        foreach $score in scores[]{
                   //(5)计算总分数
                  sum+= $score;
        }
         //(6)根据分数做业务处理
        switch(sum)
        升级降级,发优惠券,发奖励;
}

一个月执行一次的定时任务,会存在什么问题?
计算量很大,处理的数据量很大,耗时很久,按照水友的说法,需要1-2天。
画外音:外层循环100W级别用户;内层循环9kW级别流水;业务处理需要10几次数据库交互。
可不可以多线程并行处理?
可以,每个用户的流水处理不耦合。
改为多线程并行处理,例如按照用户拆分,会存在什么问题?
每个线程都要访问数据库做业务处理,数据库有可能扛不住。
这类问题的优化方向是:
(1)同一份数据,减少重复计算次数;
(2)分摊CPU计算时间,尽量分散处理,而不是集中处理;
(3)减少单次计算数据量;
如何减少同一份数据,重复计算次数?
image

如上图,假设每一个方格是1个月的分数流水数据(约3kW)。

3月底计算时,要查询并计算1月,2月,3月三个月的9kW数据;
4月底计算时,要查询并计算2月,3月,4月三个月的9kW数据;

会发现,2月和3月的数据(粉色部分),被重复查询和计算了多次。
画外音:该业务,每个月的数据会被计算3次。
新增月积分流水汇总表,每次只计算当月增量:
flow_month_sum(month, uid, flow_sum)
(1)每到月底,只计算当月分数,数据量减少到1/3,耗时也减少到1/3;
(2)同时,把前2个月流水加和,就能得到最近3个月总分数(这个动作几乎不花时间);
画外音:该表的数量级和用户表数据量一致,100w级别。
这样一来,每条分数流水只会被计算一次。
如何分摊CPU计算时间,减少单次计算数据量呢?
业务需求是一个月重新计算一次分数,但一个月集中计算,数据量太大,耗时太久,可以将计算分摊到每天。
image

如上图,月积分流水汇总表,升级为,日积分流水汇总表。
把每月1次集中计算,分摊为30次分散计算,每次计算数据量减少到1/30,就只需要花几十分钟处理了。
甚至,每一个小时计算一次,每次计算数据量又能减少到1/24,每次就只需要花几分钟处理了。

虽然时间缩短了,但毕竟是定时任务,能不能实时计算分数流水呢?
每天只新增100w分数流水,完全可以实时累加计算“日积分流水汇总”。
image

使用DTS(或者canal)增加一个分数流水表的监听,当用户的分数变化时,实时进行日分数流水累加,将1小时一次的定时任务计算,均匀分摊到“每时每刻”,每天新增100w流水,数据库写压力每秒钟10多次,完全扛得住。
画外音:如果不能使用DTS/canal,可以使用MQ。

总结,对于这类一次性集中处理大量数据的定时任务,优化思路是:
(1)同一份数据,减少重复计算次数;
(2)分摊CPU计算时间,尽量分散处理(甚至可以实时),而不是集中处理;
(3)减少单次计算数据量;
希望大家有所启示,思路比结论重要。

最后
欢迎大家一起交流,喜欢文章记得点个赞哟,感谢支持!

相关文章
|
Web App开发 编解码 Java
B/S基层卫生健康云HIS医院管理系统源码 SaaS模式 、Springboot框架
基层卫生健康云HIS系统采用云端SaaS服务的方式提供,使用用户通过浏览器即能访问,无需关注系统的部署、维护、升级等问题,系统充分考虑了模板化、配置化、智能化、扩展化等设计方法,覆盖了基层医疗机构的主要工作流程,能够与监管系统有序对接,并能满足未来系统扩展的需要。
705 5
|
11月前
|
测试技术 数据处理 Python
Python列表推导式:简洁高效的数据处理利器
Python列表推导式:简洁高效的数据处理利器
465 80
|
6月前
|
传感器 人工智能 编解码
2025年11月,全球数字人技术竞技场与数字化应用技术指南
2025年,全球数字人技术进入多维竞技时代。中美中东等地在技术深度、场景广度与生态厚度上全面比拼,推动数字人从“形似”到“神似”、从营销工具到产业赋能、从技术单打独斗到价值共生的跃迁,掀起一场重塑产业与人文交互的创新浪潮。
|
9月前
|
缓存 Linux 云计算
OOM 杀进程 or 应用卡顿?该如何抉择
阿里云操作系统控制台推出了 FastOOM 功能,支持节点以及 Pod 级别的用户态 OOM 配置,通过提前介入杀进程的方式避 Near-OOM 导致的抖动夯机。
420 0
|
机器学习/深度学习 存储 运维
分布式机器学习系统:设计原理、优化策略与实践经验
本文详细探讨了分布式机器学习系统的发展现状与挑战,重点分析了数据并行、模型并行等核心训练范式,以及参数服务器、优化器等关键组件的设计与实现。文章还深入讨论了混合精度训练、梯度累积、ZeRO优化器等高级特性,旨在提供一套全面的技术解决方案,以应对超大规模模型训练中的计算、存储及通信挑战。
882 4
|
Docker 容器
Docker部署minio-arm64版本,阿里官方推荐
Docker部署minio-arm64版本,阿里官方推荐
|
监控 小程序 前端开发
小程序全栈开发中的WebSocket实时通信实践
【10月更文挑战第3天】随着移动互联网的发展,小程序因便捷的用户体验和社交传播能力,成为企业拓展业务的新渠道。本文探讨了小程序全栈开发中的WebSocket实时通信实践,包括其实时通信、长连接及双向通信的特点,并通过实时聊天、推送、游戏和监控等功能的实现,展示了WebSocket在小程序中的应用。开发者需注意安全性、性能及兼容性等问题,以保障小程序的稳定运行和用户体验。
393 7
|
存储 测试技术 项目管理
【北京大学 软件工程】三、软件需求
本文介绍了软件需求工程的基础概念和流程。首先定义了需求及其获取,强调需求是描述系统功能、性能等方面的要求,并需具备必要性、无歧义性、可测性、可跟踪性和可测量性五大基本性质。接着阐述了需求的分类,包括功能、性能、外部接口、设计约束和质量属性五类,并详细说明了各类需求的具体内容及示例。此外,还探讨了需求发现的技术,并分析了每种技术的应用场景与优缺点。最后,文章解释了需求规约(SRS)的概念、格式和作用,指出它是软件开发组织与用户之间的技术合同,用于指导项目管理、产品设计、测试计划和用户手册的编写。需求规约不应包含设计细节或项目规划信息,而是专注于明确系统的功能性与非功能性要求。
1095 1
【北京大学 软件工程】三、软件需求
|
JavaScript 前端开发 C++
【Vue.js的终极对决】服务端渲染VS客户端渲染:一场关乎速度与SEO的生死较量!
【8月更文挑战第30天】Vue.js 是一个流行的 JavaScript 框架,支持服务端渲染(SSR)和客户端渲染。SSR 在服务器生成完整 HTML,有利于 SEO 并缩短首屏加载时间,但增加服务器负担;客户端渲染则在浏览器生成页面,提升交互性,降低服务器负载。本文通过代码示例对比两者优劣,并提供选择指南,帮助开发者根据 SEO 需求、交互性需求及服务器资源等条件,选择合适的渲染方式,从而优化应用性能和用户体验。
454 0
|
JavaScript Java 测试技术
基于springboot+vue.js的论坛系统附带文章和源代码设计说明文档ppt
基于springboot+vue.js的论坛系统附带文章和源代码设计说明文档ppt
268 1

热门文章

最新文章