计算:MapReduce
“Do one thing, and do it well”
核心功能
数据本地化的并行计算
针对存放在上千个节点的 GFS 上的数据,如何进行数据处理?
计算需求举例:统计网页的访问频次,有三个字段:URL、用户ID和访问时间,数据存储在GFS上。
SELECT URL, COUNT(*) FROM url_visit_logs GROUP BY URL ORDER BY URL
- Map过程
- 输入:行号, URL,用户ID,访问时间
- 输出:URL:空字符串
- Shuffle过程
- 把相同的Key的Value整合在一个列表中
- 输出:URL:[“”, “”,“”,“”]
- Reduce过程
- 对混洗后的数据执行COUNT函数
- 输出:URL:计数
系统容错和自动恢复
如何做好服务器之间的协同?
提交MR任务后:
- 根据指定的输入路径找到对应的数据,对数据进行分片split,等于GFS中一个块Block的大小,然后MR会在整个集群上启动很多个MR的复刻fork进程。
- 在这些进程中,有一个是master进程,剩下的是worker进程。我们有M个map人物和R个reduce任务分配给worker去处理,而master进程是负责找到空闲的worker进程,然后把任务分配给worker进程处理。
PS:hadoop 2.0后的版本master的角色是Resource Manager,worker的角色是Application Master.
- 被分配到map任务的worker会读取某个分片,变成key-value给map任务,Map函数计算完后,会生成新的key-value对缓存在内存中。
- 缓存的key-value对,会定期写到map任务所在机器的本地硬盘上。并且按照一个分区函数,把输出的数据分成R个不同的区域,这些本地文件的位置会被传给master节点,master节点转发给reduce任务所在的worker那里。
- reduce任务的worker在收到master通知后,会通过RPC从map任务所在机器的本地磁盘上抓去数据。当获取完所有的数据后,reduce任务会将文件根据Key排序,相同key的value会被放在一起,也就是shuffle过程。
- reduce任务最后执行Reduce函数,并把结果输出到当前reduce分片最终的输出文件里。
- 当所有map和reduce任务执行完后,master会唤醒启动MR任务的用户程序,然后回到用户程序里,执行MR任务提交之后的代码逻辑。
如何解决软硬件的容错?
-
重新运行
master节点会定期去ping每一个worker节点,如果失效,会重新在另一台服务器上,启动worker进程,重新运行所有在失效节点上分配的任务。 -
写Checkpoints
如果是master节点失效呢?master存放的信息会作为Checkpoints定期写入到硬盘里去。调度系统监控master,如果失效了启动一个新的master来读取cp数据,然后就可以恢复任务的继续执行了。
如何解决性能问题?避免网络瓶颈?
-
把MR程序代码复制到GFS数据所在服务器上,如果数据所在节点没有worker,就分配给最近的worker处理。
-
通过Combiner减少网络数据传输
让中间数据的数据量小一些,对Map函数的输出结果做一次聚合,同一台服务器上的Map输出都可以合并。
如何保持易用性,方便debug?
- 提供单机运行的MR库,可以拿一点小数据在本地调试MR任务。
- 在master里内嵌了一个HTTP服务器,把master状态展示给开发者看。
- 计数器机制,在Map和Reduce函数里调用计数器进行自增,所有的map和reduce计数器都会汇总在master节点上。
演进
- 计算模型简单——>演进到Hive类SQL语言
- 海量磁盘读写——>演进到spark把数据放在内存而不是磁盘