第三方数据未拉取取不出来 系统之间的数据对接和传输,产品经理视角的万字总结
2. 数据库对库同步
接口完成的是信息的传输,相对来说比较保守,易于保护敏感信息。而数据库同步实际就是表对表的共享,相对接口就大方多了,因此多发生在企业内部两小无猜的系统之间。
数据库同步有这么几种办法:
1)使用中间表
例如:B系统要用A系统的数据,可以新建一个数据库DB,A系统将数据写入DB,B系统再到数据库中读取数据。
也就是将数据放进一个中间表中,A、B两个系统都对这个表有访问权限,这样的好处就是选择性地将一大批数据共享出去。
2)直接调取对方数据表
这个方式就是在B系统在开发时,在代码中加载A系统的数据表,直接从数据表中取数据。这就是实时拉取对方的数据,B系统自己本地不做表保存。比较省,事但是耦合性较大,数据量大的时候不建议。
3)同步对方的数据表
直接将对方的数据表copy一份过来,并保持实时同步,otter技术就是常用的一个方法。
otte可以将mysql的数据同步至另外mysql或者,也支持双向同步(即A库同步给B库,B库也同步给A库)、文件同步等,主要应用应用是多数据中心、BI系统抽取数据、灾备。
该方式需要DB协助配置。也就是做了一个mysql的同步平台(带WEB管理界面),在界面上,你可以定义相应的映射规则,otter进程就会根据你定义的规则读取,并更新到目标库中去。
该方式主要用于内部系统之间(一般一个公司的才这样)库对库的传输,可以实现数据的相互同步更新。建议应用在数据量大的时候,或者基础数据对周边兄弟系统提供基础支持的时候。优点是占用资源少,交互更加简单可靠。
当连接B的系统越来越多的时候,由于数据库的连接池是有限的,导致每个系统分配到的连接不会很多,当系统越来越多的时候,可能导致无可用的数据库连接。
这时候otter比较适合。而两个不同公司的系统,不太会开放自己的数据库给对方连接,因为这样会有安全性影响。
3. 文件包共享方式
一些第三方公司为了保密,不愿意提供接口,那么会把文件存在类似网盘或网页上,供需求方下载。
双方系统约定文件服务器地址、密码、文件命名规则、文件内容格式等,通过上传文件到文件服务器,进行数据交互,对大数据量的也很适合。这就是一种异步的上传下载机制,双方的操作割裂开,并且一旦上传可以被多个需求方使用。
比如:第三方支付公司与需求方约定好SFTP服务器(一种文件服务器,可以理解为网盘)的账号密码,然后支付公司将账单数据上传到SFTP服务器上,那么需求方就可以登陆SFTP客户端,进行下载、解析,然后保存使用。这也实现了数据在服务器之间的传输。
实际上这些数据本身也是加密的,所以只有协议的公司才能拿到解码钥匙。长期合作的公司就会持续更新,授权的公司就可以持续下载和解析。这里就有一个下载频率的问题,一般使用定时任务按一定频率去下载。并且要考虑丢包的机制。
案例:
到SFTP服务器抓取并解析WP支付平台的账单明细,方案如下:到SFTP服务器找到文件路径,筛选出需要的类型文件,打开文件,按规则解析所需的字段,对应写入本地数据表。
脚本执行逻辑:每次抓取路径下‘修改时间’为前一天的文件。(这里有个隐患:如果出了故障,可能某天的数据就漏了)。
问题:怎么防止丢抓呢?
分析:因为是外部数据,所以这里无法对源数据做“是否被抓取过”的标注,因此建议防丢方案是增加断抓补抓机制。
断抓补抓机制:比如4号抓了修改时间为3号的数据。5号断抓,则6号继续抓取4、5号的数据。断抓补抓的机制就是说一旦某一天的数据中断了,发现不连续,那么系统就自动在下次重新抓一次,看看是否能补上。直到三次都未取到,则不再补救。
该方案可以降低我方抓取故障导致的抓空情况。有时候开发懒省事不愿意考虑这么多,这时候产品经理要提醒他。
4. 消息队列MQ( Queue)
1)MQ概念
消息队列技术是分布式应用间交换信息的一种技术。目前市场上有很多开源的jms消息中间件,比如, 。
简单说就是一方不断把信息推到队列中,像排队进隧道一样,另一方依次消费这些信息。消息队列可驻留在内存或磁盘上,队列存储消息直到它们被应用程序读走。
该方式更适用于公司内部,数据量大,规律性强,批量往来的数据。主要解决应用解耦,异步消息,流量削锋等问题。
2)以异步处理举例说明
用户注册后,需要发注册邮件和注册短信。传统的做法有两种:
假设三个业务节点每个使用50毫秒钟,不考虑网络等其他开销,则串行方式的时间是150毫秒,并行的时间可能是100毫秒。
因为CPU在单位时间内处理的请求数是一定的,假设CPU1秒内吞吐量是100次。则串行方式1秒内CPU可处理的请求量是7次(1000/150)。并行方式处理的请求量是10次(1000/100)
小结:如以上案例描述,传统的方式系统的性能(并发量,吞吐量,响应时间)会有瓶颈,如何解决这个问题呢?
引入消息队列,异步处理,改造后的架构如下:
按照以上约定,用户的响应时间相当于是注册信息写入数据库的时间,也就是50毫秒。
注册邮件,发送短信写入消息队列后,直接返回,因此写入消息队列的速度很快,基本可以忽略,因此用户的响应时间可能是50毫秒。因此架构改变后,系统的吞吐量提高到每秒20 QPS。比串行提高了3倍,比并行提高了两倍。
在设计方案的时候要注意异常情况的处理机制,比如:首次消费失败?
如果第一次数据消费的时候,无法识别没有匹配上,但是又想下次再消费一次看是否匹配的上怎么办?可以设定机制:无法识别的则重新插到队列后面继续推送。
如果一直循环仍消费不掉信息积压怎么办?
设定处理机制:超过一定积压数据量或者循环时间过长则进行报警。
3)MQ、文件包共享、接口的对比
MQ推送过去之后,是否推送成功无需对方再用MQ返回,因为推到中间站就意味着我方能做的事情已经做完。
而接口是一来一往才知道是否成功的,也就是要返回一个信息。这点与mq是不一样的。但是如果非要对方再返回是否接受成功的话,那么就要做反向MQ,这相当于另一个独立的MQ。
文件包共享也不需要反馈机制,因此传到了文件服务器之后,数据方的事情就做完了。队列的一个信息只能被消费一次,不同系统不能共同消费一个队列。因此如果对接多个系统则要多次创建MQ。而接口可以创建一个,让其他很多系统调取。
在订单系统对接各个销售网站和平台的时候就可以采用这样的机制,避免多次对接。文件包共享也是可以上传一次,供多个需求方下载。这点和接口有相似之处,是MQ所不具备的。
5. 其他手段
数据传输包含了数据信息的获取和写入,其实除了线上的自动机制,还有很多土办法,在后端产品系统中也是常使用的。
1)导入导出
场景:没有办法做系统之间的对接,但是线下能获得数据。数据量不太大,且有规则数据,则可以通过导入的方式。
文档一般用csv格式,该格式文件较小,兼容性好,然后需要定义好excel表格对应字段的关系,比如A列对应字段‘name’,B列对应字段’age’。
上传时需要对文件检验,比如格式不对、必填项为空等,建议一旦一处错误,就全部不予导入。并返回错误提示,修改后继续导入。
若数据太大(与服务器的性能也有关系,比如超过一万条),可以采用异步上传机制,就是上传之后不立即执行写入,而是后台自动分批写入。
2)爬取
作为数据需求方,获取数据可以通过协商接口的方式、SFTP解析的方式、或者直接爬取的方式。
比如需要获取第三方网站商标库中最新商标名称、注册地、logo、授权期限等信息,如果该网站不给于开放的接口授权,可能就需要我们开发写爬虫代码爬取(当然有的商业数据也是带有反爬机制的,这就看谁道高一尺魔高一丈了)。
三、数据传输的处理机制1. 数据同步的触发机制
前面提到了数据获取的方式,那么数据获取频次或者触发机制是怎么样的呢?这要根据应用场景来设定方案,但是一般都是要求持续获取的。
一种方式是操作事件触发,比如页面的按钮点击则触发传递最新状态。这种的时效性比较高,但是也会由于并发而增加系统负荷。
如果对时效要求不高就可以采用异步机制。比如使用脚本监控。设定脚本的运行频率,当读取到更新时间为频宽内的数据,则将其捕获并传输。定时脚本也叫定时任务等,定时脚本在后端是很常用的。
比如说每次获取A系统6小时内更新的数据,那么每2小时取一次的话是没问题的。但是若每7小时获取一次就会漏掉1小时的数据。因此一定是每次获取的数据时间区间,要高于数据获取的时间间隔。
当然用时间是一种维度,更安全的是用标示性字段。比如每次获取为0的数据。前台是做表索引(索引前面讲到过),这样遍历(遍历约等于全表查询)数据库的时候就不会太慢。
2. 是否异步执行数据处理
如果获取后还要在本地进行规则运算,则最好先落地到中间表,再由中间表写入最终表,也就是异步写入。
比如:按照订单+包裹号维度,从物流系统获取运费到财务系统,然后财务系统再将其分摊到包裹的商品上面,算出每个商品分摊的运费金额。
这时候就很容易出错,因为分摊规则是个算法,算法就带有规则的可变动性。一旦分摊规则的参数不准确,或者算法结构变化,都会导致最终分摊的运费金额错误,那么这时候追查错误原因并修复数据就很麻烦。
所以在进行分摊之前,先落地到财务系统的临时表(中间表)中,然后获取数据完成,再进行写入分摊运费的操作。
除了上述方便查错误原因外(有种数据清洗的意思),这种异步操作同时也确保了较少的偶联,不至于一个环节出错,则联动出错。同时它作为一个基础数据,也可以被其他功能调用。若数据量万级以上的,必须这样做。
3. 判重机制
数据通道搭建好之后,数据流往往是持续获的。而数据源在别人那里,可能会被增删改,因此常常有相似或相关的数据进来。在写入本地表的时候,不管是覆盖、更新还是插入,都是以确定若干字段做为判重的标示为前题的。
比如职工信息表:(姓名+手机号+性别+家乡+身份证号)。(姓名+手机号+性别+家乡)这几个字段对一个职工不一定唯一,但是身份证号就是唯一的。因此如果我们更新这里的数据,就以身份证号为唯一标示。
比如获取到同一个身份证号的手机号与我们的数据库的不同,则更新。遇到我们的数据库不存在的身份证号码则插入。
某些时候无法确定那几个是唯一字段,则可以添加一个备用字段,人为定义其取值规则,然后作为去重字段,比如这个字段叫,取数据源表的主键+日期,(或者直接就取源表的id,也就是外键)。
有了判重字段(也就是数据唯一的字段),就可以进行更新、插入或者跳过规则设定了。
注意:若一段时间之后,改变了表的去重规则,则需要考虑到历史数据对新数据的影响,因为二者的判重维度不一样,可能会进来和以前的历史数据冲突的交叉数据。
4. 获取到数据之后,如果使用?
一种是直接在页面展示,不保存在本地数据库中。相当于每刷新一次页面则通过接口调取一次对方的数据展示。但这种从性能和场景上都是比较少的,一般都是先保存到本地数据库上,自己本地各种调用。
对于先保存到本地的情况,有两个问题要考虑:是否异步保存,和如何确保同源同步。
5. 处理日志
数据日志:目的是记录数据的来龙去脉,追溯以分析问题,日志要记录三个主要事项:数据源系统是否提供数据、目标系统是否接收到数据、目标系统是否写入了数据。
产品经理告诉开发加数据捕获日志的时候,需要告知是否存到表里,因为系统一般都有一个类似缓存一样的日记,只是会定期清理的,只有保存下来才能一直记录和追溯。
开发后台本身是有数据log日志的,因为log4j开源代码定义了5个主要级别的log:FATAL、ERROR、WARN、INFO、DEBUG,一般情况下,开发都会自觉配置INFO或DEBUG级别的日志,以方便查数据。
但是代码中的kog保存时间不会太长,比如一个月就会清除了。因此如果需要保留的时间长,则可以将其保存到本地数据库。
根据实习需要,存了数据库就可以做成页面,展示给用户看,比如可以从以下维度展示:
四、数据传输的注意事项1. 目标数据表最好和中间表的维度一致
假设从A系统获取的数据存入B系统,先落地到中间表b,然后经过一些列运算后将数据从b写入到b’表。注意b和b’表的去重字段要对应起来,并传递下去。因为维度相同,做到一对一,方便实现异常数据溯源。
2. 不同入口写入同一类型数据时,如何与自身入口的数据去重,且与其他入口的数据互相去重?
案例:有新旧两个不同的写入程序,写数据到利润表,写入的都是‘退件入库’利润类型,是殊途同归。不巧的是两个写入入口各自有本身的去重规则,彼此去重的规则不能通用:假设入口1对应的去重字段是A+B,入口2写入的去重字段是B+C。
这就意味着同一个数据如果分多次写入,有可能从两个入口都会写入。如何实现避免重复写入是核心问题。我们首先考虑的是,如果一条源信息从一个入口已经写入了利润表,那么就不能从另一个入口再写。
其次,如果从入口1写入一次,那么后面源数据更新再次触发写入的时候(判重,确定是插入还是更新),就还要从入口1写。也就是一旦从一个入口写入,后面该数据的变更触发的再次写入也只能从这个入口继续变更。
只有这样才能保证这个数据不重复。好比先找到是哪家的孩子,再确定是第几个孩子,且只能是基于这家内部去确认。
方案一:比如入口1遇到一个待写入的数据,则先按自己的去重字段A+B校验。如果发现不存在该数据,则再按照入口2的去重字段B+C(这个事先是知道的)判断是否存在,若也不存在,则回到入口1写入。若存在,则入口1不在写入,且结束进程(因为入口2会触发写入该数据的)。
方案二:比如入口1遇到一个待写入的数据,则先按入口2的去重字段B+C校验。
查看对方入口下是否有重复数据,有,则本入口不写(继续按对方的路径写);无,则自己的路径写。显然方案二的判断路径更短,相对好一点。
3. 同步基础数据的时候是否提前过滤
这个在上面内容中也提到过。比如:A系统维护了员工的基础信息,其中有个状态为【是否有效】,只有有效状态的才能在整个系统中看得到才是生效的。B系统要取用员工信息的数据,但不做数据维护。那么是否只取启用状态的数据到B,还是不区分状态都取呢?
答案是:在数据量差异不大的情况下,取全量。
原因之一就是,若启用状态的用户忽然被A系统禁用,那么可能该用户在B系统的生产数据报错,这时候到中间表看状态就可以看出来问题,而不需跨系统或跨部门沟通查证。
#专栏作家#
唧唧歪歪PM,公众号:唧唧歪歪PM(ID:),人人都是产品经理专栏作家,2019年年度作者。《后端产品经理宝典》作者,药学硕士转行互联网产品多年;熟悉跨境电商业务,医药领域;擅长大型后台体系,社交APP。