漫谈大数据仓库与挖掘系统
来源:e-works 更新时间:2014-01-13

 前言:什么是大数据?及大数据的价值 很多人可能认为,数据只是一堆数字,是没什么价值的。其实这些人很可能早已可能享受到数据的红利。例如早在2006年中旬上线的 百度指数 ,其实就是一个基于大数据的数据产品的雏形,但是还不能说是完整的大数据产品(后文中我们会去解释为什么)。百度指数是用以反映关键词在过去30天内的网络曝光率及用户关注度,它能形象地反映该关键词的每天的变化趋势,以及显示这些搜索的地区分布和简单的人群属性。百度指数的数据被大量的用作针对百度甚至其它一些搜索引擎的SEO的参照,也经常被一些研究公司、学者引用作为一些研究报告的参考数据。   在百度指数之后,阿里巴巴集团亦推出了 淘宝指数 ,相对于 百度指数 , 淘宝指数 是一个更加完备的数据产品,用户可以在淘宝指数中搜索任何一个关键词,得到这个关键词在淘宝(天猫)上的搜索/成交趋势、人群信息(如性别、年龄、星座、地区、爱好)等等,还可以查询从这个关键词出发的淘宝上的相关商品、商品属性、品牌等的销售情况,以及对任意人群信息组合(例如25-30岁北京女性)下的相关交易信息。淘宝指数目前亦是免费开放,只要使用淘宝帐号登录即可,通过淘宝指数,我们可以很轻松的发现很多很有趣的事情:   例如通过查看“周大福钻石”的搜索和成交信息( 点此查看连接 ), 我们可以很清楚的看到,从2011-08-01到2012-11-30,487天来搜索周大福钻石的人群中有68%的女性和32%的男性,但是在购买周大福钻石的人群中,却是100%的男性。

 再例如对比“加多宝”和“王老吉”,我们很容易就会看到,从今年四月中旬加多宝出现之后,王老吉的搜索量明显下降,加多宝则直线上升,在9月12日前后,两者的曲线发生了历史性的交汇。

其实早在2010年,开发淘宝指数的团队,暨阿里巴巴集团数据平台部门,便推出了针对淘宝(天猫)商家的收费数据产品 数据魔方 ,基于淘宝上品牌、属性等提供更加详细的多维度的数据组合查询。同时新浪微博还推出了新浪微指数,优酷推出了优酷指数,这些直接呈现数据,以数据的统计、挖掘、汇总、分析为主题的产品,是大数据时代的第一种产物。   大数据时代中还有一类产物便是基于大数据分析和挖掘的能力,针对用户进行个性化的信息推送的产品,目前美国亚马逊、阿里巴巴集团旗下的淘宝网等电子商务网站中,这种产品均在越来越广泛的得到应用,并取得了很好的转化效果,比传统的导购模式表现出了更高的转化率(可以理解为看这些页面的人中实际购买这些页面呈现的商品的人的比例)。另外在网站的后台,基于大数据的BI(商业智能 Business Intelligence)分析更是早已为网站的运营人员和规划人员提供了宝贵的信息支持。目前国内外也有很多数据公司通过构建大数据分析系统来服务各类企业的BI部门。   看到这里,有些人可能觉得,所谓的数据产品仅仅是对数据进行一些统计分析,然后呈现出来,没什么了不起的。这么说从某种意义上来讲所言非虚,但是,笔者希望本文的读者在任何时候都记住一句话:看起来简单的事情,实质上往往都是不简单的。   大数据不是简单的统计分析哦   先说说什么叫做大数据:从公认的定义上看,数据量达到PB级别(1PB=1024TB=1048576GB)的数据,就可以叫做大数据了。目前从公开的资料中我们了解到,阿里巴巴集团目前的数据仓库之一“云梯”中总存储容量50PB,实际使用容量超过了40PB。百度搜索引擎抓取的数据综合,大概是10-50个PB,这个范围很大,因为这个情况是每隔一小时时间就会发生很大变化。另外其的UGC,也就是用户产生的内容,例如百度贴吧,百度知道,百度文库中的内容,这些内容是广大互联网网民自己产生,自己上传,大家一起分享的数据,这部分数据目前达到1PB。   处理这么多数据,显然,单独的计算机,哪怕是大型机,都很可能是力有不逮的。那么,我们就要借助所谓的云计算(Cloud Computing)技术了。在介绍这部分内容的同时,笔者亦会介绍三个概念:离线计算、实时计算和流数据计算。   离线计算指的是,在用户查询计算产生的数据之前,计算就已经完成了,用户仅仅是查询计算的最终结果。例如细心的你可能会发现,百度指数和淘宝指数中的大部分数据都是每天更新一次的,这个便是因为,这些数据一般都是在每日凌晨时通过离线计算产生的。离线计算由于计算早在用户查询之前就完成了,所以对计算所消耗的时间长度不做要求。目前广泛运用于离线计算的是开源 Hadoop系统 ,在阿里巴巴集团中,其数据仓库系统之一:云梯系统,便是架构在Hadoop上的。这个集群目前拥有超过2800个节点,清一色基于英特尔处理器的x86服务器,日均作业数高达15万。相关数据产品在每天凌晨开始处理超过1.5PB的数据量,会在几个小时内处理完毕,每秒钟处理的数据量都可能是以GB为单位的。同时阿里集团还有另外一套规模略小,但是是基于自主知识产权开发的系统飞天(ODPS)上的数据仓库系统,也拥有接近2000个节点。至于百度公司,根据其2011年公布的情况,其所有的Hadoop集群的节点总和在4000个左右。   离线计算产出的结果数据都是固定的组合的,例如我们可以计算出“王老吉”一词在北京地区由男性在百度上搜索的搜索量。然后数据产品的前端系统查询时直接查询取出这样的数据即可。但是这里有一个问题,如果前端用户需要多维度组合查询的话,例如查询任意性别(男、女)*任意年龄(假设五个年龄段)*任意城市(340多个城市)*任意爱好(假设有10种爱好)的人群的搜索量,那么,如果需要把这些组合全部通过离线计算算出,便有2*5*340*10=34000中组合,那么一个词一天的结果数据便有34000个,这样组合计算的效率和结果的存储成本是不可接受的。所以,我们必须构架一套实时计算系统,暨计算在用户查询时便发生的系统。 我们往往也把实时计算系统归类于OLAP(On-Line Analytical Processing, 联机分析系统)中。   有些读者可能用过一些数据库系统,例如SQL Server、MySQL、Oracle等,从本质上讲,这些数据库中对数据的计算也是在查询时发生的。但是,在大数据时代,数据量极度膨胀,使得这些传统的数据库很难在短时间内从海量数据中查询计算出用户需要的数据。举个例子,假设淘宝(天猫)每天的成交交易的笔数是1000万笔(实际上显然不止这个数字),那么30天内就有3亿数据量的积累,在这3亿数据条目中,要求在0.5秒内查询出符合三四种条件组合的成交量,并且做分组(Group)、汇总(Sum)、排序(Order)等运算组合的情况下,单机部署的Oracle、MySQL等的性能都无法满足这个要求。所以便需要更高性能的,在多个节点上并行计算的实时计算系统来支撑了。目前实时计算系统中还没有像Hadoop那样占有极大的市场份额的开源软件,各大公司都在开发自己的实时计算系统,例如阿里巴巴集团的 Garuda系统 。   离线计算和实时计算,虽然计算发生的时刻不同,但是数据装载的时刻往往是相同的,都是在每天凌晨装载完毕。而流数据计算系统,则指的是数据源源不断的流到系统中,在数据到达时便计算相关结果的系统。显然流数据系统是可以计算呈现几分钟内新增的数据的。目前这方面的相关应用比较少,可以查到的例子如阿里巴巴集团数据平台的 Galaxy系统 ,为 数据魔方 提供流数据计算的支持。   以上种种,归结起来,大数据便是海量的(Volume)、多种类的(Variety)、需要大规模的处理才能够凝聚足够价值的(Value)、处理和检索响应速度快的(Velocity)的数据。处理大数据所需要的系统,和传统的数据挖掘工作所需要的系统有根本性区别。同时,大数据时代愈发强调数据的关联性,将各种数据之间关联组合,以产生更大的价值。   我们可以试想一下,以我国公安机关拥有的公民信息为核心,加上民航和铁路部门拥有的出行信息、银行拥有的交易信息、各个城市的社保公积金数据、电信系统的数据等等,构建一套大规模的国民数据挖掘处理系统,这样的系统的数据价值自然是极大的,显然,便能够充分体现出,关联的大数据(Linked Big Data)所产生的巨大价值了。当然这样的系统是不可能存在的,不过作为例子描述却是极佳的。   说了这么多,序言所要讲述的内容也就差不多了。本文接下来的章节会对大数据仓库与挖掘系统做一个简单的介绍。   (二):层次、维度与主题 在上一章节的末尾,我们谈到,这个系列的文章,最终会以我国公安机关拥有的公民信息、加上民航部门拥有的出行信息、银行拥有的交易信息等数据为例,逐渐讲述如何构建一个大数据的国民信息挖掘系统。不过以上一章节所叙述的基础知识,还不足以让我们进入实例环节。在这一章,我们还是必须补充一些相关的基础知识。   当然本文作为一个科普性质的读物,笔者并不希望读者们对本文望而生畏,所以,即便是对基础知识的介绍,本章节也不会参杂多少深奥的理论知识。而且事实上,数据仓库与数据挖掘的相关技术和理论,大多都是从工程师们的实践中总结出来的,而不是由大学中的教授们研究出来的。不过,为了解释数据仓库到底是什么,它和我们所熟知的数据库系统有什么不同,笔者还是要引用现代数据仓库之父,William H.Inmon大师的著作:《 数据仓库 Building the Data Warehouse 》中的一个定义:   “数据仓库是:面向主题的、集成的、稳定的、面向时间的数据集合。”   一句简单的话,阐述了数据仓库系统的至少一半以上的任务。面向主题的、集成的、稳定的、面向时间的,这四个形容词中,最好理解的,便是面向时间的。以民航部门拥有的出行信息为例,每一天出行的旅客、目的地等信息都是不同的,这样的记录的时间性,在航空公司的业务数据库中,可能仅仅是每条记录中的一个记录时间(年月日时分秒或者其它的什么形式)的字段,但是在数据仓库中,则是不然。数据仓库中,时间是一切数据的分类的第一方法。所有的类别、来源的数据,若是在一个时间段内产生(通常以天或周为单位),都会用相同的方法做分类。分类的方式可能是表,也可能是Hive等系统中某表中的一个分区,显然目前后者是更加常用的。所以,数据仓库中往往拥有业务数据库中的数据在时间周期内的变化的全部历史。例如我国全部航班的总的起飞数量这一数据,在业务数据库中,很可能只存储了最新的数据,但是在数据仓库中,由于每日(或周或小时)都将业务数据库的数据装入数据仓库的一个周期分类中,所以,却是能够查找到每个时间周期的全部历史数据的。   集成这个特性也是很好理解的,在业务数据库系统中,不同的业务系统往往使用不同类型和位置的数据库,但是在数据仓库系统中,无论何种数据源,无论是Access、SQL Server、MySQL还是Oracle,甚至是系统访问日志中的数据,都会被统一装入同一个数据仓库系统,这便是数据仓库系统的集成性了。这里,我们把装入数据仓库系统之前数据所在的位置叫做数据源,数据源可以是异构的,也就是说可以是任何形态存储的,甚至是人工录入的。稳定这个特性,则指的是数据仓库中的数据,一旦从数据源中存入,便不会再进行任何变化,只会在此基础上进行进一步的分析处理。   我们已经了解了数据仓库的四个特性中的三个,但是排在第一位的,最重要的“面向主题的”,却是比较难以理解的。很难用一两句定义来解释其中主题二字的含义。那么我们便只能以一个例子来说明:还是以航空公司为例,在航空公司的业务中,更受关注的往往是你乘坐的航班的编号、你选用的航空公司、你登机的时间等等,在前台业务中,被查询最多的,也便是这些信息。但是在数据仓库中,这些信息的重要性往往不如作为主体的你更加重要。航空公司们往往希望通过挖掘每个人的行为特征,来更加精准的为客户提供服务和推送广告,这里,客户,或者说人,便是一个主题了。所以读者们可以先笼统的认为,主题是数据分类的方法。   说完了数据仓库的的定义,让我们来看一看数据仓库中数据的层级结构。上一个章节中所述的离线计算、流数据计算以及实时计算的分类,指的是数据处理系统的分类,这里的层级结构,则指的是数据的组织形式。在这个方面,各种著作中的说法不一,但是从实践出发,笔者在这里将数据仓库的数据分为三个层面来叙述:数据运营层(ODS)、数据仓库层(DW)和数据产品层(Product)。   数据运营层,也叫ODS层,是最接近数据源中数据的一层,数据源中的数据,经过抽取、洗净、传输,也就说传说中的ETL之后,装入本层。本层的数据,总体上大多是按照源头业务系统的分类方式而分类的。例如这一层可能包含的数据表为:人口表(包含每个人的身份证号、姓名、住址等)、机场登机记录(包含乘机人身份证号、航班号、乘机日期、起飞城市等)、银联的刷卡信息表(包含银行卡号、刷卡地点、刷卡时间、刷卡金额等)、银行账户表(包含银行卡号、持卡人身份证号等)等等一系列原始的业务数据。这里我们可以看到,这一层面的数据还具有鲜明的业务数据库的特征,甚至还具有一定的关系数据库中的数据范式的组织形式。但是,这一层面的数据却不等同于原始数据。在源数据装入这一层时,要进行诸如去噪(例如去掉明显偏离正常水平的银行刷卡信息)、去重(例如银行账户信息、公安局人口信息中均含有人的姓名,但是只保留一份即可)、提脏(例如有的人的银行卡被盗刷,在十分钟内同时有两笔分别在中国和日本的刷卡信息,这便是脏数据)、业务提取、单位统一、砍字段(例如用于支撑前端系统工作,但是在数据挖掘中不需要的字段)、业务判别等多项工作。   数据仓库层(DW),是数据仓库的主体,在这里,从ODS层中获得的数据按照主题建立各种数据模型。例如以研究人的旅游消费为主题的数据集中,便可以结合航空公司的登机出行信息,以及银联系统的刷卡记录,进行结合分析,产生数据集。在这里,我们需要了解四个概念:维(Dimension)、事实(Fact)、指标(Index)和粒度( Granularity)。   事实(Fact)数据是一切数据的基础,是针对某一特定事件的度量。以上一段中研究人的旅游消费为主题的数据集为例,这个数据集中的主体的事实数据,便是人在出行到目的地之后,在目的地城市的刷卡消费信息,这一数据由业务发生的事实产生,所以叫做事实数据。维(Dimension)则是事实数据的其中一个侧面,例如人的旅行的目的地,则便是旅行消费信息的一个维度。   再举一个更加确切的例子,在淘宝网(天猫)中,我们以交易为主题建立一个数据集,那么每一笔交易的信息便构成一个事实表,每一个交易可能有几十个维度,例如商品的类目、卖家、买家、品牌等等。将全部的商品类目提取出来构成一张表,那么这张表便是这个数据集的一个维度表。在大型数据仓库中,维度表往往非常复杂。例如在淘宝(天猫)中,仅类目一个维度,便包含八十余个一级类目(行业类目)、成千上万个二三四级类目、以及最底层的叶子类目等信息,各个类目之间还存在着树状的关联,有的一级类目便同时是叶子类目(例如手机类目)。这些维度信息构成了庞大的围绕着事实数据的维度表系统。   粒度(Granularity)则表示数据仓库中数据集的精细程度。粒度越高,则数据的细节越多。例如在高粒度的数据表中,会包含一个人在任何城市中的每一条的刷卡记录,而在低粒度表中,则可能只包含一个人在各个城市中的刷卡总金额。这便是粒度不同的体现。这么做,是因为大多数的分析挖掘往往仅关注低维度的数据集合,那么使用高维度的数据集进行输入便会大规模的浪费系统资源。至于指标(Index),在笔者的理解中,则是相对于维度的一个概念,是数据集中不会按照维度进行筛选的数据,例如刷卡成交金额等。   在数据仓库层中,数据按照主题组织,按照不同的事实、维度进行组合和关联分析,构成了数据仓库中主体的数据。而最后一层数据产品层,则是数据仓库中的最上层。数据产品层使用DW层的数据集,针对要输出的产品不同,而进行不同的数据开发组合,最终输入给数据产品的数据库或实时计算系统中。例如一个分析每个城市的旅游人员的刷卡金额的数据产品,则可以在这一层中进行按照城市维度的各大银行刷卡信息的汇总的数据计算。   看了这么多基本理论,相信读者们也开始头昏脑涨了。不过没关系,从下一章开始,我们便会面对构建我们国民信息挖掘系统中的第一个超级技术难题:ETL系统的构建。   (三):ETL的开始——数据的传输和同步 在前面的章节中,我们提到,本文最终的目的,是带领大家构造设计一个“全民信息数据挖掘系统”。 而在上一节中,我们得知,数据仓库的特性之一便是其的“集成性”:不同的数据来源、不同的形式的数据集中在一处,在数据仓库系统中进行分析。这便是一个数据仓库系统的ETL的第一个步骤。所谓的ETL,便是Extraction-Transformation-Loading, 数据的提取、转换和装载到数据仓库的过程。数据从前端的业务系统中,装载到数据仓库中。在这个过程中,我们从数据源抽取出所需的数据,经过数据清洗,最终按照预先定义好的数据仓库模型,将数据加载到数据仓库中去。   说到数据源,当然指的便是业务系统中的各个数据来源,例如我们的各个网站或者C/S(客户端/服务器)系统中后台的各种数据库,如MySQL、SQLServer、Oracle、DB2等,如果再考虑到“全民信息挖掘系统”的特性,我国不少政府部门的业务数据库还在使用M$的FoxPro和Access, 这也是数据源的一种。上述提到的数据源,都是指的是业务系统使用的数据库系统,便是所谓的“第一类数据源”,具有高结构化(被软件系统辨识和处理的容易程度极高)、查询容易等的特点。   还有一类数据源,结构化程度相对较低,计算机处理起来相对困难,例如web服务器产生的日志(这个还是相对容易处理的),用户上传的图片等等。在这里,日志数据是比较特殊的一类数据源,一般来讲,日志是直接以文本文件记录在文件系统中的,日志记录了用户在网站上的全部访问情况,对数据挖掘至关重要,所以在各大互联网的企业中,对日志数据的传输,都做了大量特殊的处理。   总体来讲,在构建数据的传输和同步系统时,主要需要考虑两个方面,便是数据的结构类型,和对数据的时效性的要求。对于结构类型,主要分为数据库存储的高度结构化数据、日志等的半结构化文本数据、和图片等完全非结构化数据三种;在时效性方面,主要有(准)实时(数据产生后在短时间,一般是几分钟内便要同步到数据仓库)和定时传输(每天、周传输一次)两种情况。   我们先来看定时的数据库结构化数据传输的情况。数据库有很多种,每一种数据库的数据类型都略有不同,而我们的数据仓库系统,由于其的集中性,数据类型肯定是统一的、一致的。那么,要从各种数据库同步数据到数据仓库的过程中,我们需要进行数据的转换。不过,由于各种数据库均支持SQL语言,在SQL查询出的数据中,全部数据都可以转换为字符串(Block或Buffer一类除外,不过,这类数据我们一般也不会在数据仓库中分析),所以,我们通过字符串的转换方式,便可以达到数据源转换的效果。   更进一步的,由于我们一般不会直接让数据产品的最终用户直接通过数据仓库来查询数据(至于为什么我们后文会介绍),我们往往还需要在数据仓库分析处理数据之后将结果导入业务数据库,所以我们需要一个多方向的高自由度的结构化数据同步服务。在这里,我们可以采用阿里巴巴集团开发的开源产品 DataX 。 DataX可以在任意的异构数据源之间交换数据。数据在DataX的传输过程中以一种中间形态存在,DataX会管理好数据的传输、缓存等工作,而对于不同的数据源,DataX通过插件的形式来提供支持,插件的作用是将数据从数据源中读出并转换为中间形态,以及将中间形态的数据转换为目标数据源的数据格式而写入目标数据源。   就好似一个交通枢纽,核心是一个巨型的立交桥,而插件则相当于立交桥的入口和出口,在从港口来的行人,在港口-立交桥入口中从轮船上下来,乘车进入立交桥,再通过收费站来到公路,可以进入机场入口,再从汽车上下来登上飞机等等。。。这样就达到了任意类型的交通工具(数据源)的自由转换的目的。   DataX可以让我们在任意格式的结构化数据源间定时交换数据,而如果要在各个数据源间实时的交换数据,我们需要另一种方法。实时的数据传输的主要问题在于对业务数据库的性能上的压力,目前对于业务数据库实时同步到数据仓库中,最简单的方案是给业务数据库增加一个从(Slave)数据库,从数据库一般通过读取主数据库的OpLog(记录了每一次数据变化的操作),来和主(Master)数据库来保持数据的一致性,并且不会对主数据库造成很大的性能影响。最简单的,我们可以通过每分钟对从数据库的新增数据进行一次扫描读取,来传输到数据仓库中,因为业务系统是不连接从数据库的,所以这不会对业务系统造成影响。   但是,聪明的读者一定会想到,既然读取主数据库的OpLog便可以在不大影响性能的情况下保持数据的准实时同步,那么我们为什么还需要一个从数据库呢?这确实是解决问题的一个思路,不过解析OpLog相对于直接SQL查询从数据库来说更加困难,开发成本较高。腾讯的TDBank数据仓库系统中,采用了类似的方案,他们开发了MyDbSync软件,通过解析MySQL的binlog(也就是OpLog)来同步数据,取得了良好的使用效果。   我们再来看日志数据的同步,对于日志数据,我们在实践中以准实时的同步为主,因为每天的日志是源源不断的产生的,并且经常分布在成百上千台服务器的硬盘中,如果每天一次性的读取日志,在性能上得不偿失,所以应该在日志产生之后尽快以流的形式源源不断的同步到数据仓库中。一般来讲,我们通过消息订阅的模型来进行日志的准实时同步。我们建立一个日志数据交换中心,每台服务器的日志都由在这台服务器上的专门的软件源源不断的同步到日志交换中心上,然后需要存储这些日志的数据仓库们来订阅这些日志,就好像我们订阅报纸一样,一旦有新的日志数据到达,日志交换中心立刻通知数据仓库系统来取这些日志数据。在全部订阅者取完了这份日志数据之后,这份日志从日志交换中心的存储上删除,腾出空间来装载下一份日志。   阿里巴巴集团数据平台部门开发的 TimeTunnel , 便是可以用来建立日志数据交换中心的系统。TimeTunnel 部署的日志交换中心,只要一台服务器便可以实现2KB大小的日志数据的每秒钟4万条的实时传输,只要数十台服务器组成的日志中心集群,便足够承载我们的全民数据挖掘系统所需要的实时的数据如银行刷卡日志的同步工作了。   通过结构化数据库的数据实时/定时同步,以及日志数据的准实时同步,我们便可以把我们所需要的全民数据从全国各地同步到我们的数据仓库中心中,接下来,我们将对这些数据进行分析和清洗。对这样大规模的数据进行清洗,我们便要涉及大规模离线计算(如Hadoop/Hive)的使用,这便是我们日后要说的内容。