【51CTO.com原创稿件】为什么需要数据仓库
随着公司业务不断发展,数据种类和存储呈现爆发式增长,繁多的业务数据如何被各业务中心分析和使用,如何有效组织和管理大量业务数据,减少大数据平台相近逻辑重复计算、相近数据重复存储,都将面临巨大挑战。
数据仓库层次架构
数据仓库层次整体划分为三层:近源数据层、整合数据层和应用数据层,如下图:
近源数据层
近源层是数据仓库拷贝源数据提供整合的数据存储区域,粒度、结构和源系统保持相同
- 缓冲区:保存源系统每天的增量数据,可根据应用需要保留适当历史周期的数据,不长期保存数据
- 操作区:存储数据仓库最细节数据,按照业务源系统分类划分;对数据做结构化处理,完整保留所有细节数据。
近源层是整个数据仓库中数据量***的部分。
整合数据层
- 明细区:采用维度建模方法,整合近源层数据,进行适度的反范式设计明细事实数据表。
- 汇总区:根据应用层和其他下游系统取数需要,对明细事实数据进行适度汇总,提升取数性能。
- 维度区:数仓统一维度数据模型。
应用数据层
应用数据层为个性化汇总层,针对不是很通用统计维度、指标存放在此层中,本层计算通常只有自身业务关注的维度和指标,和其他业务线一般无交集 。
数据建模
数据建模是数据仓库中的核心工作,苏宁数据建模主要采用的kimball维度建模方法,建模主要分两块,维度表设计和事实表设计。
维度表设计
维度是数据仓库的核心,他提供了数据分析的视角和标准,大部分的维度表数据量都相对较小,但是他是整个数据仓库的核心,整个的数据建模都是围绕着维度来建设。
维度表主键
维度表在数据仓库中有不可替代的重要地位,因此维度表主键的确认也尤其重要,维度表的主键用于和事实表做关联使用,所以维度表主键也为事实表的外键,维表主键可由有业务含义的自然键组成;也可由无意义的代理建组成,比如使用流水号、自然键+日期等方式。
维表相对静态、不随时间变化直接使用自然键作为主键,比如:业务状态码、性别、城市省份等不会随着时间改变而改变主键对应业务含义,一般直接使用业务自然键作为主键;维表随着时间的变化而产生变化需要考虑使用代理键作为主键。苏宁门店代码,会因为组织法人等信息变更,生门店代码会发生变化,对应主键的业务含义会随着时间的变化而改变,使用一个代理键和业务门店代码映射,可以识别历史和当前不通的门店代码为一个门店。
实际使用过程中,由于在大数据平台中生成稳定代理键和自然键关系比较复杂,一般使用流水号代理键使用非常少。
维度反规范化处理
在OLTP系统中,一般表设计都遵循3NF等规范化要求要求建立数据模型,这个可以有效避免数据冗余以及数据不一致性,如下图:
然而在OLAP系统中,使用规范化,会导致数据表关联操作多、性能差,在OLAP系统中,数据是相对稳定的,此时往往会采用反规范化处理,根据分析需要建立对应维度宽表,降低模型查询复杂度,提升批处理查询性能。如下图:
维度的合并和拆分
合并:
- 相同范围数据,对应多张表存储属性不同,根据维度分析需要整合至一张维度表中,整合后减少事实表和维度表关联次数,方便数据分析和加快数据统计计算。
- 不同数据范围,对应多张表存储信息,根据维度分析需要将相同属性整合到一张表中,不同表中差异化的数据整合到各自数据表中。
拆分:
- 根据属性的使用频率、属性变化程度、属性数据计算产生时间等角度分析多维度属性做适当拆分,常用的信息在一张表中,对异变、冷门属性拆分到另外一张表中,对出数比较晚的数据也做单独拆分,可以尽可能保障主数据模型出数稳定和提前出数时间。如下图:
- 根据业务细分或者业务数据使用热度进行拆分,例如苏宁商品目前已经到十亿+级别数据量,其中很大一部分商品已经不在售卖,不会产生流量和交易,可以将近N月产生流量或交易数据分别建立维度表,减少事实表和维度表关联系统消耗。如下图:
需要结合业务数据情况和数据分析要求,合理使用合并和拆分方法。
缓慢变化维
缓慢变化主要是解决记录数据仓库中数据历史变化,实际根据业务需要我们会有多种处理方式。
以会员会员张三举例,9月1日前公司地址为南京市玄武区苏宁大道一号总部一期;9月2日由原公司地址总部一期变更为总部二期,对应多种处理方式包含覆盖方式、新增列方式和新增行方式,下面对每种方式处理方法单独介绍。
- 覆盖方式:维度属性的变化,维度旧的属性总是被新值所覆盖,不保留历史状态数据,当数据不需要保留历史记录,不需要执行以前的报表,可以采取此方式。如下图:
- 新增列方式:新增数据列记录对应列数据变化前数据,可以记录指定列数据变化情况。如下图:
- 新增行方式:当维度数据发生变更,维度表新增一条维度记录,并且分配新的代理主键,通常配合有效开始时间、有效结束时间、有效标识使用。如下图:
快照维度表
在实际大数据平台开发过程中,产生唯一代理键和生成缓慢变化为拉链表是比较困难和复杂的,在很多实际的场景中是基于计算周期,每个周期生成一份快照表,保留每个周期的快照数据,采用快照表方式维护简单使用也比较方便,弊端也很明显浪费存储,在数据量不是特别大的情况下使用此方式还是比较合适的。
层次维表
通常维度之间往往存在层次关系,关系的层级可能是固定的,也可能是不固定的
- 固定深度层级:比如苏宁采购目录层级关系,表现为固定四级层级关系,为提高查询性能,将表设置为固定四层宽表。如下图:
- 深度轻微差别层级:比如苏宁销售目录关系,表现为三到五级层级关系,层级关系不固定,但层级深度有限,可以基于***深度和业务规则建立维度表。如下图:
- 深度可变层级:对于深度层级不确定维表,在建模和使用都相对较复杂,可以采用桥接表方式,对每个可能的路径保留一行,确保能遍历所有层次。还以销售目录举例,如下图:
由上图可见,桥接表加工处理比较复杂,且带来双算的隐患,实际模型设计中,多选择扁平化模型设计方法来解决业务问题。
事实表设计
维度模型设计过程
- 选择业务过程:业务过程由组织完成的微观活动。例如易购交易过程包含:下单、支付、发货、收货、退货等,明确了业务过程根据业务需求选择和建模有关的业务过程。
- 申明粒度:确认事实表中每一行数据的准确粒度,以交易过程举例,对应粒度为交易时间、会员、商家、商品,申请粒度和主键(单号)等价,不要以数据主键来定义数据粒度
- 确定维度:根据业务需要确认需要分析的业务维度,包含时间、地点、人物、环境等,常见包含日期、会员、商品、渠道、设备等
- 确定事实:事实也称为度量,根据业务需要和数据来源确认度量。
事务事实表
事务可以理解为业务操作最基本的动作,他可表示特定时间、空间发生的一个事件。如果某个事务发生,将在对应事实表中建立对应一行记录,它能实现对细节行为数据的分析。
如下已订单下单和支付过程具体,如下图:
在实际设计过程中,如果多个业务动作的维度和度量都基本相同,可以考虑将多个业务过程合并为一张事实表,合并可以减少数据开发工作量和方便以后业务变更。如下图:
周期快照事实
如果希望分析某个业务在某个固定的、可预测的事件间隔内的累计性能,可使用周期快照事实表,利用周期快照可对一天、一周、一个月结束时建立数据快照,存储到事实表中,周期快照事实表可用于记录事实每个周期的变化情况。
例如我们业务中通常对会员累计支付金额、积分余额、会员等级、商品库存等做周期快照,方便分析会员、商品等属性对应度量值,而不需要长期聚集事务历史。
累计快照事实表
累计快照表示具有确定的开始和结束时间以及此期间所有中间过程的步骤,累计快照适中会表示多个日期外键,表示主要时间或过程里程碑。
以交易过程举例,统计订单对应下单到支付时长、支付到发货时长、发货到收货时长、支付到收货时长等,事务事实表计算复杂,性能差,比较适合采用累积快照事实表。如下图:
数据处理常见问题
离线数据处理
1)表存储格式
尽可能避免使用textfile存储格式。数据内容中时常会出现换行、tab等一些特殊字符,使用textfile容易出现数据行错位、列错位等情况,如果特殊情况不可避免使用textfile格式,尽量选择json文件格式,或者多个特殊分隔符作为行和列分隔符。
2)数据压缩
建议使用orc或rc等压缩方式存储表,以cpu换存储和时间 ,加快读写效率。
3)数据倾斜
在表数据处理过程中,多种情况会发生数据倾斜:
1. 大小表关联,走common join,由于关联key值在大表中分布不均匀,可以开启mapjoin,将小表加载到内存,大表不需要根据key做hash分布,不会出现数据分布不均情况。
2. 两大表关联,其中表中关键key值存在部分键值数据非常大,导致数据倾斜
- 个别键值,比如null值数据非常大,对个别键值做rand处理,打散数据
- 非个别的键值数据量很多,比如热销商品访问数据量会比其他商品数据量大,可以首先统计topN数据量Key列表到topN表中,将量大表先和topN表关键,这样topN数据可以先mapjoin,剩下数据common join,可以避免数据倾斜。
出现数据倾斜还是需要先分析key值数据分布情况确认解决方案。
实时数据处理
1)数据重复
在实时数据处理过程中,不论使用storm、sparkstreaming、flink,因为在保证大数据大吞吐计算情况下,往往较难保证数据事务,在环境或者计算出现异常情况下,容易出现某个批次部分数据重复计算,在很多数据业务分析往往是无法接受的,对需要准确性统计的计算场景,缓存每次计算结束的列表,每次计算前根据已计算列表验证当前数据是否已经计算过,对计算过的数据跳过本次计算,这样程序异常或者重启,重新读取kafka数据会跳过已经计算完成的数据。对用户流量类大数据量做到精确统计消耗成本太高,可以根据实际业务需要选择对应方案。
2)双数据流关联
多数情况,在实时指标分析过程中,指标和维度往往能通过一个数据源来分析计算得出,在某些场景下,指标对应维度会对应不同的数据源,这时候就需要将两个数据源根据业务ID关联起来,然而两个实时数据流可能会出现1.两个数据流数据不同步,2.数据采集可能存在一定的数据丢失,导致可能部分pv再等待另外一个流永远都等不到。
以流量PV指标举例,分析维度包含:城市、页面类型、供应商等,其中流量访问日志里面包含PV_ID、城市、页面类型等信息,流量库存日志包含PV_ID、供应商等信息,pv数指标对应维度分表对应两个数据源中,在离线计算中join直接解决,在实时计算过程中又怎么关联呢?
首先需要分析两个数据流哪个是主数据流,所有的统计数据以主流为基础,保证主流数据不丢失,部分场景也可能两个流合并作为主数据流;
其次需要对两个数据流设定一定的缓存,对未关联上的数据先记录到缓存中,等待另外数据流做关联操作,缓存需要有持久化机制,保证系统出现问题或者程序重启缓存不会丢失;
再次设置缓存时长,由于包括数据丢失等可能情况会导致数据无法关联情况,此时需要根据业务定义缓存时长,对超过时长还未关联到的数据根据业务做对应处理。
在实际实时模型设计尽可能减少双流关联的计算场景,一方面双流关联开发较复杂,另外一方面双流关联相比单流数据准确性存在下降的可能性,在上举例中,可以通过上游采集系统在访问流添加供应商等维度,由一个数据流支撑对应指标和维度,双流在采集端容易做业务合并的尽可能在采集端做业务合并。
大促计算保障
电商行业,大促业务量是日常业务量的很多倍,暴增的数据量对计算平台各环节都会带来较大的挑战。
离线计算,1.数据暴增首先带来的是底层平台HDFS计算压力,需要根据预估业务量扩容平台计算能力;2.数据暴增容易带来数据倾斜问题,例如大促爆款商品等呈现分化数据会导致数据分布严重不均匀,需要打散数据,有效利用平台资源分散计算,缩短计算时间;3.提前分析核心业务线,识别关键路径,对关键路径中慢节点做拆分优化,提高计算并行能力,缩短关键路径时间。在大促保障期间,通过计算倾斜的优化和关键路径的拆分优化,有效提前整体出数时间。
实时计算:1.根据预估业务量扩容实时计算storm、spark streaming、flink等平台资源;2.在流处理业务中,根据业务数据量、业务重要程度对业务计算做拆分,避免集群内业务互相影响,对storm需要根据业务做集群拆分,尽可能将数据量大非核心业务拆分单独集群,避免集群内非核心业务抢占核心业务资源3.合理利用数据缓存有效提高实时计算能力;4.对适合在客户端采集实现的业务,由采集来实现,减轻大数据平台计算压力,也能通过数据采集优化有效避免部分业务的双流关联,提高实时计算效率和准确度。
名词解释:
作者:彭虎,苏宁易购IT总部大数据中心技术副总监,12年IT从业经验,专长大数据hive、storm、spark等数据计算技术,对数据建模、数据计算、多维分析有着专业认知和研究,致力于数据仓库探索研究、数据质量分析、数据计算保障。
【51CTO原创稿件,合作站点转载请注明原文作者和出处为51CTO.com】