Hadoop-python中使用大数据

一、写在前面:为什么先从 Python 学 Hadoop

最近开始系统学习大数据,第一站就是 Hadoop。很多教程一上来就抛出一堆概念:HDFS、NameNode、DataNode、YARN......听得云里雾里,很容易劝退。其实 Hadoop 的核心计算思想 MapReduce 并不神秘,它的精髓用一段 Python 代码就能模拟出来。这篇学习笔记记录了我是如何用 Python 从"单机统计"一路走到"分而治之",逐步理解 MapReduce 思想的完整过程。

二、Hadoop 是什么:一头"玩具大象"的由来

Hadoop 这个名字很有意思------它是创始人 Doug Cutting 以儿子的一头黄色玩具大象命名的,那只小象后来成了大数据的吉祥物。Hadoop 的诞生源于 Google 在 2003~2004 年发表的三篇经典论文:GFS(Google 文件系统)、MapReduce(分布式计算模型)和 BigTable(分布式数据库)。Apache 社区照着论文的思路,用开源方式复刻出了 HDFS 和 MapReduce,这就是 Hadoop 的核心。理解了这层渊源再回看今天各种云存储和分布式计算系统,很多设计都能追溯到这三篇论文。

三、需求场景:统计每个城市的车流量

设想一个智慧交通场景:城市道路上布满了交通卡口(电子警察摄像头),每辆车经过卡口时都会产生一条"过车记录",字段依次为:车牌号、卡口编号、卡口所在城市、车辆品牌、道路编号、车辆速度、行驶方向。一条真实记录的格式如下:

京K82539,G5221,天津,丰田,R469,25,上行

一天下来,全市所有卡口的过车记录可能达到上千万条甚至上亿条。现在业务部门提出一个需求:统计每个城市分别有多少辆车经过。本质上这是一个"按城市分组计数"(Group By + Count)的问题,也是大数据世界里最经典的统计场景。

四、数据准备:用 Python 造出 1000 万条模拟数据

学习阶段没有现成的海量数据,没关系------自己造。gen_data.py 脚本模拟生成了 1000 万条卡口过车记录,保存到 gateway_records2.txt 中,文件大小 400 多 MB。生成逻辑很简单,每个字段都用 random 模块随机产生:

车牌号:省份简称"京" + 随机大写字母 + 5位数字

def generate_plate_number():

provinces = "京"

letters = string.ascii_uppercase

numbers = ''.join(random.choices(string.digits, k=5))

return random.choice(provinces) + random.choice(letters) + numbers

卡口所在城市:从10个城市中随机选一个

cities = ["北京", "上海", "广州", "深圳", "杭州",

"成都", "武汉", "南京", "重庆", "天津"]

一条完整记录 = 7个字段用逗号拼接

return f"{plate_number},{gateway_id},{city},{car_brand}," \

f"{road_id},{speed},{travel_direction}"

其他字段同理:卡口编号是"G"+4 位数字,车辆品牌从丰田、大众、宝马、特斯拉等 10 个品牌中随机选择,道路编号是"R"+3 位数字,速度在 20~120 km/h 之间随机,行驶方向只有"上行""下行"两种。最终调用 generate_and_save_records 函数循环写入 1000 万行即可。这个 400 多 MB 的文本文件,就是接下来要处理的"大数据"。

五、小数据热身:统计每个班级的人数

处理大数据之前,先用小数据把套路练熟。Demo01 的需求是:读取学生数据,统计每个班级的人数。假设 student.txt 中每行是"姓名,性别,班级",核心代码如下:

读取所有学生数据

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

方式三:用 map 函数抽取每行的班级字段

clazzs = list(map(lambda line: line.split(",")-1, students))

定义空字典:班级 -> 人数

clazz_num = {}

遍历班级列表,做分组累加统计

for clazz in clazzs:

if clazz not in clazz_num:

clazz_numclazz = 1 # 第一次出现,初始化为1

else:

clazz_numclazz += 1 # 已存在,人数+1

这段代码揭示了一个非常重要的统计套路------"键值对(Key-Value)分组累加":以分组字段(班级)为 key,以累加结果为 value,用字典完成计数。先判断 key 是否已存在:不存在就初始化为 1,存在就加 1。这个套路正是 MapReduce 中所有统计类需求的灵魂,后面会反复出现。

六、直面大数据:单机统计暴露出什么问题

把同样的套路搬到大数据上,Demo02 的需求是统计每个城市的车流量,代码几乎原样照搬:

读取 400M+ 的网关记录文件

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

抽取每行第3个字段(城市)

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

分组累加统计

city_num = {}

for city in citys:

if city not in city_num:

city_numcity = 1

else:

city_numcity += 1

逻辑完全正确,但真正跑起来,单机处理的三大问题就暴露了:

① 内存爆炸:f.readlines() 一次性把 400 多 MB 数据全部读进内存,生成 1000 万元素的列表,还要再生成一个 1000 万元素的 citys 列表,内存占用轻松超过 1GB,机器配置稍差就会内存溢出(OOM)。

② 速度太慢:整个统计过程只用了一个 CPU 核心串行执行,1000 万条数据要处理相当长的时间,其他 CPU 核心全程围观。

③ 无法扩展:数据规模再上一个量级(比如几十亿条、几个 TB),单机就彻底无能为力------磁盘装不下、内存不够用、时间等不起。

打个比方:让一个人数完整个城市的车,不如派 1000 个人去 1000 个路口分别数,最后把 1000 份结果汇总------这就是"分而治之"(Divide and Conquer)。

七、出路:分而治之,MapReduce 的雏形

面对单机处理不了的大文件,Hadoop 给出的答案正是分而治之,拆成三步走:

第一步"分"(Split):把大文件切成许多小文件;

第二步"算"(Map):把每个小文件分给不同的机器并行统计,得到一批局部结果;

第三步"合"(Reduce):把所有局部结果汇总成最终结果。

这就是 MapReduce 的基本骨架。下一篇文章,我们将用 Python 亲手把 Split → Map → Reduce 三个阶段实现一遍,完整模拟"1000 个人数车、最后汇总"的全过程。

八、本篇小结

  1. 大数据处理的本质是"按 Key 分组统计",字典(K-V)分组累加是所有统计类需求的通用套路;

  2. 单机处理大文件有三大痛点:内存溢出、单核串行、无法横向扩展;

  3. 大数据方案的思路是分而治之:分片 → 并行处理 → 汇总,这正是 MapReduce 三阶段(Split / Map / Reduce)的雏形。

带着这三个结论进入下篇,我们动手把"迷你 MapReduce"完整实现一遍。

相关推荐
小刘在重生~1 小时前
Django|Excel 批量上传、Form/ModelForm 文件上传、Media 媒体文件配置
python·django·excel
QYR-分析1 小时前
超分辨显微镜行业市场现状、竞争格局及发展前景分析
大数据·人工智能
优德普ERP数字化1 小时前
AI+QMS+MES落地化工设备制造追溯:对象、事件、接口和审核怎么组织
大数据·qms·mes·优德普·针孔检测·化工设备质量追溯·搪玻璃反应釜
威联通安全存储1 小时前
TS-h1887XU-RP 在模具制造行业试模与改模数据场景的部署
python·制造
小白羊丨1 小时前
为什么微调而不是大模型 + Prompt?正确率如何得到,是否过拟合?
大数据·人工智能·prompt
步行cgn1 小时前
Spring Environment 详解:Spring Boot 配置管理的核心接口
spring boot·python·spring
Csvn1 小时前
🐍 Day 12: 编码与字符集 — 告别乱码噩梦
后端·python
2601_962283881 小时前
Python 开发框架:Django、Flask和FastAPI
python·django·flask·fastapi·web开发
lzfshub1 小时前
Open-DIS Python发送DIS实体状态PDU:实现坦克炮塔与主炮部件参数
java·网络·python·dis