分布式系统学习

如何协调多台机器高效、可靠地完成统一目标

单机系统引发的问题:

  1. 存储问题: PB级数据,单机根本无法存储全部数据
  2. 计算问题: 单机CPU和内存无法快速处理海量数据(如排序1TB数据单机需数小时)
  3. 可靠性问题:

通过多台机器协同工作,解决以下问题:

单机存储不足 -> 数据分片(Sharding)+ 多副本存储 单机算力不足 -> 并行计算(如MapReduce) 单点故障风险 -> 冗余设计 + 自动容错(如GFS多副本) 高并发请求处理 | 负载均衡 + 横向扩展(如BigTable分片)

分布式存储

把数据分散存储在多台服务器(节点)上,并通过网络把它们组织成一个整体,让用户看起来像是在访问“一个存储系统”。

数据切分: 把一个大文件拆分成很多小块(Chunk),分散到不同节点。 冗余: 每个数据块会有副本(常见是 3 份),保证某个节点宕机也能读到数据。 元数据管理(Metadata): 有专门的节点(如 Master / NameNode)记录每个数据块在哪台机器。 接口统一: 对外统一接口 用户看到的是一个统一的文件系统接口(如 HDFS 看起来像一个大文件系统)。

分布式系统实现的依赖:

_网络通信:_节点之间需要高效的 RPC/数据传输 _一致性协议:_确保写入时多个副本数据一致(GFS 用 Lease + 日志) _元数据存储:_Master 要有可靠的元数据存储(日志、检查点)。 _故障检测与恢复:_发现节点挂了,自动复制丢失的数据。 分布式锁/调度:(Master 内部或外部支持)。

什么是MapReduce

阅读MapReduce

MapReduce(Google)的思想:

Google 的 MapReduce 把分布式计算抽象成两个阶段: Map:对输入数据的每一部分执行相同的处理(比如提取词频) Reduce:把中间结果合并(比如统计每个词出现次数) 抽象度高 只需关注“对每个元素做什么(map)”和“怎么合并(reduce)”

全文搜索

倒排索引:

为什么快? 分析复杂度

N = 文档数量 L = 每个文档的平均长度(单词数) 遍历所有文档(N 个文档)。 在每个文档里查找 "Go"(要扫描这个文档的所有单词 → L)。 O(N × L)

而倒排索引:

首先需要构建索引,方便以后的查询 虽然 构建索引慢,但只做一次。 在构建中就已经搭建出:

Go → [ (doc1, [3]), // 第3个单词是 Go (doc2, [1]), // 第1个单词是 Go (doc3, [5]) // 第5个单词是 Go ] 用户输入关键词后,系统只需查倒排索引,不用再扫描文档全文,速度快

分布式排序

单机无法加载所有数据 → 必须分布式 如何保证全局有序(不仅是每台机器内部)? 如何负载均衡(避免某些机器分到的数据特别多)?

对于MapReduce的 分区策略:

比如 key < 1000 去 Reduce0,1000 ≤ key < 2000 去 Reduce1

框架自带排序能力:MapReduce Shuffle 阶段会对 key 排序,天然适合分布式排序。 可扩展性强:可以处理 PB 级数据,只需调整分区策略和增加节点。

接口实现取决于环境

  1. 小型共享内存机器:共享内存_的高速访问和低通信延迟使得实现可以专注于_单机内的并行计算,而不需要复杂的分布式协调机制。 2.大型 NUMA 多处理器: 3.硬件(双处理器 x86,2-4 GB 内存):低成本、计算资源有限,MapReduce 将任务分解为小粒度的 map 和 reduce 任务,充分利用多核并行计算,适合内存约束。 4.网络(100 Mbps/1 Gbps,实际带宽低):网络瓶颈显著,MapReduce 通过数据局部性(map 任务在数据节点执行)和中间结果压缩减少网络传输。 5.存储(IDE 磁盘 + GFS):廉价磁盘不可靠,GFS 通过分片和复制确保数据可用性,MapReduce 利用 GFS 的局部性调度降低 I/O 开销。

远程过程调用

在 MapReduce 中的作用(第 5 步):

Reduce worker 需要从 map worker 的本地磁盘读取中间键值对。由于这些数据分布在集群的不同机器上,Reduce worker 通过 RPC 向 map worker 所在的主机发起请求,获取数据。 RPC 的实现通常基于客户端-服务器模型,Reduce worker 作为客户端,Map worker 的主机作为服务器提供数据。

内部细节:

  1. 序列化/反序列化(Marshalling/Unmarshalling) 把内存数据结构转成可传输的格式(JSON、Protobuf、Avro 等)
  2. 网络通信 建立连接(TCP/HTTP) 请求/响应协议(如 gRPC 使用 HTTP/2 + Protobuf)
  3. 函数映射 客户端调用 → 服务端找到对应函数(通常通过函数名或服务ID)
  4. 错误处理 & 超时 网络延迟、失败重试、异常传播

Master数据结构

维护 任务调度 任务执行状态 维护map 文件输出位置

Master 节点: 是 MapReduce 框架中的协调者,负责任务调度、监控和容错。它运行在集群中的一台机器上,管理所有 worker 的任务分配和状态

主副本运行 Master 逻辑,分配任务、收集状态、转发中间数据位置。Master 通常是一个单独的进程,运行在集群中的一台机器上。它维护任务状态表(如“未分配”、“运行中”、“已完成”),通过心跳机制与 worker 通信。

其他副本(worker)运行用户定义的 map 或 reduce 函数,执行实际计算。

worker 通常是进程,而不是线程。每个 worker 是一个独立的执行单元,运行在集群的一台机器上,处理一个 map 或 reduce 任务。

为什么是进程: 进程间隔离强,故障不会影响其他 worker。 一台主机可以有多个worker 分布式集群中,线程模型难以跨机器管理。

处理Worker节点故障

如果正在处理map redeuce的worker发生故障 则应该被重置状态空闲 重新处理任务。


第一节课随堂笔记


在分布式系统中存储是一个痛点 很难完美的被实现这是为什么? RPC 线程(结构化并发)并发控制 锁机制 性能 (可拓展性加速) 可拓展性(叠加硬件)两倍的资源带来两倍的性能和吞吐量 如何使服务支持数百万用户(加速)按照比例分散用户到不同的机器(并行加速) 这种并行加速带来的问题:一旦数量增多 数据库的压力就会增大,某个时刻并行的加速就会带来瓶颈 容错性:服务器已经连续数年没有崩溃了 但是总有一天每天大约会有3台机器会发生故障  分布式中总会有设备发生问题  可用性:在特定故障下仍然保证系统可用 可恢复性: 停止响应请求 重启解决问题  非易失性存储: Flah技术 复制副本管理容错 

一致性: 键值服务 庞大的键值对表 Put Get  大量的数据拥有不同的数据版本 同一个get的值可能不同
强一致性 依靠通信保证 弱一致性 : 允许读取旧值   副本间的通信  都是巨大的成本 潜在的指令运行!

**正式讲解:**

排序时间非常的长       排序算法 网页索引器  框架! 所有能轻松的进行大规模计算
框架会处理一切
模运算的真正含义
Reduce中1的key 和 Map中的key
生成符合下一MapReduce作业所需要的格式或信息数据

Worker到底是什么? map的执行体? 
emit()机制 是什么? 将数据写入磁盘?  

主节点告知worker  请你去执行对于特定的输入文件执行map函数 

GFS  将大数据分割成小块 分布在GFS服务器上  GFS和MapReduce同时运行在服务器上 每个服务器上目前已经具有文件的切片了 每个woker 负责读取输入数据的千分之一 或者 MapReduce的文件就是从 GFS服务器上获取的? 这里存有疑惑  

大量的网络通信!! 网络吞吐量
在局域网内连接很多机器 让机器间作为通信 怎么做到? 

**如何尽量避免网络通信 就可能产生优化**!

在服务器上同时运行GFS 与 MAPREDUCE 确定哪个服务器在磁盘上持有文件!  将该输入文件的映射发送给同一机器上的MAPREDUCE 这个也有些疑惑? 我没有理解这句话的意思
每一份数据通过网络从 Map - > Reduce
小男孩提到了 reduce的流式操作?效率优势  流式操作为什么效率高?
10太字节是什么