大数据表同步

阅读更多

       前段时间,项目组有需求需要对一个千万级的表进行数据同步,目标并不复杂,将用户的一张表数据同步到我们自己的数据库中,当然,中间需要关联几张自己的表数据。

       一开始,客户考虑到安全等因素,只提供数据表导出的csv文件,大小约为700多M,数据量1200w。LZ脑子一热,不假思索使用spring+ibatis开始搞起了代码,一个小应用大概用了一上午编写完毕,当时LZ为自己的小成就还沾沾自喜。但在当天下午的实际测试时,LZ被着实打击了一番,系统根本支撑不下去,本机测试数据量达到100多W的时候,系统内存溢出,LZ试图增加环境变量,增加内存配置,数据在达到200w的时候,已经占用系统全部内存,LZ怀疑是自己的笔记本不给力,将代码部署到linux主机,开始使用默认最大2G内存,跑出来的效果和笔记本相当,没有内存溢出,程序直接假死。LZ主动将内存配置改为最大配置16G,想碰碰运气,系统最终在700W当口败下阵来。

       LZ没有气馁,想到了折中的办法,一次性加载数据吃不消,我就拆开了加载,每次加载10W条数据,看到数据一条条的入到数据库里,LZ很是欣慰,当时临近下班,LZ将程序部署linux后让它后台执行,打算第二天早上看执行结果。第二天的结果让LZ哭笑不得,13个小时,愣是没跑完,数据还在蜗牛般爬行,在程序运行了16个小时后,1200w数据终于入库完毕。

       功能完成了,但是同步效率奇差,肯定无法满足客户需要。LZ开始怀疑ibatis的性能问题了,都说ibatis是JDBC封装而来的,性能势必会有损耗。LZ花了个把小时把代码改造了一番,重新部署一番后开始了第二轮测试,结果还是有进步的,很明显,数据同步的速度有所加快,但是依然不能让人满意,LZ测算了一下跑完程序依然要8-9个小时。

       程序一边跑,LZ已经开始琢磨新的思路,自然而然想到的当然是多线程,没错,单一线程执行确实还是太慢了,LZ打算使用JDK的线程池,线程数量20个,每个线程数据量10W左右,程序最大内存2G,这样程序实时数据200W,当然由于使用了spring加载properties,所有参数都改为了可配置,根据部署环境的大小进行调配。到这个时候LZ也发现一个问题,由于数据源并非来自表结构,而是csv文件,想要多线程读取数据有些麻烦,且如果出现错误不方便定位数据位置。LZ最终牺牲了程序启动后的3分钟时间,将1200W条数据大小总量700M的csv文件,拆分成120个,每个6,7M大小的小文件,再使用多线程进行操作入库。部署linux环境后进行了第三轮调试,80分钟即可跑完程序,性能已经完全达到客户要求范围,将内存调整为最高16G以后,40分即可跑完程序,不过为了linux单板不挂机,安全考虑还是使用最高2G内存。

       LZ不敢自诩自己的思路和做法是最好的,或许有人可以把效率提高到半个小时甚至10分钟也说不准,但是通过这个需求的持续改进和最终的结果,LZ想让大家明白,想法永远比技术本身值钱,活学活用才能有创新和突破,程序可以改变世界,只要你肯动脑筋。

你可能感兴趣的:(同步,多线程)