重点内容;大数据概念,大数据主要的应用场景以及了解目前主流的大数据平台和大数据组件的功能。
5个V
1;Volume;表示大数据的数据体量巨大。
数据集合的规模不断扩大;已经从 GB 级增加到 TB 级再增加到 PB 级;近年来;数据量甚至开始以 EB 和 ZB 来计数。
2;Velocity;表示大数据的数据产生、处理和分析的速度在持续加快。
加速的原因是数据创建的实时性特点;以及将流数据结合到业务流程和决策过程中的需求。数据处理速度快;处理模式已经开始从批处理转向流处理。
3;Variety;表示大数据的数据类型繁多。
传统 IT 产业产生和处理的数据类型较为单一;大部分是结构化数据。随着传感器、智能设备、社交网络、物联网、移动计算、在线广告等新的渠道和技术不断涌现;产生的数据类型无以计数。
4;Value;表示大数据的数据价值密度低。
大数据由于体量不断加大;单位数据的价值密 度在不断降低;然而数据的整体价值在提高。以监控视频为例;在一小时的视频中;有用的数据可能仅仅只有一两秒;但是却会非常重要。现在许多专家已经将大数据等同于黄金和石油;这表示大数据当中蕴含了无限的商业价值。
5;Veracity真实性
数据的准确性和可信赖度;一般可以理解为数据的质量。
重点内容;大数据的基石理论:GFS,MapReduce和BigTable的内容和原理,基于这些理论实现的大数据系统
《Google File System》(GFS) 这篇论文;就像是一篇设计文档一样;具体的描述了google如何去设计一个分布式的文件管理系统;来对每天产生的海量数据进行管理、储存、修改、访问。因为谷歌公布了其技术论文;更有国外类似如Hadoop的等开源框架的具体实现;国内的许多互联网大厂才能在此基础上设计自己的分布式文件管理系统;例如淘宝的TFS;Taobao File System; 、百度的BFS;Baidu File System;等等。
作为大数据的 “开山鼻祖”;进来我们就来简单了解一下google的 《Google File System》(下文简称GFS)。
设计预期;
在GFS的开篇中就说到;这个系统在设计之初就是希望设计成一个分布式的文件系统;其中整个系统由许多普通且廉价的服务器组成;大约几百台或者上千台;。系统设计完成必须要满足这么几个预期;
1、性能;这个系统要求对于数据的吞吐量必须要达到MB/s、GB/s甚至是TB/s的级别;这样在一瞬间有海量的数据涌来的时候;才能对这些数据进行处理。
2、可伸缩性;因为组成系统的每台服务器都是普通的服务器;因此每台服务器随时都有损坏、报废的可能;因此必须使得系统能够自动的检测哪些服务器出现了问题;并且可以自动的对其进行处理;不需要使得整个系统断电;就能动态的改变服务器的数量。这样的性能非常的重要;不但体现在服务器损坏时可以自动的修复;更加体现在比如 “双十一”时;这时候的数据量肯定比以往的数据量更加的庞大;因此需要的服务器的数量就更多;因为需要系统可以根据实时的需要;来决定使用的服务器的资源的多少;这样的 可伸缩性 使得整个系统的更加的灵活。
3、可靠性;这里的可靠性就是指系统需要有很强的容错能力;比如上文提到的;如果服务器突然损坏;怎么来保证数据不丢失;更有甚者;比如发生了自然灾害;整个数据中心崩溃;怎么来恢复数据;保证系统能继续进行正常的工作。还有在日常的一些对数据的访问的过程中;如果系统发生了物理上的异常;比如发生了0/1的跳变;那如何来进行容错;这些都是设计整个系统的可靠性时;需要进行考虑的东西。
4、可用性;可用性指用户如何来对数据进行访问、修改、追加、复制等操作;同时需要保证多个客户端并行;同时;的访问或者修改同一个数据时;怎么才能保证数据的一致性;是使得数据的修改不混乱;保证下一次读取时;数据时可用的;不是混乱的数据。
GFS中包含了数百台服务器;普通的计算机;;一个服务器就是一个节点;其中有一台服务器最特殊;叫做 “Master节点”;他是所有服务器的老大;其余的服务器都叫做 “Chunk节点”;整个系统叫做一个集群;而海量的数据都是存储在集群上的;同时数据的计算和处理也是基于集群工作的。
Master节点;Master节点是储存什么的呢?Master节点储存的是 “元数据”;说通俗点;储存的就是每一个Chunk数据的位置;以及每一个Chunk节点储存了哪些数据。 注意;master节点不存储具体的数据;具体的数据都存储在chunk节点上;Master节点相当于一个目录;你通过master节点就可以查到你想要的数据存储在哪一个chunk节点上;以及这个chunk节点的具体位置在哪里。
chunk节点; chunk节点用来存储具体的数据;其中的数据是一块一块的划分的;我们称作块数据;一块的大小为大概128M。注意;为了保证容错性;我们一般会使用3个chunk来存储相同的数据;也就是说将一份数据备份3份;这样当一个chunk出错或者损坏时;可以通过另外两份备份的数据;快速的将当前chunk的数据进行恢复。
下面举一个例子来说明;当客户端需要访问或者修改时;系统的交互流程;
1、客户端访问master节点;master节点根据客户端需要访问的数据;查找自身存储的索引信息;找到对应的chunk节点的位置和索引范围;
2、master节点返回chunk节点的位置;以及chunk节点中块数据;block;的范围;注意;因为相同的信息一般会存储在3个chunk节点当中;因此这里master节点会根据相应的算法来寻找距离最近的chunk节点;作为主chunk
3、客户端获取到chunk的位置和数据区域以后;和主chunk进行连接;访问主chunk内的数据;不再和master进行交流 注意;在没有意外的情况下;客户端一般是和主chunk进行交互;如果读数据有修改;再由主chunk将数据同步到其他的chunk之中
4、客户端访问chunk完成后;chunk向master进行通信;更新master内存储的数据区域的位置;保证客户端下次读取时数据的正确。
5、尽量减少对Master的访问;虽然我们使用的服务器都是普通且廉价的;但是master节点依然占有比较重要的位置;如果master节点损坏的话;会对整个系统产生比较严重的影响;因此我们应该尽量的减少对master节点的访问。而且master节点的数量相比于chunk节点很少;一般1个集群1台master节点;;如果所有的客户端访问该系统都需要频繁的和master节点进行交互的话;必然会严重降低系统的并行处理数据的性能;不符合我们整个系统大吞吐量的设计目标;因此;一般来说客户端每次访问系统只需要和master进行一次交互;在获取了相应的chunk的位置和数据范围后;以后的操作都直接和chunk进行交互就ok了;这样就避免了频繁的和master进行交互。
6、主chunk失效不需要重新访问master; 这里还有一个细节;master在返回chunk的位置和数据范围时;并不是只返回主chunk的位置和数据范围;而是连带着将其与两个chunk的位置和范围也一并返回;这样如果客户端访问主chunk失败;可以直接访问其他的两个chunk;不需要再和master进行交互。
7、“数据流”传输;chunk之间的数据传递是通过数据流的形式进行的。什么意思呢;比如;客户端在向主chunk进行写数据时;并不是说等全部写完了以后;主chunk再把数据同步到另外两个chunk。主chunk是一边接收;一边传输;收到多少数据;就把数据同步到另外两个chunk;因此也叫 “管道传输”。 这样做的目的也是为了提高系统的吞吐量性能;另外两台服务器不需要进行等待;可以进行工作。
8、主chunk“限时租约;超时收回”; master指定一台chunk节点作为主节点时;这个过程叫做 “租约”;租约一般是有时间限制的;当时间超出后;master会重新给客户端分配主chunk;这叫做 “租约更改” 。这样做的主要目的是为了防止主chunk内陷入死循环或者损坏时;系统的工作无法继续进行。
MapReduce是一种分布式计算框架 ;以一种可靠的;具有容错能力的方式并行地处理上TB级别的海量数据集。主要用于搜索领域;解决海量数据的计算问题。MR有两个阶段组成;Map和Reduce;用户只需实现map()和reduce()两个函数;即可实现分布式计算。
MapReduce可以分成Map和Reduce两部分理解。
1.Map;映射过程;把一组数据按照某种Map函数映射成新的数据。我们将这句话拆分提炼出重要信息;也就是说;map主要是;映射、变换、过滤的过程。一条数据进入map会被处理成多条数据;也就是1进N出。
2.Reduce;归纳过程;把若干组映射结果进行汇总并输出。我们同样将重要信息提炼;得到reduce主要是;分解、缩小、归纳的过程。一组数据进入reduce会被归纳为一组数据;或者多组数据;;也就是一组进N出。
3.mapreduce;我们将map过程和reduce过程连接起来;会发现会发现它是这样的;如下图;
在mapreduce的过程中;想要实现复杂的操作;就要多个类似上图的计算串联成为一个复杂计算过程;得到想要的结果;因为mapreduce过程更关心的是方法;过程的实现;;并没有给出API层面的数据集的概念。所以可以理解为;mapreduce过程是整个计算框架的基本运算单位。
MapReduce 的工作流程大致可以分为5步;
1、 分片格式化
2、 执行map task
3、 执行suffle
4、 执行reduce task
5、 写入文件
1、分片、格式化数据源
输入 Map 阶段的数据源;必须经过分片和格式化操作。
分片操作;指的是将源文件划分为大小相等的小数据块( Hadoop 2.x 中默认 128MB );也就是分片( split );Hadoop 会为每一个分片构建一个 Map 任务;并由该任务运行自定义的 map() 函数;从而处理分片里的每一条记录。
格式化操作;将划分好的分片( split )格式化为键值对<key,value>形式的数据;其中; key 代表偏移量; value 代表每一行内容。
2、执行 MapTask
每个 Map 任务都有一个内存缓冲区(缓冲区大小 100MB );输入的分片( split )数据经过 Map 任务处理后的中间结果会写入内存缓冲区中。
如果写人的数据达到内存缓冲的阈值( 80MB );会启动一个线程将内存中的溢出数据写入磁盘;同时不影响 Map 中间结果继续写入缓冲区。
在溢写过程中; MapReduce 框架会对 key 进行排序;如果中间结果比较大;会形成多个溢写文件;最后的缓冲区数据也会全部溢写入磁盘形成一个溢写文件;如果是多个溢写文件;则最后合并所有的溢写文件为一个文件。
3、执行 Shuffle 过程
MapReduce 工作过程中; Map 阶段处理的数据如何传递给 Reduce 阶段;这是 MapReduce 框架中关键的一个过程;这个过程叫作 Shuffle 。
Shuffle 会将 MapTask 输出的处理结果数据分发给 ReduceTask ;并在分发的过程中;对数据按 key 进行分区和排序。
4、执行 ReduceTask
输入 ReduceTask 的数据流是<key, {value list}>形式;用户可以自定义 reduce()方法进行逻辑处理;最终以<key, value>的形式输出。
5、写入文件
MapReduce 框架会自动把 ReduceTask 生成的<key, value>传入 OutputFormat 的 write 方法;实现文件的写入操作。
Combine 阶段;;在map之后;在reduce之前;;小文件合并;
当所有数据处理完成以后; MapTask 会对所有临时文件进行一次合并;以确保最终只会生成一个数据文件;合并的过程中会不断地进行排序和 Combine 操作
其目的有两个;
一是尽量减少每次写人磁盘的数据量
二是尽量减少下一复制阶段网络传输的数据量;最后合并成了一个已分区且已排序的文件。
;Hbase就是基于BigTable的理论产生的;
1、 存储方式;BigTable按key(row:string, column:string, time:int64) -> value(string)方式排序;方便快速索引。更细节地说;先按行名升序、如果行名相同再按列名升序、最后按时间戳为版本号降序排列。最后在文件系统中GFS中按lsm方式存储。
2、 数据拆分;为了实现集群;BigTable以行名范围对数据拆分片存储;每个分片叫tablet。每个tablet是相同行键前缀的数据集合。假设用户的数据行健以用户id开头、用户id为9位;那么以行健前9位划分tablet;就可以让相同用户的数据内聚到一个tablet中。
3、 与sql对比;BigTable是用于管理结构化数据。但它与传统的SQL又有一些差异;
a、每个SQL表的列是固定的;且列存储的数据类型也是固定的;但是BigTable的列数目、各行的列都可以不相同;所以BigTable是具备稀疏特征的说法。
b、SQL表的行号是数字型的;BigTable的行是字符串类型;即行名称;且各行的行名在写入时动态指定。
c、在底层存储结构上;很多传统SQL存储引擎;例如Innodb)采用B;树;而BigTable采用的LSM方式;从存储方式看;BigTable是以key(row:string, column:string, time:int64) -> value(string)方式的KV存储
这里需要关注一个重点;LSM树(Log-Structured-Merge-Tree)正如它的名字一样;LSM树会将所有的数据插入、修改、删除等操作记录(注意是操作记录)保存在内存之中;当此类操作达到一定的数据量后;再批量地顺序写入到磁盘当中。这与B;树不同;B;树数据的更新会直接在原数据所在处修改对应的值;但是LSM数的数据更新是日志式的;当一条数据更新是直接append一条更新记录完成的。这样设计的目的就是为了顺序写;不断地将Immutable MemTable flush到持久化存储即可;而不用去修改之前的SSTable中的key;保证了顺序写。
因此当MemTable达到一定大小flush到持久化存储变成SSTable后;在不同的SSTable中;可能存在相同Key的记录;当然最新的那条记录才是准确的;根据时间戳过滤;。这样设计的虽然大大提高了写性能;但同时也会带来一些问题;
问题;
1;冗余存储;对于某个key;实际上除了最新的那条记录外;其他的记录都是冗余无用的;但是仍然占用了存储空间。因此需要进行Compact操作(合并多个SSTable)来清除冗余的记录。
2;读取时需要从最新的倒着查询;直到找到某个key的记录。最坏情况需要查询完所有的SSTable;这里可以通过前面提到的索引/布隆过滤器来优化查找速度。
未完待续