像看小说一样的大数据入门课

849 阅读13分钟

今天看了MIT的分布式系统的网课6.824, 第一堂课就提到了Google在2004年前后发表的三篇论文, 也就是我们熟知的"三驾马车":

  • 分布式文件系统GFS
  • 大数据分布式计算框架MapReduce
  • NoSQL数据库系统BigTable

注意这里为什么有的叫系统, 有的叫框架, 框架在架构设计上遵循一个重要的设计原则叫“依赖倒转原则”,依赖倒转原则是高层模块不能依赖低层模块,它们应该共同依赖一个抽象,这个抽象由高层模块定义,由低层模块实现。

在当时谷歌提出这个是为了解决大量网页的内容抓取, 存储, 以及排名的问题的. 可以想象, 这个过程的存储于计算量是多么的庞大. 谷歌的这篇论文也表现了谷歌当时解决这个问题的思路: 部署一个大规模的服务器集群, 使用更多的普通机器完成这个任务而非少量的高性能服务器.

后来, Hadoop应运而生, 创造了一个时代, 甚至成为了大数据的代名词.

Hadoop主要包括分布式文件系统HDFS和分布式计算系统MapReduce. 此后, 出现了许多Hadoop的周边产品, 大数据的生态环境也逐渐形成并扩大, 更多的数据分析师开始使用大数据系统进行数据分析.

后来诞生了著名的资源调度框架: Yarn, 再后来各种框架与技术层出不穷, 像批处理框架: Spark甚至直接威胁到了MapReduce的地位, 一经推出便受到业界追捧, 像一些流处理框架: Flink, Storm, Spark Streaming也解决了实时性的一些应用场景中批处理的不足之处; 还有HBase这样优秀的NoSQL框架,等等等等...

谷歌可能自己都没有想到, 它当初的那篇论文, 开启一个崭新的大数据时代!!!


第一驾马车: 分布式文件系统

如果说数据是菜, 分布式计算系统是一个厨艺精湛的厨子, 那么分布式文件系统就是那一口大锅. 若没有一个分布式文件存储系统, 那么一切无从谈起.

最著名的分布式文件系统是HDFS, 从它的设计理念中, 我看到了分布式系统原则中的透明性: 对应用程序提供PB级的存储容量, 但是却让程序感觉在使用一个普通的文件系统.

那么HDFS是如何设计的呢? 它如何支撑起这么大的数据存储的呢?

核心原理: 将RAID的理念扩大到整个分布式服务器集群

在这里我简要的介绍一下什么是RAID: 就是将数据分片, 同时写入到多个磁盘中, 当然, 真实过程远没有这么简单, 你还得解决数据备份的问题等等.

HDFS也对数据进行了分片, 然后并行读写, 同时还进行了一些数据冗余以保证可用性, 它的这个存储其实是站在巨人的肩膀之上---模仿了操作系统中文件系统的NameNode与DataNode, 你可能又不懂了, 那么我来简要介绍一下, NameNode就是存储元数据, 元数据就是数据的数据, 比如说这个数据的ID, 它存在了哪个磁盘之上等等, 就这样一级级的指下去(其实没有几级), 你就找到了数据的存储位置, 有兴趣的可以自己去了解一下.

看到这里, 你是不是觉得HDFS没有什么厉害的, 都是一些以前有的东西. 其实我也这么觉得, 但是我一直信仰大道至简. 下面我们来谈一谈为什么HDFS会这么流行吧.

我们知道, 分布式系统中我们很关注可用性, 而从HDFS的设计中就可以看出它履行了这一个理念!

  • 数据存储故障容错: 可能由于电路的一些问题, 磁盘上面存储的数据出现了错误, HDFS的解决办法是对于每一个DataNode上面的数据块, 都按照一个算法计算并存储一个校验和, 每当你读取一个数据块的时候都会重新计算一遍校验和, 并与之前存储的校验和进行对比, 如果不正确就到其他备份的DataNode上面读取数据

  • 磁盘故障容错: 我们知道磁盘的寿命是有限的, 如果磁盘发生了损坏, 那么HDFS就会将该磁盘对应的备份数据复制到其他服务器上面, 以保证备份数不变

  • DataNode故障容错: DataNode与NameNode之间通过心跳包来保持联系, 如果DataNode超时未发送心跳包, NameNode就会认为这个DataNode宕机了, 然后查找相应备份, 复制到其他服务器上面

    其实我认为这个设计有点不好, 如果DataNode只是暂时的断网了呢? 过一会就恢复网络了呢?

  • NameNode故障容错: NameNode是整个系统的核心, 要是NameNode出问题了, 那么整个系统就瘫痪了. 其实这个NameNode与DataNode的结构也是很普遍的一主多从.

    所以一定要保证NameNode的高可用, 我们的HDFS采用了主备热从的方式, NameNode服务器其实是一个集群, 其中只有一个主服务器才能提供服务, 那么这个时候谁是主服务器就显得至关重要, 否则就会出现"脑裂"的现象, 我们采用的是Zookeeper来进行分布式选举, 确保在任何时候只会有一个主服务器

关于分布式文件系统, 我想谈的就是这么多了!

第二驾马车: 分布式计算框架

MapReduce火了, 我认为它火的原因有两个, 一是因为它解决了大规模数据的计算问题, 二是因为它降低了大数据处理的门槛, 我们只需要根据MapReduce编程框架编写业务逻辑代码即可, 而不用管一些运行时环境的配置或者内部进行了哪些调用.

MapReduce的概念: 指定一个*Map(映射)函数,用来把一组键值对映射成一组新的键值对,指定并发的Reduce(归纳)*函数,用来保证所有映射的键值对中的每一个共享相同的键组。来自维基百科

MapReduce, 顾名思义, 它的处理主要包含两个过程: map和reduce, 这个其实是函数式编程的两个基本函数:

图片出处: CMU15210串并行数据结构教材

以后有机会的话我应该会写一篇博客介绍一下函数式编程的, 并分享一下CMU的这门课程.

map函数可以对一部分数据进行计算, 于是在分布式系统中, 我们可以对HDFS分出来的每一个块分配一个map函数进行计算(移动计算), 然后将计算的结果输入reduce程序并计算出最后的结果.

一般介绍MapReduce都是举WordCount的例子, 但我之前看到过一篇博客介绍了一个更加容易懂得例子:

你想数出一摞牌中有多少张黑桃。直观方式是一张一张检查并且数出有多少张是黑桃?

MapReduce方法则是:

  1. 给在座的所有玩家中分配这摞牌
  2. 让每个玩家数自己手中的牌有几张是黑桃,然后把这个数目汇报给你
  3. 你把所有玩家告诉你的数字加起来,得到最后的结论

总结一下: MapReduce这个模型可以用两个词语来形容: 简单和强大

  • 简单是因为它只有map与reduce这两个过程
  • 强大是因为它几乎可以实现大数据领域所以得计算需求

第二架马车介绍完毕QwQ

第三驾马车: NoSQL数据库系统

在海量数据面前, 关系型数据库表现出了它的不足之处.

因为传统的关系型数据库为了保证关系运算的正确性, 在设计数据库表结构的时候, 需要指定表的字段名称, 以及数据类型等, 并且还要遵循特定的设计范式. 这样做可能会为查询与插入带来很大的性能提升, 但是对于需求的变更, 这样僵硬的数据结构就力不从心了, 有经验的工程师可能会预先设计一些冗余字段来应对需求的变更, 但是设想一下, 对于一个学生的基本信息表,表中不同学生的联系方式各不相同,选修的课程也不同, 而且将来还会有更多联系方式和课程加入到这张表里,如果按照传统的关系数据库设计,无论提前预设多少冗余字段都会捉襟见肘、疲于应付。

而这种场景之下, 非关系型数据库可以很好的解决此类问题.

NoSQL, 就是非关系型数据库, 这是一种很好的支持分布式, 支持海量数据存储的数据库设计模式. 相比于关系型数据库将一些业务处理逻辑包含在了数据存储之中, 非关系型数据库则只在数据库中存储数据, 不包含任何的业务逻辑.

NoSQL中的杰出代表就是HBase.

那么它是如何解决可扩展性的问题的呢? 不用修改表的结构如何新增字段呢?

对于可扩展性, HBase的核心原理就是利用了HRegion的分裂性:

简单介绍一下: 在HBase中, 数据的存储主要靠的是一个叫做HRegion的东西, 你可以把它理解成一个管理员, 所有的数据读写操作都必须交给它来完成.

一台物理服务器上面会有多个这样的HRegion进程, 当一个HRegion进程管理的数据到达了一个阈值的时候, 它就会分裂成两个, 把它管理的数据迁移到集群中的其他物理主机上面, 这就实现了负载均衡.

其实这个HRegion也相当于一个分片, 你可以这样去理解, 如果你还想进一步了解, 可以去查阅相关的资料

对于字段的添加, HBase的设计采用了列族:

其实许多的NoSQL数据库都使用了列族, 在创建表的时候, 你只需要指定列族的名称, 而无需指定字段, 字段可以在写入数据的时候再进行指定, 这样就可以不用更改表的结构达到新增字段的目的啦!

至于HBase的存储, 它采用了一种叫做LSM树的东西, 有兴趣的可以自己查阅一下相关资料...


好了, 到这里三驾马车就讲完了, 下面我来介绍一下大数据生态圈的其他知识吧!

移动计算而不是移动数据

我们以往的计算处理架构是, 给一个程序传入数据, 然后执行计算, 最后该程序输出结果.

但是在大数据时代, 我们的数据量巨增, 一方面是因为用户数增多, 另一方面是因为以往很多被我们忽视的数据被重新利用了起来, 比如说前端的埋点, 记录你在哪个商品鼠标悬停了多长时间这样的数据.

所以传统的计算模型已经满足不了我们的需求了, 因为一个程序不可能读取这么大量的数据, 所以我们采取分布式集群, 用成千上万台计算机来进行计算. 由于这些数据之间可能互相有关联, 比如说经典的"啤酒与尿布", 我们可能想要挖掘出这样的东西, 所以我们不仅需要分布式计算, 分布式存储, 我们还需要分布式通信.

由于一个程序相对于那么大量的数据来说小得多, 而且现在也有Docker这么方便的容器技术了, 我们的程序只需要打个包, 这个包里面含有这个程序运行时需要的一系列环境, 避免你在宿主机上安装这些环境, 还可以避免一些依赖的版本问题, 然后分发到那些需要进行计算的服务器上面就可以了!

很显然, 一次分发这么多程序可能会导致网络通信的瓶颈, 所以我认为可以向一个集群中的一台机器发送这个打包的程序, 然后这个集群中的其他机器从这台机器拷贝.

其实说了这么多, 你只用记住一点就行了: 在大数据领域, 移动计算比移动数据更划算

大数据的资源调度

大数据的处理中不仅有大量的数据, 而且还有大量的计算资源(那成千上万的服务器), 所以我们需要一个专门执行计算调度的东西.

回望大数据早期, Hadoop1 的时候, MapReduce的计算与资源调度就耦合在了一起, 这里你先思考一下, 这样做会带来什么问题? 为什么Hadoop2要把这个资源调度给解耦出来呢?

-----------------------------------------我是一条可爱的分界线-------------------------------------------

因为资源调度在MapReduce这个计算框架之中, 如果你想在这个集群中运算其他的计算任务, 比如说Spark, Flink, 那么你就无法使用集群中的资源了, 因为资源归MapReduce管, 如果资源调度和计算框架耦合在一起, 那么你就得为每个计算框架单独部署一个集群, 这很显然不经济.

比如Yarn就是一个有名的大数据资源调度框架, 下面简单的介绍一下这个框架:

它也是一个典型的主从模式的框架:

  • 资源管理器(Resource manager): 负责整个集群的资源管理调度
  • 节点管理器 (Node manager): 负责具体服务器上面的资源管理调度

不知道你发现没有, 介绍到现在好多框架都是这样一种架构, 集中管理, 分布存储于计算

没错, 是这样的, 一个好的架构模式总会有人争相模仿的.

原创不易, 限于本人水平有限, 文中难免会有一些地方出现纰漏, 敬请指正, 如果您觉得本篇文章帮助到您了, 可以点一个赞哟, 您的一个赞将是对我的极大鼓励!^ _ ^