第二,批次。批次实际上是一个更不常见的场景,有些时候可能会发生数据重导,它跟重启不太一样,重启作业可能就是改一改,然后接着上一次消费的位置启动。而重导的话,数据消费的位置会发生变化。
比如,今天的数据算错了,领导很着急让我改,然后我需要把今天的数据重算,可能把数据程序修改好之后,还要设定程序,比如从今天的凌晨开始重新跑。这个时候由于整个数据程序是一个 7x24 小时的在线状态,其实原先的数据程序不能停,等重导的程序追上新的数据之后,才能把原来的程序停掉,最后使用重导的数据来更新结果层的数据。
在这种情况下,必然会短暂的存在两套数据。这两套数据想要进行区分的时候,就要通过批次来区分。其实就是所有的作业只消费指定批次的数据,当重导作业产生的时候,只有消费重导批次的作业才会消费这些重导的数据,然后数据追上之后,只要把原来批次的作业都停掉就可以了,这样就可以解决一个数据重导的问题。
6)维度数据建设
其次就是维度数据,我们的明细层里面包括了维度数据。关于维度的数据的处理,实际上是先把维度数据分成了两大类采用不同的方案来进行处理。
① 变化频率低的维度
第一类数据就是一些变化频率比较低的数据,这些数据其实可能是一些基本上是不会变的数据。比如说,一些地理的维度信息、节假日信息和一些固定代码的转换。
这些数据实际上我们采用的方法就是直接可以通过离线仓库里面会有对应的维表,然后通过一个同步作业把它加载到缓存中来进行访问。还有一些维度数据创建得会很快,可能会不断有新的数据创建出来,但是一旦创建出来,其实也就不再会变了。
比如说,美团上开了一家新的门店,门店所在的城市名字等这些固定的属性,其实可能很长时间都不会变,取最新的那一条数据就可以了。这种情况下,我们会通过公司内部的一些公共服务,直接去访问当前最新的数据。最终,我们会包一个维度服务的这样一个概念来对用户进行屏蔽,具体是从哪里查询相关细节,通过维度服务即可关联具体的维度信息。
② 变化频率高的维度
第二类是一些变化频率较高的数据。比如常见的病人心脑科的状态变动,或者某一个商品的价格等。这些东西往往是会随着时间变化比较频繁,比较快。而对于这类数据,我们的处理方案就稍微复杂一点。首先对于像价格这样变化比较频繁的这种维度数据,会监听它的变化。比如说,把价格想象成维度,我们会监听维度价格变化的消息,然后构建一张价格变换的拉链表。
一旦建立了维度拉链表,当一条数据来的时候,就可以知道,在这个数据某一时刻对应的准确的维度是多少,避免了由于维度快速的变化导致关联错维度的问题。
另一类如新老客这维度,于我们而言其实是一种衍生维度,因为它本身并不是维度的计算方式,是用该用户是否下过单来计算出来的,所以它其实是用订单数据来算出来的一个维度。
所以类似订单数的维度,我们会在 DW 层建立一些衍生维度的计算模型,然后这些计算模型输出的其实也是拉链表,记录下一个用户每天这种新老客的变化程度,或者可能是一个优质用户的变化的过程。由于建立拉链表本身也要关联维度,所以可以通过之前分组 key 的方式来保障不乱序,这样还是将其当做一个不变的维度来进行关联。
通过这种方式来建立拉链表相对麻烦,所以实际上建议利用一些外部组件的功能。实际操作的时候,我们使用的是 Hbase。HBase 本身支持数据多版本的,而且它能记录数据更新的时间戳,取数据的时候,甚至可以用这个时间戳来做索引。
所以实际上只要把数据存到 HBase 里,再配合上 mini-versions ,就可以保证数据不会超时死掉。上面也提到过,整个实时数仓有一个大原则,不处理离线数仓能处理的过程。相当于处理的过程,只需要处理三天以内的数据,所以还可以通过配置 TTL 来保证 HBase 里的这些维度可以尽早的被淘汰掉。因为很多天以前的维度,实际上也不会再关联了,这样就保证维度数据不会无限制的增长,导致存储爆炸。 |