进入大数据阶段就意味着进入NoSQL阶段,更多的是面向OLAP场景,即数据仓库、BI应用等。
大数据技术的发展并不是偶然的,它的背后是对于成本的考量。前文提到的集中式数据库或者基于MPP架构的分布数据库往往采用的都是性能稳定但价格较为昂贵的小型机、一体机或者PC服务器等,扩展性相对较差;而大数据计算框架可以基于价格低廉的普通的硬件服务器构建,并且理论上支持无限扩展以支撑应用服务。
在大数据领域中最有名的就是Hadoop生态,总体来看,它主要由三部分构成:底层文件存储系统HDFS(Hadoop Distributed File System,Hadoop分布式文件系统)、资源调度计算框架Yarn(Yet Another Resource Negotiator,又一个资源协调者)以及基于HDFS与Yarn的上层应用组件,例如HBase、Hive等。一个典型的基于Hadoop的应用如图3-7所示。
图3-7 一个典型的Hadoop应用
HDFS被设计成适合运行在通用硬件(Commodity Hardware)上的分布式文件系统。它和现有的分布式文件系统有很多共同点,例如典型的Master-Slave架构(这里不准备展开介绍),也有不同点,HDFS是一个具有高度容错性的系统,适合部署在廉价的机器上。关于HDFS这里主要想说两点,默认副本数的设置以及机架感知(Rack Awareness)。
HDFS默认副本数是3,这是因为Hadoop有着高度的容错性,从数据冗余以及分布的角度来看,需要在同一机房不同机柜以及跨数据中心进行数据存储以保证数据最大可用。因此,为了达到上述目的,数据块需要至少存放在同一机房的不同机架(2份)以及跨数据中心的某一机架(1份)中,共3份数据。
机架感知的目的是在计算中尽量让不同节点之间的通信能够发生在同一个机架之内,而不是跨机架,进而减少分布式计算中数据在不同的网络之间的传输,减少网络带宽资源的消耗。例如当集群发生数据读取的时候,客户端按照由近到远的优先次序决定哪个数据节点向客户端发送数据,因为在分布式框架中,网络I/O已经成为主要的性能瓶颈。
只有深刻理解了这两点,才能理解为什么Hadoop有着高度的容错性。高度容错性是Hadoop可以在通用硬件上运行的基础。
Yarn是继Common、HDFS、MapReduce之后Hadoop 的又一个子项目,它是在MapReduceV2中提出的。
在Hadoop1.0中,JobTracker由资源管理器(由TaskScheduler模块实现)和作业控制(由JobTracker中多个模块共同实现)两部分组成。
在Hadoop1.0中,JobTracker没有将资源管理相关功能与应用程序相关功能拆分开,逐渐成为集群的瓶颈,进而导致集群出现可扩展性变差、资源利用率下降以及多框架支持不足等多方面的问题。
在MapReduceV2中,Yarn负责管理MapReduce中的资源(内存、CPU等)并且将其打包成Container。这样可以使MapReduce专注于它擅长的数据处理任务,而不需要考虑资源调度。这种松耦合的架构方式实现了Hadoop整体框架的灵活性。
Hive是基于Hadoop的数据仓库基础构架,它利用简单的SQL语句(简称HQL)来查询、分析存储在HDFS中的数据,并把SQL语句转换成MapReduce程序来进行数据的处理。
Hive与传统的关系型数据库的主要区别体现在以下几点。
1)存储的位置,Hive的数据存储在HDFS或者HBase中,而后者的数据一般存储在裸设备或者本地的文件系统中,由于Hive是基于HDFS构建的,那么依赖HDFS的容错特性,Hive中的数据表天然具有冗余的特点。
2)数据库更新,Hive是不支持更新的,一般是一次写入多次读写(这部分从Hive 0.14之后开始支持事务操作,但是约束比较多),但是由于Hive是基于HDFS作为底层存储的,而HDFS的读写不支持事务特性,因此Hive的事务支持必然需要拆分数据文件以及日志文件才能支持事务的特性。
3)执行SQL的延迟,Hive的延迟相对较高,因为每次执行都需要将SQL语句解析成MapReduce程序。
4)数据的规模上,Hive一般是TB级别,而后者规模相对较小。
5)可扩展性上,Hive支持UDF、UDAF、UDTF,后者相对来说可扩展性较差。
HBase(Hadoop Database)是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统。它底层的文件系统使用HDFS,使用ZooKeeper来管理集群的HMaster和各RegionServer之间的通信,监控各RegionServer的状态,存储各Region的入口地址等。
HBase是Key-Value形式的数据库(类比Java中的Map)。既然是数据库那肯定就有表,HBase中的表大概有以下几个特点。
1)大:一个表可以有上亿行,上百万列(列多时,插入变慢)。
2)面向列:面向列(族)的存储和权限控制,列(族)独立检索。
3)稀疏:对于空(null)的列,并不占用存储空间,因此,表可以设计得非常稀疏。
4)每个单元格中的数据可以有多个版本,默认情况下版本号自动分配,是单元格插入时的时间戳。
5)HBase中的数据都是字节,没有类型定义具体的数据对象(因为系统需要适应不同类型的数据格式和数据源,不能预先严格定义模式)。
这里需要注意的是,HBase也是基于HDFS,所以也具有默认3个副本、数据冗余的特点。此外HBase也是利用WAL的特点来保证数据读写的一致性。
HBase采用列式存储方式进行数据的存储。传统的关系型数据库主要是采用行式存储的方式进行数据的存储,数据读取的特点是按照行的粒度从磁盘上读取数据记录,然后根据实际需要的字段数据进行处理,如果表的字段数量较多,但是需要处理的字段较少(特别是聚合场景),由于行式存储的底层原理,仍然需要以行(全字段)的方式进行数据的查询。在这个过程中,应用程序所产生的磁盘I/O、内存要求以及网络I/O等都会造成一定的浪费;而列式存储的数据读取方式主要是按照列的粒度进行数据的读取,这种按需读取的方式减少了应用程序在数据查询时所产生的磁盘I/O、内存要求以及网络I/O。
此外,由于相同类型的数据被统一存储,因此在数据压缩的过程中压缩算法的选用以及效率将会进一步加强,这也进一步降低了分布式计算中对于资源的要求。
列式存储的方式更适合OLAP型的应用场景,因为这类场景具有数据量较大以及查询字段较少(往往都是聚合类函数)的特点。例如最近比较火的ClickHouse也是使用列式存储的方式进行数据的存储。
Spark由Twitter公司开发并开源,解决了海量数据流式分析的问题。Spark首先将数据导入Spark集群,然后通过基于内存的管理方式对数据进行快速扫描,通过迭代算法实现全局I/O操作的最小化,达到提升整体处理性能的目的。这与Hadoop从“计算”找“数据”的实现思路是类似的,通常适用于一次写入多次查询分析的场景。
Spark Streaming是基于Spark的一个流式计算框架,它针对实时数据进行处理和控制,并可以将计算之后的结果写入HDFS。它与当下比较火的实时计算框架Flink类似,但是二者在本质上是有区别的,因为Spark Streaming是基于微批量(Micro-Batch)的方式进行数据处理,而非一行一行地进行数据处理。