
数据漂移是 ODS 数据的一个顽疾,通常指 ODS 表的同一个业务日期数据中包含前一天或后一天凌晨附近的数据或者丢失当天的变更数据。
公司主营互联网金融业务,因此有了一张数据量庞大的申请人信息记录表。这张表里的时间字段非常多,因为整个业务场景涉及到好几段流程:
客户提交申请贷款请求 → 我们接受申请贷款请求 → 进入决策引擎 → 决策引擎调用第三方数据系统 →决策引擎返回结果报告 → 匹配发送记录和返回报告 → 反馈给客户发送结果
可见每一段子流程(子域)里都会有相应的时间字段。 选择使用客户的提交申请时间来做分区字段,也是为了贴近客户的实际体验。即某一天的申请记录明细就应该是那一天客户提交给我们的所有申请信息。实际上并给如此,主要有两种场景导致了异样的发生:
我们接受到客户的申请贷款的请求后,到提交给核心信贷系统以及决策引擎系统这段时间理论上是很快的,秒级响应。但某些时候因为网络波动或者服务器故障,会导致申请积压,卡在某一环节,如果正好卡在落库之前,这时客户在 T 天提交贷款申请请求,积压解决后申请记录落库实际发生在 T+1 天。导致 T+1 天凌晨做ETL 数据同步时这批申请信息记录获取不到,最终数据平台丢失了一部分数据。
有一类特殊的业务场景叫”先提后审“,客户提交一种特殊的申请贷款请求后,需要客服审核内容,审批通过后才可实际发送。如果客户在客服下班时间段提交了这种申请贷款请求,那么实际要到第二天客服上班后才会实际被提交,落库也发生在客服审批之后。同上一种情况,也会发生丢失数据的情况。
某些公司采用了很粗暴的解决方案,T+1 天允许 T 这天的数据存在数据漂移的现象。但是在 T+7 天,对 T天数据进行重传,恢复这些丢失数据,保证最终状态的数据是完整的。这种方式跟公司业务也是跟契合的,因为申请贷款的状态会在 7 天内做更新(因为决策引擎系统返回的状态报告也会有几天的延迟,约定 7 天内不返回报告计为未知状态不再更新)。这种方式本意是用作数据更新的,结果顺带缓解了数据漂移。(不算解决是因为 T+1 天到 T+7 天,数据仍然有丢失,不完美)
既然按照申请贷款时间戳切分,会出现数据漂移,那么就考虑换一个业务场景的时间戳。在申请贷款这个业务场景下,选择放款时间作为时间切分字段。放款一旦发生,就不会变化;放款作为核心关键功能,除非巨大故障也极少发生延迟现象。(当然真的发生了后期再补数据,因不可抗拒因素产生的问题是无解的,只要做到可补救即可)。如果系统有一个统一的放款服务,这个字段的一致性也是有保证的。
但公司没有采用这种切分方式,我的理解是有两个原因:
1)存在月结客户,并不是所有客户的业务都是先申请再放款的,一些特殊业务大客户是先放款再申请的。
针对这些客户,并不存在真正的放款操作。
2)目前放款服务是散落在系统的各个地方的,并没有统一管理起来,导致放款这个操作本就不具备业务逻辑上的统一性。
针对问题 1),其实是有解的,对月结客户仍然可以走一遍放款流程,记录下一个“伪放款时间”,甚至真放款也无不可,无非额度扣成负数。当然公司目前没有这么操作,针对月结客户,额度是直接锁死的。月结客户的还款计划依赖月度的离线计算脚本。这样的操作同时带来了数据不统一的问题,在线客户的账单来自交易记录(放款,系统操作),而月结客户的账单来自申请记录统计(离线统计,脚本计算)。因为这种数据源的不统一,公司的核心账务计算一直不如意,实在是一个遗憾。
针对问题 2),公司的线上申请贷款业务发展了*年,这么多年里新增了许许多多的业务模块、功能、乃至针对大客户的特权特殊服务。放款操作并不统一,甚至存在一小部分客户是非系统操作,而是由计算脚本放款的。不统一的放款服务也带来了一定的混乱局面,实为另一个遗憾。所幸这个问题以及在推进解决中,公司已经在规划一个放款整体的服务,作为各业务线的中台应用,解决这个历史顽疾。
当然放款时间作为切分字段,针对申请贷款业务来说是很合适的。可惜并不是所有业务场景下都能找得到这样的业务时间。很多公司的情况有很多许多业务功能,使用单一的业务时间会遗漏很多其他过程的变化记录,
比如很常见的电商业务,就有下单、支付、退款、售后等过程,并不适合以某一单一业务时间做切分字段。
既然取一天的数据会有数据漂移现象且发生在凌晨,那么自然而然就有一种方式:我们多向前一天要一部分数据,也向后一天多要一部分数据。根据经验,一般是15 分钟。保证数据只多不少,切分时按照需要的业务时间再过滤,这样可以解决那些因为延迟造成的数据漂移,
但同时也带来了问题:
如果多获取了 T+1 天的一些更新变化,会导致 T 天的最终状态没有被保留,最终存储在 T 天的数据实际是T+1 天凌晨的状态。这对下游的相关统计会造成一些误差。另外,上边提到的特殊业务场景也并没有解决。
这一部分的感受不是很深刻,按照一些文章的说法:
根据日志时间冗余前后数据,然后用修改时间过滤非当天数据,这一步几乎和之前描述一样,保证系统原因的遗漏不发生;
根据日志时间冗余后一天数据的部分,按照主键以日志时间升序取第一条,为了获取最接近 T 天状态的数据;
将 1,2 步骤的数据做全外连接,限制业务时间来获取 T 天数据。
相对而言,贷款申请业务是一种比较单一、简单的业务场景。而简单的业务场景,解决方案自然也比较简单粗暴。目前**某些公司采用的 T+7 重传,很好地解决了数据更新与数据漂移的问题。虽然我认为统一的放款时间做时间切分会更合理,对财务计算更更友好。
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search
由于fast-stemmer的问题,我很难安装我想要的任何rubygem。我把我得到的错误放在下面。Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingfast-stemmer:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcreatingMakefilemake"DESTDIR="cleanmake"DESTDIR=
当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。