Hadoop-python中使用大数据1

一、回顾:我们手里有什么,目标是什么

上篇我们造出了 1000 万条卡口过车记录(约 400 多 MB 的 gateway_records2.txt),并发现单机一次性统计"每个城市的车流量"既费内存又费时间。这一篇,我们按照"分而治之"的思想,用 Python 依次实现 MapReduce 的三个阶段:Split(分片)→ Map(映射)→ Reduce(归约),完整跑通一次"迷你 MapReduce"。

二、第一阶段 Split:把大文件切成 1000 个小文件

"分"是第一步。Demo03 把 400 多 MB 的大文件按每 10000 行一片,切成 1000 个小文件,命名为 part-0、part-1......part-999,存放在 split 目录下:

将400M的文件切分成1000个小文件

page = 0

split_f = open(f"split\\part-{page}", mode="w", encoding="utf-8")

count = 0

line = f.readline() # 逐行读取,而不是一次性readlines

while line: # 还有数据就继续循环

count += 1

split_f.write(line) # 写入当前分片

line = f.readline() # 读取下一行

if count == 10000: # 当前分片写满1万行

print(f"已生成:part-{page}")

count = 0

page += 1

split_f.close() # 关闭当前分片

split_f = open(f"split\\part-{page}", mode="w", encoding="utf-8")

注意两个细节:一是这里用 readline() 逐行读取,而不是 readlines() 一次性读入内存------这是处理大文件的通用技巧,上篇单机版的 OOM 问题就源于此;二是"每写满 1 万行就换下一个文件"的写法,正是 Hadoop"按块切分"思想的简化版。

补充知识:在真实的 Hadoop 中,切分由 HDFS 完成------文件上传时就被物理切成块(默认 128MB 一块),每个块默认存 3 份副本分散在不同机器上(既防止数据丢失,又方便并行读取)。Map 任务不是按"行数"而是按"块"来分配数据的。

三、第二阶段 Map:并行处理每一个分片

数据切好后,把每个小文件交给一个"工人"去统计。Demo04 遍历 split 目录下的 1000 个小文件,对每个文件独立执行"按城市分组计数",并把局部结果写入 map 目录下的同名文件:

import os

base_dir = "split\\"

files = os.listdir(base_dir) # 1000个小文件

for file in files: # 每个文件独立处理,互不干扰

file_path = base_dir + file

with open(file_path, mode="r", encoding="utf-8") as f:

lines = line.strip() for line in f.readlines()

citys = line.split(",")\[2 for line in lines]

city_num = {} # 局部统计字典

for city in citys:

if city not in city_num:

city_numcity = 1

else:

city_numcity += 1

把本文件的局部结果写出去

with open(f"map\\{file}", mode="w", encoding="utf-8") as w_f:

for city, num in city_num.items():

w_f.write(f"{city},{num}\n")

这里有两个关键点值得细品:

  1. 每个小文件的统计逻辑与上篇单机版 Demo02 完全一样,只是数据量从 1000 万行缩小到了 1 万行------单机"吃不下"的大问题,被拆成了 1000 个"吃得下"的小问题;

  2. 文件之间的统计互不依赖------这正是并行计算的前提。在真实集群中,1000 个 Map 任务可以被调度到成百上千台机器上同时执行,总耗时不再等于"处理 400MB 的时间",而是约等于"处理 1 万行的时间"。单机要跑几分钟的活,并行起来几秒钟就能完成。

四、第三阶段 Reduce:汇总 1000 份局部结果

Map 阶段结束后,map 目录下出现了 1000 个中间结果文件,内容都是"城市,数量"的键值对,例如"武汉,1006"。最后一步"合":把所有局部统计汇总成最终结果。Demo05 读取 map 目录下全部文件,用同一个字典做全局累加,最终输出到 reduce/part-0:

import os

base_dir = "map\\"

files = os.listdir(base_dir)

city_num = {}

for file in files: # 遍历1000个中间结果文件

with open(file_path, mode="r", encoding="utf-8") as f:

lines = line.strip() for line in f.readlines() # 武汉,1006

for line in lines:

city = line.split(",")0

num = int(line.split(",")1)

if city not in city_num:

city_numcity = num

else:

city_numcity += num

保存最终结果

with open("reduce\\part-0", mode="w", encoding="utf-8") as w_f:

for city, num in city_num.items():

w_f.write(f"{city},{num}\n")

到这里,"分 → 算 → 合"三步全部完成。reduce/part-0 中的每一行,就是每个城市的最终车流总量。

五、串起来看:一次完整的迷你 MapReduce

把三个阶段连起来,完整流水线是这样的:

Split:400MB 大文件 → 1000 个小分片(每片 1 万行)

Map:1000 个任务并行统计 → 1000 个中间文件(城市,数量)

Reduce:汇总 1000 份中间结果 → 1 个最终文件(每个城市的车流总量)

补充一个进阶知识点:Demo04 里"每个文件先在内部用字典归约一次"的做法,其实就是真实 MapReduce 中 Combiner 的雏形。Combiner 在 Map 端先做一次局部合并(比如把 <天津,1><天津,1> 先合并成 <天津,2>),大幅减少需要跨机器网络传输的数据量,是 MapReduce 最重要的性能优化手段之一。真实的 Shuffle 阶段还会把中间结果按 key 分区、排序,再通过网络送到对应的 Reducer 机器上------这是 MapReduce 中最复杂、也最容易成为性能瓶颈的一环。

六、真实的 Hadoop 长什么样

上面的 Python 模拟是为了理解思想。真实的 Hadoop 是一套完整的分布式计算框架,由三大核心组件构成:

HDFS(分布式文件系统):解决"数据怎么存"。大文件被切成块(默认 128MB),每个块存 3 份副本,分散在集群不同机器的磁盘上。NameNode 记录元数据(文件由哪些块组成、块在哪些机器上),DataNode 实际存放数据。数据天生就是"分散"的,这正是 Hadoop 能处理 PB 级数据的底气。

YARN(资源调度器):解决"任务怎么排"。Map/Reduce 任务运行前,先向 YARN 申请 CPU 和内存,YARN 在集群范围内统一调度分配,让上千个任务有条不紊地并行执行。

MapReduce(计算框架):解决"怎么算"。开发者只需用 Java 写 Mapper 和 Reducer 两个类,框架自动完成分片、调度、Shuffle、排序、容错(某个任务挂了自动换机器重跑)等所有脏活累活。

经典的 WordCount 程序就是本文 Demo 的"官方版本":Mapper 把每一行拆成单词,输出 <单词,1>;Reducer 把同一个单词的所有 1 相加,输出 <单词,总数>。与我们"按城市统计"的差别仅在于:真实的 key/value 会在集群机器之间通过网络流动,而我们用本地文件模拟了同样的数据流。

相关推荐
好好沉淀1 小时前
巧用 Set 去重与复合键:高效统计分组内不重复元素的数量
java·spring boot·后端
Wang's Blog1 小时前
Java框架快速入门: Spring Security+OAuth2之工程结构与开发环境配置
java·spring·状态模式
lzfshub1 小时前
Open-DIS Python发送DIS实体状态PDU:实现坦克炮塔与主炮部件参数
java·网络·python·dis
魏 无羡1 小时前
springboot 拦截器
java·spring boot·后端
步行cgn2 小时前
Spring Boot 绑定嵌套 Bean 详解
java·spring boot·后端
phltxy11 小时前
C语言操作符详解
java·c语言·算法
步行cgn12 小时前
@Configuration 详解:Spring 配置类的核心注解
java·后端·spring
sunshine22 girl12 小时前
Java学习一 环境配置2 安装和基本使用Idea
java·学习·intellij-idea
嘿嘿-6613 小时前
Windows 一键使用 GPT-6 Astra:Codex CLI 配置教程
java·人工智能·windows·gpt·chatgpt·web