zoukankan      html  css  js  c++  java
  • 记录一次线上处理5千万数据转换的经验

    前言:刚来新公司2个月就面临了一次线上真实数据的转换,这些数据异常重要,对我们公司来说就是客户的资源,说白了就是客户存在我们公司的钱,一旦处理失败将会影响极大,可以想象一下你存银行2万元,第二天查询却一分钱没有的情况,但是很遗憾此次处理没有处理好,造成了极大的影响,对我个人而言也是,后续我对此次数据转换失败进行了深刻反思,发现处理失败原因主要2个方面,1是流程不对,2是基础知识准备不足,现在我将把当时处理的过程以及后续如何处理整理出来,供大家参考,希望大家少入坑。

    1、当时处理数据的过程

    我们当时采用的是分批处理,第一次灰度处理200个用户,第2次灰度处理4万个用户,第三次是全量处理,那么现在我将记录当时处理经过,因为我是底层服务的负责人,所以这个需求是别的业务方提出来,然后进行需要和技术进行评审,完毕后由我给出技术方案。

    1.1、200个灰度用户处理

    当时由于是200个用户,那么我采取的处理就是以用户这个维度进行处理,然后从文件中读取业务方给的用户id,然后通过一些业务逻辑处理生成一批可执行的shell脚本。与此同时依然以用户的维度写了一个回滚方案,如果执行一断失败即可回滚。写完这些技术方案我们进行了一次技术评审,评审发现我处理的数据有一些过期或者失效的用户资源,然后我们讨论这些资源是否要处理,最后得出结果是不处理,然后我对生成的shell脚本进行修复,只取用户可用资源。后续我们也进行几次评审,确定了最终的shell脚本,到上线那天进行执行。处理完毕以后由我先进行测试,然后由qa进行测试,最后由pm进行验收,整个过程很顺利,没有出现异常情况,完美验收。

    1.2、40000个用户处理

    由于上次处理的比较顺利,让我们放松了警惕,认为这种方案没什么问题,只不过把上次的200个用户替换成40000个用户,在上线的那天进行执行,当时处理也是没有任何问题,pm也验收通过,但是过了2天陆续有销售反应客户资源比原始资源大了很多,最后查询发现原来pm给我的用户数据存在不少是重复的,我并没有进行重复过滤,导致在刷数据的时候重复刷,这样一来客户资源在原来基础上扩大很多,这个不管pm如何给的数据,但是我作为资源负责人应该考虑这些问题,这是出现的第一例case,后续我们对代码进行修复。

    1.3、全量数据处理

     全量处理方案,从数据库中获取所有的用户id,这里我采用了一个笨方法,采用java程序获取的,用户总量有好几百万,资源总量大约是5千万,然后我把用户id分别进行存储不同的文件中,然后采用多线程来执行从而提高效率,这个处理时长达8个小时(这里已经很明显不对了)因为中间有些逻辑必须调用服务所以处理时间比较长,但是最终还是得到了可执行的sql脚本,到了夜晚6点左右开始执行,先是有dba进行数据备份,然后由我把准备好的sql脚本交给dba进行执行(因为数据量大,只有dba通过特殊权限才可以快速执行),这些数据全部执行完毕大约用了40分钟,然后我们进行数据验证,上游各种服务上线,那天我自己也有job上线,导致从夜晚6点一直处理到第二天凌晨6点,然后pm验证后回家休息。但是噩梦在当天9点出现,有数万用户资源加多或加少或无法进行下载,然后开始修复数据(中间修复过程不在说了),整整修复3天,每天休息时间不超过4小时,终于得以遏止,很长一段时间我就在思考和反思问题出在哪里,以后应该去怎么应对这样庞大数据的迁移或者转换,到最后我发现主要死是流程的错误,导致一错再错,下面我写下我的总结

     2、总结

    对于大量数据的转换或者迁移我们应该遵从下面几个流程,这样会最大化的减小数据出错的几率

    2.1、详细的上线方案

    其实我们也有上线方案(对于任何修改线上的操作我们应该都称为上线),但是不够明确或者有太多的点没有指出来,上线方案应该包括下面几点

    2.1.1、上线前的准备

    1是上线前夕需要禁止用户对数据的操作、查询等避免操作期间因为用户的操作导致大量脏数据进入库中后续处理非常麻烦,2是在文档中明确每个业务方的负责人是谁在什么时间节点进行关闭用户操作资源界面,在我们操作期间没有明确这些事情,导致我们转换了数据,但是没有关闭数据操作入口导致还有不少是按照以前逻辑的方式把数据添加到库中。

    2.1.2、技术方案

    涉及数据迁移或者转换我们最重要的2步一个是获取数据另一个就是处理数据然后生成可执行的shell脚本

    数据源的获取

    1、数据源的获取一定是要通过sql脚本来获取,禁止用应用程序跑

    2、数据源可分库获取,把每个库的数据放在一个文件,文件取名采用库名_数据条数(如果量很大可以继续分割)库名_n_数据条数

    3、避免有重复数据,通过shell来对数据进行排重

    处理数据源生成可执行的shell脚本

    1、确认数据处理的维度,必须要以id为主键进行转换,切不可用用户id或者其他类型,尽量保证操作的幂等性,不管执行多少次结果不会改变

    2、按照数据源文件批量处理数据,在程序执行期间必须要打印日志,而且把处理异常的数据写入到一个error文件中,执行完毕后查询生成的数值是否和数据源要处理的数值一致,如果有异常去查看异常是否自己有考虑不全的地方,如果发现数值不一致也立即去排查原因,确保整个数据处理没有任何问题

    3、记录每个文件的处理时间,比如库1数据处理时间是1个小时,那么你单台机器只能处理2个应用程序,那么在上线的那天你都需要准备8台机器,这样还可以估算整个上线的时间

    4、程序尽量在服务器执行,因为你数据获取到处理数据到最后执行肯定是在上游的入口关闭以后,如果本地执行时间可能会太久,服务器执行就可以多申请几台服务器,把程序做成定时任务,然后同时跑,可能本机需要5个小时服务器20分钟足矣

    2.1.3、执行&测试

    1、如果整体数据量比较大还是建议交付给公司dba处理,他们权限比较大,处理效率会高不少

    2、执行前选取一条单独执行,然后验证看是否正确,避免出现sql错误的低级错误

    3、单库执行,然后进行测试,因为数据量巨大,一个个比对肯定不现实,可采用的方式查看备份库数据的数然后在查看按规则转换后的数据数量,如果一致的话在随机抽取数据进行验证,如果发现2中库的数量差别大,就需要检查是否出现漏掉数据没有处理

    4、全部执行,测试方式和上面一样,进行间接的测试来验证数据的正确性

    2.1.4、验收

    1、由pa进行覆盖性的点击每项功能查询是否出现异常

    2、由pm随机进行点击

    2.1.5、回滚

    如果数据一断出现自己无法把控的情况,可以先把情况告诉领导和各方负责人,经评审后联系dba对数据进行整体回滚,如果数据量比较小,可以在操作的时候记录数据主键,按照主键进行还原即可。

    2.1.6、上线时间节点和地点

    1、上线的地点可以提前预约一个会议室,数据转换进行投影,减少误操作

    2、上线节点,在每个节点要做什么都明确出来,做到井井有条

    因为我们目前处理项目重构和拆分阶段,有不少关于数据迁移转换的情况,后来我们也有大约3万多条数据迁移,完全按照上面的方式操作很顺利,至今没有反馈一个case。好了到这里就总结完毕了,数据处理需慎重,一定要考虑各种极端情况。

  • 相关阅读:
    DAOFactory复用代码
    WebUtils复用代码【request2Bean、UUID】
    过滤器复用代码【中文乱码、HTML转义】
    数据库复用代码【c3p0配置文件、数据库连接池】
    分页复用代码【Page类、JSP显示页面】
    AJAX应用【股票案例】
    JavaScript中的for in循环
    JSON【介绍、语法、解析JSON】
    javaScript【创建对象、创建类、成员变量、方法、公有和私有、静态】
    DOM【介绍、HTML中的DOM、XML中的DOM】
  • 原文地址:https://www.cnblogs.com/LipeiNet/p/7809567.html
Copyright © 2011-2022 走看看