介绍
分布式计算简单来说, 是把一个大计算任务拆分成多个小计算任务分布到若干台机器上去计算, 然后再进行结果汇总. 目的在于分析计算海量的数据, 从雷达监测的海量历史信号中分析异常信号 (外星文明), 淘宝双十一实时计算各地区的消费习惯等.
海量计算最开始的方案是提高单机计算性能, 如大型机, 后来由于数据的爆发式增长, 单机性能却跟不上, 才有分布式计算这种妥协方案. 因为计算一旦拆分, 问题会变得非常复杂, 像一致性, 数据完整, 通信, 容灾, 任务调度等问题也都来了.
举个例子, 产品要求从数据库中 100G 的用户购买数据, 分析出各地域的消费习惯金额等. 如果没什么时间要求, 程序员小明就写个对应的业务处理服务程序, 部署到服务器上, 让它慢慢跑就是了, 小明预计 10 个小时能处理完. 后面产品嫌太慢, 让小明想办法加快到 3 个小时.
平常开发中类似的需求也很多, 总结出来就是, 数据量大, 单机计算慢. 如果上 Hadoop,storm 之类成本较高, 而且有点大才小用. 当然让老板买更好的服务器配置也是一种办法.
利用分片算法
小明作为一个有追求有理想的程序员, 决定用介于单机计算和成熟计算框架的过度解决方案, 这样成本和需求都能满足了. 分布式计算的核心在于计算任务拆分, 如果数据能以水平拆分的方式, 分布到 5 台机器上, 每台机器只计算自身的 1/5 数据, 这样即能在 3 小时内完成产品需求了.
如上所述, 小明需要把这些数据按照一定维度进行划分. 按需求来看以用户 ID 划分最好, 由于用户之间没有状态上的关联, 所以也不需要事务性及二次迭代计算. 小明用简单的 hash 取模对 id 进行划分.
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family:"Courier New"!important; font-size: 12px !important;">f(memberid) % 5 = ServerN</pre>
这样程序可以分别部署到 5 台机器上, 然后程序按照配置只取对应余数的用户 id, 计算出结果并入库. 这种方式多机之间毫无关联, 不需要进行通信, 可以避免很多问题. 机器上的程序本身也不具备分布式的特性, 它和单机一样, 只计算自身获取到的数据即可, 所以如果某台机器上程序崩溃的话, 处理方式和单机一样, 比如记录下处理进度, 下次从当前进度继续进行后续计算.
利用消息队列
使用分片方式相对比较简单, 但有如下不足之处.
它不具有负载均衡的能力, 如果某台机器配置稍好点, 它可能最先计算完, 然后空闲等待着. 也有可能是某些用户行为数据比较少, 导致计算比较快完成.
还有一个弊端就是每台机器上需要手动更改对应的配置, 这样的话多台机器上的程序不是完全一样的, 这样可以用远程配置动态修改的办法来解决.
小明这种方式引入了个第三方, 消息队列. 小明先用一个单独的程序把用户信息推送到消息队列里去, 然后各台机器分别取消费这个队列. 于是就有了 3 个角色:
推送消息的, 简称 Master.
消息队列, 这里以 Rabbitmq 为例.
各个处理程序, 简称 Worker 或 Slave 都行.
虽然仅仅引入了个第三方, 但它已经具备了分布式计算的很多特性.
计算任务分发. Master 把需要计算的用户数据, 不断的推送消息队列.
程序一致性. Worker 订阅相同的消息队列即可, 无需更改程序代码.
任意扩容. 由于程序完全一样, 意味着如果想要加快速度, 重复部署一份程序到新机器即可. 当然这是理论上的, 实际当中会受限于消息队列, 数据库存储等.
容灾性. 如果 5 台中某一台程序挂了也不影响, 利用 Rabbitmq 的消息确认机制, 机器崩溃时正在计算的那一条数据会在超时, 在其他节点上进行消费处理.
Hadoop 简介
Hadoop 介绍已经相当多了, 这里简述下比如:"Hadoop 是一套海量数据计算存储的基础平台架构", 分析下这句话.
其中计算指的是 MapReduce, 这是做分布式计算用的.
存储指的是 HDFS, 基于此上层的有 HBase,Hive, 用来做数据存储用的.
平台, 指可以给多个用户使用, 比如小明有一计算需求, 他只需要按照对应的接口编写业务逻辑即可, 然后把程序以包的形式发布到平台上, 平台进行分配调度计算等. 而上面小明的分布式计算设计只能给自己使用, 如果另外有小华要使用就需要重新写一份, 然后单独部署, 申请机器等. Hadoop 最大的优势之一就在于提供了一套这样的完整解决方案.
下面找了介绍 Hadoop 的概览图, 跟小明的设计做对比下:
图中 "大数据计算任务" 对应小明的 100G 用户数据的计算任务.
"任务划分" 对应 Master 和消息队列.
"子任务" 对应 Worker 的业务逻辑.
"结果合并" 对应把每个 worker 的计算结果入库.
"计算结果" 对应入库的用户消费习惯数据.
PS: 为了方便描述, 把小明设计的分布式计算, 叫做小和尚.
MapReduce
由于 MapReduce 计算输入和输出都是基于 HDFS 文件, 所以大多数公司的做法是把 MySQL 或 sqlserver 的数据导入到 HDFS, 计算完后再导出到常规的数据库中, 这是 MapReduce 不够灵活的地方之一. MapReduce 优势在于提供了比较简单的分布式计算编程模型, 使开发此类程序变得非常简单, 像之前的 MPI 编程就相当复杂.
狭隘的来讲, MapReduce 是把计算任务给规范化了, 它可以等同于小和尚中 Worker 的业务逻辑部分. MapReduce 把业务逻辑给拆分成 2 个大部分, Map 和 Reduce, 可以先在 Map 部分把任务计算一半后, 扔给 Reduce 部分继续后面的计算. 当然在 Map 部分把计算任务全做完也是可以的.
如果把小明产品经理的需求放到 Hadoop 来做, 其处理流程大致如下:
把 100G 数据导入到 HDFS
按照 Mapreduce 的接口编写处理逻辑, 分 Map,Reduce 两部分.
把程序包提交到 Mapreduce 平台上, 存储在 HDFS 里.
平台中有个叫 Jobtracker 进程的角色进行分发任务. 这个类似小和尚的 Master 负载调度管理.
如果有 5 台机器进行计算的话, 就会提前运行 5 个叫 TaskTracker 的 slave 进程. 这类似小和尚 worker 的分离版, 平台把程序和业务逻辑进行分离了, 简单来说就是在机器上运行个独立进程, 它能动态加载, 执行 jar 或 dll 的业务逻辑代码.
Jobtracker 把任务分发到 TaskTracker 后, TaskTracker 把开始动态加载 jar 包, 创建个独立进程执行 Map 部分, 然后把结果写入到 HDFS 上.
如果有 Reduce 部分, TaskTracker 会创建个独立进程把 Map 输出的 HDFS 文件, 通过 RPC 方式远程拉取到本地, 拉取成功后, Reduce 开始计算后续任务.
Reduce 再把结果写入到 HDFS 中
从 HDFS 中把结果导出.
这样一看好像是把简单的计算任务给复杂化了, 其实如果只有几台计算任务的话, 使用 Mapreduce 确实是杀鸡用牛刀了. 如果有 TB,PB 级别的数据, 跑在成百上千台计算节点上, Mapreduce 的优势才会体现出来. 其计算框架图架构如下:
离线计算
通常称 Mapreduce 及小和尚这种计算为离线计算, 因为它对已经持久化的文件数据进行计算, 不能实时响应. 还有个原因就是它的处理速度比较慢, 它的输入和输出源都是基于 HDFS 设计, 如果数据不是一开始就写入到 HDFS 上, 就会涉及到数据导入导出, 这部分相对耗费时间. 而且它的数据流动是基于文件系统的, Map 部分输出的数据不是直接传送到 Reduce 部分, 而是先写入 HDFS 再进行传送.
处理速度慢也是 Mapreduce 的不足之处, 促使了后面实时计算的诞生.
另外个缺点是 Mapreduce 的计算任务流比较单一, 它只有 Map,Reduce 两部分. 简单的可以只写一部分逻辑来解决, 如果想拆分成多个部分, 如逻辑 A, 逻辑 B, 逻辑 C 等, 而且一部分计算逻辑依赖上一次计算结果的话, MapReduce 处理起来就比较困难了. 像 storm 框架解决此类问题的方案, 也称为流式计算, 下一章继续补充.
喜欢这篇文章的朋友可以点个喜欢, 也可以关注一下我的个人专题: Java 成长之路
针对于上面所涉及到的知识点我总结出了有 1 到 5 年开发经验的程序员在面试中涉及到的绝大部分架构面试题及答案做成了文档和架构视频资料免费分享给大家 (包括 Dubbo,Redis,Netty,zookeeper,Spring cloud, 分布式, 高并发等架构技术资料), 希望能帮助到您面试前的复习且找到一个好的工作, 也节省大家在网上搜索资料的时间来学习, 也可以关注我一下以后会有更多干货分享.
资料获取方式: QQ 群搜索 "708-701-457" 即可免费领取
来源: http://www.jianshu.com/p/f628770d7380