什么是洗数据
洗数据指的是程序员写代码主动修改某些数据,非用户行为,
比如根据某些业务数据生成新列、某列中A值洗成B值、列拆分与合并。
为什么要洗数据
产品形态变化(升级或者退化),一个项目每个阶段都有不同的产品形态,产品形态往往影响程序员对底层数据结构的设计。
在老的设计不能满足新的产品形态的情况下,可能需要程序员对底层数据结构进行调整,调整过程可能会需要洗数据用以支持新的产品形态。
所以我们在设计底层数据结构的时候要在满足当前业务的前提下,尽可能高可扩展,产品经理的可能一会儿一个想法,更有可能频繁更换某业务的产品经理。
不洗数据行不行
一般情况下,可以通过某些兼容手段以现有数据结构通过代码转换支持新的产品形态。
但这应该只是一个临时方案,短时间内可以,如果长此以往,代码中充斥各种兼容代码,很难维护,甚至可能会影响下一次产品形态的变更。
而且兼容业务写在代码中,底层数据仍然没有变化,这对数据分析非常不友好,对新产品的数据分析他们也需要在做一层业务转换。
洗数据平台
使用线上服务器上执行洗数据程序
线上服务器执行洗数据程序有利有弊。
利:
1.可以复用一些业务逻辑
2.可以使用一些框架封装数据层的api redis、dao
弊:
1.洗数据往往需要很大内存,即使不需要也会影响服务的性能。
2.洗数据需要起多线程,一台服务起多线程,服务负载会很高。多台服务器多线程,又要考虑数据分区的问题,启动也很麻烦。
3.框架Dao是封装后的api,使用不如JDBC灵活高效。
4.一旦发现异常或其他状况,无法快速停止。
所以如果要使用线上服务器执行洗数据程序,可以在task区,但是如果依赖了其他服务的RPC接口,要考虑此服务在task区的承受能力
使用ins-ant-task执行洗数据程序
利:
1.ant项目是中间件提供的洗数据程序。它管理数据源、环境变量和日志。我们使用的时候只需要获取Connection,然后使用JDBC进行洗数据操作即可。
2.ant项目执行需要上级+茂叔审批。
3.ant项目可以重复执行,但是如果pom改动,则需要重新发起审批。
4.ant项目最大可以支持30g使用内存。
5.ant项目可以实时停止执行。
6.ant项目也可以使用RPC、zk、kafka、idp等中间件。
弊:
7.ant项目暂时无法操作memcached和redis,需要考虑如何同步一级缓存和二级缓存。
8.ant项目内使用RPC请求,目前流量会打到form区,需要考虑服务压力。
洗数据前
程序准备
预洗程序
洗数据之前,先进行预洗。
抽出一部分数据,执行洗数据逻辑,不执行写入操作,将结果输出到log,抽查log,检查有无明显错误。
根据预洗结果,评估影响记录条数。
预洗程序一般能在洗数据之前提前发现问题。
洗数据程序
1.编写高效的洗数据程序,需要使用多线程的方式去处理。
当然如果你对洗数据的效率没有要求,或者你的数据量很小,你可以考虑单线程处理,怎么简单怎么来。
我们可以分析一下洗数据的瓶颈主要在哪里,针对瓶颈进行优化。
洗数据需要进行频繁的数据库操作,或查询或插入或修改,并且都是批量操作,单独一条数据需要改值的暂不考虑。
我们需要把数据从数据库拿出来,放到内存中,根据产品经理的业务逻辑,转换成新数据,放到原来的地方或者新的地方。
那么洗数据的瓶颈主要在,内存和IO上。
内存可以暂不考虑,不够了可以加内存;
IO的问题十分影响洗数据的效率,所以我们可以选择多线程的方式充分利用多核CPU的特性,优化IO问题。
2.在洗数据程序中,我们使用生产者与消费者的经典模式进行读写分离,规避数据重复处理的问题。
生产任务的设计可能会影响整个洗数据程序的执行效率。
一般来说读线程读取一批数据,打包成一个任务交给写线程处理。适用于单表。
按表编号去分任务,一个线程处理完一张表后再去获取下一张表的任务。适用于分库分表。
4.洗数据线程数设置也不是越多越好
切换线程是需要消耗资源的,线程太多,会导致cup频繁切换,很多资源都浪费在了线程切换。
一般线程数选择,在不考虑对方压力的情况下,cpu密集型任务选择N+1、IO密集型任务选择2N+1 ,N为当前服务器的核数。
但是实际过程中,我们都需要考虑,Mysql的压力和服务器的压力还有内存使用,一般8~16线程能满足绝大部分洗数据(sql类)任务。
5.监控线程
在洗数据程序中起一个监控线程,1分钟或几分钟扫描一次当前程序执行情况,并输出到日志中。监控程序可以帮我们实时的知道当前程序的运行的进度和情况,
一般会扫描 内存使用情况、当前任务数、扫描行数、处理行数、错误数、时间、进度和一些其他你希望知道能帮你快速发现问题的数据。
6.依赖RPC接口的场景,根据服务承压进行限流。
验证程序
洗数据之后,执行验证程序。
对全量数据做一个检查,验证程序一般是将洗数据逻辑逆转看结果是否能还原或者用另外的方法再执行一遍看结果是否一致。验证程序一般能在洗数据之后发现一些之前没有预想到的数据问题。
changeLog和增量洗数据程序
在绝大部分洗数据场景中,我们都要面对增量数据可能产生的数据不一致问题,比如再洗数据过程中,我们已经将数据load到内存中进行处理,在回写数据的过程中,原数据已经发生变化,
导致回写的值并不是我们最终期望的值。此程序,能保证洗数据的最终准确性。
一般我们在项目的Dao层重写增删改方法,在完整实际操作后,向changelog表或者redis或者blog插入一条变动日志,总之能方便读取的数据源都行。
增量洗数据程序,读取log表中记录,对数据进行二次清洗,保证最终准确性。
回滚程序
回滚程序在比较重要的洗数据场景中,需要提前准备,并且需要在洗数据过程中进行备份,一般将新旧值记录到备份表或者blog中。
或者有其他的规避洗错数据的方案。
数仓数据分析
。。。。
各程序执行顺序
开启changelog -> 执行预洗程序 -> 执行洗数据程序 -> 开启增量洗程序 -> 执行校验程序
环境准备
根据洗数据场景判断是否可能产生主从延迟,如果会,需要对所有在这台实例上对主从延迟敏感的项目做摘除从库操作。
主从延迟出现的主要原因,就是主库产生了大量的binlog向从库同步,从库处理不过来了。
一般的批量insert 和 replace 由于mysql的优化不大可能出现主从延迟。
时间选择
洗数据可能会对Mysql实例造成压力和造成较高的主从延迟,应当在晚间或周末,客活少的时间段进行。
洗数据过程中
洗数据过程中需要关注什么
关注数据库压力
关注实例的cpu,最好控制在200以内。
关注主从延迟
关注主从延迟,在主从延迟消失后,恢复从库流量。
如果有RPC调用,关注被调用方的服务压力
关注服务的CUP、GC等信息,达到瓶颈的话,应当适当降速。
关注报警信息
关注群里的报警信息,一旦有风吹草动及时停止任务。
洗数据过程中的异常情况
洗错数据怎么办
向新表洗数据:truncate表之后重新洗
向新字段洗数据:重新洗直接覆盖
数据备份:对于将会覆盖原值的操作,一定要做好备份,一般备份原值和新值,为洗错数据之后做回滚操作。一般用备份表、blog备份。
回滚程序要不要提前准备好
一般不用,可以提前设计好回滚方案,目前还没遇到过需要回滚的场景。
过程记录
洗数据过程中最好做一些步骤记录,或提前计划好,防止突发情况,或者遗漏一些重要步骤。
洗完数据后的校验
洗完数据一定要Check吗
自信可以不用,出了问题背锅。
快速开发洗数据程序
对于经常洗数据的同学,要形成自己的洗数据体系,或者框架,这样在频繁的洗数据任务中能做到快速开发还能保证质量。
网友评论