一个处理大数据的后台服务(已废弃)

这其实是个小功能,但是我觉得非常有意思。因为这个业务不但总体数据量大,单个数据体也是超大个的。业务场景是这样的:我们需要把数据库的视频和专辑数据给搜索那边。搜索那边规定好了数据的格式和传输方式。全量数据用文件的方式放到hadoop节点上,增量数据用消息队列发送。

原计划是每周发送一次全量,增量数据是分钟级。但是实际上最后全量是一条跑一次。因为发现我的程序执行的辣么快。为啥快呢?当然啦,我进行了好几次优化,竟然还通宵了。不过,最重要的基础是……,我就不说我的机器配置了。请看我的JVM参数设置:

真心有做土豪的感觉。公司对我太好了,感动的泪如雨下!

下面说一下业务模块,共7个业务模块,使用ScheduledExecutorService启动10个定时任务,分别是:视频全量任务,视频增量任务,视频手动补发任务,专辑全量任务,专辑增量任务,专辑手动补发任务,磁盘清理任务和三个将数据缓存到内存任务。

总体上使用了Spring的控制反转功能加载资源。连Dubbo的资源管理也是用的Spring,只能说明这个控制反转太好用了。持久层框架,我用的是我们大乐视自己研发的mango。

视频和专辑的手动补发很简单,就是用ServerSocket开了两个端口监听http请求。然后解析socket的输入流,从输入流里面的参数里提取出需要重发的id列表处理后(处理过程就是增量的逻辑)在输入流中写入响应。因为这个,我可不可以说自己做过socket编程啊!

磁盘清理任务是因为我总共就500G的硬盘。每次执行完全量,一天的数据共80个G,所以全量执行前要先执行清理,只保留4天的全量。

我们的视频目前是近千万条的数据,专辑有百万条数据,数据需要查询几个表汇总出数据。而我有125G的内存,所以我将一些常用的字典数据缓存到map里,三个缓存任务就是干这个用的。

先说全量:

为了减少资源之间的等待,我把全量数据分成600个线程,每个线程独立写一个文件。线程执行完进行gz压缩。搜索那边访问我们的磁盘只取压缩后的数据。取到的文件他们那边负责归并。专辑也是一样,但是经过测试,分成了440个线程。因为是24核物理机,经过测试,开启了50个线程的线程池跑这总共的1040个线程。程序启动时将这些全量视频处理线程和全量专辑处理线程都创建好,放到map里。

全量在执行前,会执行线程业务分配线程。

先说视频的分配线程。因为每个视频都要跑所有的数据表,且数据的大小相对比较均匀。ID是数据库里的自增主键。有近千万条数据。首先查询数据库的最大ID和最小ID。用这两个ID的差除以线程数600得到ID间隔。循环从map里取出一个全量视频处理线程,将最小ID最为处理开始ID,最小ID加上ID间隔最后处理结束ID,还有给它分配的线程号传给这个视频处理线程。下一个以上个处理结束ID作为处理ID继续分配。分配到最后一个时,我会把处理结束ID加上1000。这是为了应对执行期间的新增。

专辑因为一条数据中不但要包含专辑本身的信息,还需要将专辑下的视频信息一起合成一条信息。有的专辑下只有一个视频。有的专辑下面却有3万多条视频,跑这一条数据就需要近20分钟。所以线程分配的时候,首先将所有专辑下视频数多于1000的作为超大视频将ID存到一个list里(1000多条)。将剩下的ID放到另外一个list里(近百万条数据)。将线程数均分成两份(之所以不直接用440条是因为视频和专辑全量线程数是可配置的)。一部分按ID数均分给超大视频。另一部分按ID数分配给其他视频。将要执行的ID列表和线程号作为参数传给专辑处理线程。那么对于超大视频线程来说,它会处理2到3个ID。对于其他的线程,处理的视频数是几千。

(此处假装我附上代码,代码是公司资源)

当然线程业务分配线程会创建一个日期命名的目录将当天的视频或专辑数据都放在一个目录下。

然后是视频或专辑创建线程。程序一开始将一个AtomicInteger进行incrementAndGet。在此线程结束先gz压缩,然后将此AtomicInteger进行decrementAndGet。这是用来判断是否所有的线程都执行完的,因为之后要生成一个视频创建结束的标志。因为有两台机器。搜索首先检查当天数据是否有结束标示,没有就取另一台的数据。之所以要传线程号就是为了作为磁盘文件名的一部分。文件名和目录结构如下图:

(磁盘上的文件)

创建视频的时候,首先查询在开始和结束时间段内的视频数。如果这个地方用limit来查,不能有效利用索引,数据量又大,查询速度慢好几十倍。

如果这个视频数小于一次性处理数据量(经过测试,我定到了800)。就一次性处理。如果这个视频数大于这个数据,就循环处理,一次处理800条。这样既提高的运行速度又保证了不占用过多的内存。

介于当时考虑的细节过多,描述下来总共需要1万字以上,主要说说当时的要求是尽量快的执行,我在调整参数和逻辑的时候,CPU密集和IO密集两种情况交替出现。几个通宵的尝试才调到了最优。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏北京马哥教育

一秒内诊断 Linux 服务器的性能

60,000 毫秒内对 Linux 的性能诊断 当你为了解决一个性能问题登录到一台 Linux 服务器:在第一分钟你应该检查些什么? 在 Netflix,我们有...

3276
来自专栏生信技能树

我的第一R包- 生信配置文件大全

大家好,我是李剑峰,生信技能树论坛的VIP小编,目前在上海交通大学医学院附属瑞金医院进行研究生阶段的学习,主要研究方向是生物信息学、医学信息学、大数据综合分析、...

3629
来自专栏程序员八阿哥

年薪20万Python工程师进阶(7):Python资源大全,让你相见恨晚的Python库

用来访问第三方 API的库。 参见: List of Python API Wrappers and Libraries。

2952
来自专栏北京马哥教育

性能调优攻略

关于性能优化这是一个比较大的话题,在《由12306.cn谈谈网站性能技术》中我从业务和设计上说过一些可用的技术以及那些技术的优缺点,今天,想从一些技术细节上谈...

3274
来自专栏编程札记

Goroutine并发调度模型深入之实现一个协程池

7425
来自专栏非著名程序员

看大神如何玩转微信小程序日历插件?

1613
来自专栏机器人网

终于全了!ABB机器人学习资料

? 1、安全 自动模式中,任何人不得进入机器人工作区域 长时间待机时,夹具上不宜放置任何工件。 机器人动作中发生紧急情况或工作不正常时,均可使用E-stop键...

3573
来自专栏微信公众号:Java团长

你的项目应该如何正确分层?

说起应用分层,大部分人都会认为这个不是很简单嘛 就controller,service, mapper三层。看起来简单,很多人其实并没有把他们职责划分开,在很多...

2003
来自专栏Linyb极客之路

低延迟系统的最佳实践

低延迟意味着更快的响应时间,更快的性能,以下最佳实践大部分来自于Quora等问题提炼:

1012
来自专栏恰同学骚年

操作系统核心原理-5.内存管理(中):分页内存管理

在上一篇介绍的几种多道编程的内存管理模式中,以交换内存管理最为灵活和先进。但是这种策略也存在很多重大问题,而其中最重要的两个问题就是空间浪费和程序大小受限。那...

1263

扫码关注云+社区