从Android部门转岗到数据智能中心已经一年多,这段时间主要是知识接收的阶段,精力也逐步放在大数据相关知识上,所以后续也不准备更新Android对应的博客了。经过一番踩坑,尝试着从小白的角度对大数据进行整体的讲解,也是对初期学习的总结,欢迎对大数据感兴趣的童鞋品尝。
一、前言
在正式介绍之前需要思考一下,为何我们要专门搭建Hadoop体系为首的大数据分析平台,要知道一个生产环境的大数据平台就像搭积木一样,需要对使用形形色色的组件进行构建,直接使用关系型数据库(比如MySQL)岂不是更加方便快捷,就此引出了以下概念:
1.1在线事务处理(OLTP, OnLine Transaction Processing)
这种模式对于从事后端的童鞋来说应该很熟悉,因为直接涉及到日常的业务,比如日常的用户的交易行为:
- 注册了一个账号
- 用户对商品下订单
- 用户进行支付
这些操作一般要求数据库进行事务处理来保障数据的一致性, 而且还得要求客户端查询修改速度要尽可能的快,也就是低延迟的读取和写入 —— 而不是批量处理作业(这些作业只能定期运行,比如每天一次)。应用程序通常使用索引通过某个键查找少量记录进行随机访问,再根据用户的输入插入或更新记录。由于这些应用程序是交互式的,因此访问模式被称为在线事务处理(OLTP, OnLine Transaction Processing)。
1.2在线分析处理(OLAP, OnLine Analytice Processing)
数据库也开始越来越多地用于数据分析决策,这些数据分析具有非常不同的访问模式。通常,分析查询需要扫描大量记录,比如上千万条记录,每个记录只读取几列,并计算汇总统计信息(如求平均值),而不是将原始数据返回给用户。例如,如果您的数据是一个用户的订单表,那么分析查询可能是:
- 这个月产品的销售额?
- 最近运营的推广活动中有多少增收?
- 买A产品的用户是否也会一起购买B?
这些查询通常由业务分析师编写,并提供给帮助公司管理层做出更好决策(BI商业智能)的报告。为了区分这种使用数据库的事务处理模式,它被称为在线分析处理(OLAP, OnLine Analytice Processing)。
1.3数据仓库
属性 | 事务处理 OLTP | 分析系统 OLAP |
---|---|---|
读取模式 | 查询少量记录,随机读取 | 在大批量记录上聚合 |
写入模式 | 随机访问,写入要求低延时 | 批量导入(ETL) |
针对用户 | 终端用户,通过Web应用 | 内部分析决策支持 |
处理的数据 | 数据的最新状态(当前时间点) | 随时间推移的历史事件 |
数据集大小 | GB ~ TB | TB ~ PB |
表1-1 比较事务处理和分析系统的特点
通过OLTP系统和OLAP对比分析,OLTP通常要保证高可用、低延迟、数据一致性,这些日常业务系统对我们至关重要,一旦出现问题会对线上用户造成较大的影响,对公司的经济也会造成损失。因此公司通常不愿意让业务分析人员在OLTP数据库上运行临时分析查询,因为这些查询需要扫描大部分数据集,代价很昂贵且有风险,会影响到线上用户正常使用。
为了避免这种情况发生,可以在单独的数据库上运行分析任务,与线上业务分离开来,这个单独的数据库被称为数据仓库(data warehouse)。
如果仅仅这样的话,数据仓库(data warehouse)也可以通过关系型数据库(例如MySQL)来实现,其提供的分库分表功能也可以达到对大数据量进行分析处理,事实也正是如此,早期的商业分析系统(BI系统)确实是基于关系型数据库实现的。但是问题随着时间推移逐渐暴露出来:
- 对于非结构化和半结构化数据的处理非常乏力,例如图片、文本、音频的存储、分析。
- 为了保障数据安全,机器性能要求比较高,而高端机器可能非常贵,如果分析的数据是低价值的话,例如线上的用户所有行为日志,性价比低。
- 当数据量过大的时候,查询速度极速下降,性能出现瓶颈。
- 关系型数据库为了保障数据的一致性有各种约束条件。但是数据仓库通常来说是只读的,不需要对数据做修改和一致性的保障,所以这些约束反而会成为影响性能的因素。
- 关系型数据库是写时模式,数据加载进来的时候就得明确定义特征,对于用于分析用户行为多维度数据来说是很难提前确定的。
二、大数据分析平台
在上述的一系列问题下,基于Hadoop的数据仓库逐渐表现出优异性,围绕Hadoop体系的生态圈也不断变大变强变快。Hadoop类似于Unix操作系统,其通过MapReduce作业来对分布式文件系统进行文件读写,该文件系统被称为HDFS(Hadoop分布式文件系统),一个Google文件系统(GFS)的开源实现。
2.1 数据存储
现在通过最简单的例子来分析Hadoop的HDFS和MapReduce,假设收集以下客户端日志,以文本格式存储在HDFS下,如下:
{"name":"张三","price":66,"content":"手机壳"}
{"name":"李四","price":88,"content":"手机壳土豪版"}
{"name":"王五","price":188,"content":"手机壳至尊版"}
{"name":"张三","price":67,"content":"手机壳2"}
{"name":"李四","price":89,"content":"手机壳土豪版2"}
HDFS会日志进行分布式存储,主要是分区和复制,分区是文件大小超过阈值后会对其进行分割(比如HDFS默认block size是128M),假设我们的日志大小超过阈值,分为log_1.txt:
{"name":"张三","price":66,"content":"手机壳"}
{"name":"李四","price":88,"content":"手机壳土豪版"}
{"name":"王五","price":98,"content":"手机壳至尊版"}
log_2.txt:
{"name":"张三","price":67,"content":"手机壳2"}
{"name":"李四","price":89,"content":"手机壳土豪版2"}
复制是存储在多个不同的节点上以获得容错能力,HDFS用户存储数据的服务器称为DataNode,默认把log文件放在3台不同的DataNode上,每个分区文件都有三个副本,这样子只要不是3台服务器同时出现问题就保证数据可用。
log.txt文件在HDFS中的分布大致如图:
当然,这些对于使用者来说是透明的,分布式存储主要优化的动作都在这一块上面。
2.2 数据读取之原始方式
已知在HDFS有文件log.txt,现在想计算每个用户的支付总数,一般情况下要进行以下步骤:
- 1、一次性读取全部文件内容
- 2、按行遍历文件
- 3、以用户名name为key聚合计算price
这种原始人的数据获取方式在数据量小的时候还能用一下,要是数据量有上千万上亿条,一次性获取解析,费时费力,估计服务器内存还得爆掉,完全没有使用到HDFS的分区复制的特性。
考虑一下,是否可以在多台机器下,每台机器读取一个分区来计算,然后在另外的机器上聚合中间结果再生成最终结果。这个时候MapReduce出现了,可以使用它编写代码来处理HDFS等分布式文件系统中的大型数据集。
2.3 数据读取之MapReduce
创建MapReduce作业,你需要实现两个回调函数,Mapper和Reducer。
Mapper
Mapper会在每条输入记录上调用一次,其工作是从输入记录中提取键值。对于每个输入,它可以生成任意数量的键值对。它不会保留从一个输入记录到下一个记录的任何状态,因此每个记录都是独立处理的。
Reducer
MapReduce框架拉取由Mapper生成的键值对,收集属于同一个键的所有值,并使用在这组值列表上迭代调用Reducer。
使用MapReduce的话,获取数据步骤如下:
- 1、在Mapper实现函数中解析每行记录,以name为键,price为值
- 2、在Reduce实现函数中以name为键迭代求和
- 3、把代码提交给调度器,计算结果会输出。
MapReduce调度器试图在其中一台存储输入文件副本的机器上运行每个Mapper,并且可以在多台机器上并行执行计算,而无需编写代码来显式处理并行问题。
2.4 数据读取之Hive
MapReduce针对于开发人员确实是可行的,但是很多底层细节需要开发人员自己维护,而且这这只适用于有经验的Java开发人员,因此将Hadoop放在了一个非程序员无法触及的位置,即使这些用户想通过Hadoop来分析他们的数据。
事实上,底层细节实际上是从一个任务到另一个任务的重复性操作,例如通过过滤得到所需的数据,以及执行类似于SQL的连接(JOIN)等。这个时候,基于一些高级工具比如Hive应运而生,能自动布线组装多个MapReduce阶段,生成合适的工作流。
Hive可以直接通过SQL语句进行数据查询,而无需编写重复代码及任务工作流之间的维护。
用Hive来执行以上查询的步骤:
// 大致的查询思想如下
SELECT name,SUM(price) FROM log GROUP BY name;
三、总结
主要是通过数据的存和取两方面来讨论我们为何使用Hadoop以及一些工具出现的原因,这里只是简单的总结,后续会一步步深入学习总结,也可以关注我司公众号灵机数据智能中心学习其它大佬们的深入文章。
参考:
1、《Hive编程指南》
2、《设计数据密集型应用》
3、对比解读五种主流大数据架构的数据分析能力