从零实现一个分布式文件系统:HDFS的核心设计
前言在分布式存储中HDFSHadoop Distributed File System是处理海量数据的基石设计用于大文件的存储和处理。今天我们从零实现HDFS的核心功能· 元数据管理NameNode· 数据存储DataNode· 文件分块Block· 副本管理Replication· 心跳机制Heartbeat· 数据块复制与均衡· 文件读写流程---一、HDFS核心原理1. 架构图┌─────────────────────────────────────────────────────────────┐│ Client │└─────────────────────────────────────────────────────────────┘│ │▼ ▼┌─────────────────────────────────────────────────────────────┐│ NameNode ││ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││ │ 文件元数据 │ │ 块位置 │ │ 操作日志 │ ││ │ 命名空间 │ │ (缓存) │ │ (WAL) │ ││ └─────────────┘ └─────────────┘ └─────────────┘ │└─────────────────────────────────────────────────────────────┘│ │▼ ▼┌─────────────────────────────────────────────────────────────┐│ DataNode集群 ││ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││ │ DataNode1 │ │ DataNode2 │ │ DataNode3 │ ││ │ Block A │ │ Block A │ │ Block B │ ││ │ Block B │ │ Block C │ │ Block C │ ││ └─────────────┘ └─────────────┘ └─────────────┘ │└─────────────────────────────────────────────────────────────┘2. 核心概念概念 说明NameNode 元数据管理节点单点DataNode 数据存储节点Block 数据块默认128MBReplication 副本数默认3Heartbeat 心跳DataNode→NameNode---二、完整代码实现1. 基础数据结构c#include stdio.h#include stdlib.h#include string.h#include unistd.h#include pthread.h#include time.h#include errno.h#include sys/stat.h#include fcntl.h#include dirent.h#define MAX_FILENAME 256#define MAX_BLOCK_ID 64#define MAX_DATANODES 10#define BLOCK_SIZE (64 * 1024 * 1024) // 64MB#define REPLICATION_FACTOR 3// 数据块typedef struct block {char block_id[MAX_BLOCK_ID];long long size;long long offset;struct block *next;} block_t;// 文件元数据typedef struct hdfs_file {char filename[MAX_FILENAME];block_t *blocks;int block_count;long long file_size;time_t create_time;time_t modify_time;struct hdfs_file *next;} hdfs_file_t;// DataNode信息typedef struct datanode {char node_id[64];char host[32];int port;long long disk_free;long long disk_total;int status; // 0: offline, 1: online, 2: busytime_t last_heartbeat;char blocks[1024][64]; // 存储的块ID列表int block_count;struct datanode *next;} datanode_t;// NameNodetypedef struct hdfs_namenode {hdfs_file_t *files;datanode_t *datanodes;char block_dir[256];int block_id_counter;pthread_mutex_t mutex;int running;int port;pthread_t heartbeat_thread;} hdfs_namenode_t;// DataNodetypedef struct hdfs_datanode {char node_id[64];char data_dir[256];int port;pthread_mutex_t mutex;int running;int port_listen;pthread_t heartbeat_thread;char *blocks;} hdfs_datanode_t;// HDFS客户端typedef struct hdfs_client {char namenode_host[32];int namenode_port;} hdfs_client_t;2. NameNode实现c// 创建NameNodehdfs_namenode_t *namenode_create(int port) {hdfs_namenode_t *nn malloc(sizeof(hdfs_namenode_t));memset(nn, 0, sizeof(hdfs_namenode_t));nn-port port;nn-running 1;nn-block_id_counter 0;pthread_mutex_init(nn-mutex, NULL);mkdir(./blocks, 0755);printf([NameNode] 启动端口: %d\n, port);return nn;}// 注册DataNodeint namenode_register_datanode(hdfs_namenode_t *nn, const char *node_id,const char *host, int port, long long disk_free) {pthread_mutex_lock(nn-mutex);datanode_t *dn nn-datanodes;while (dn) {if (strcmp(dn-node_id, node_id) 0) {dn-status 1;dn-last_heartbeat time(NULL);dn-disk_free disk_free;pthread_mutex_unlock(nn-mutex);return 0;}dn dn-next;}dn malloc(sizeof(datanode_t));strcpy(dn-node_id, node_id);strcpy(dn-host, host);dn-port port;dn-disk_free disk_free;dn-disk_total disk_free;dn-status 1;dn-last_heartbeat time(NULL);dn-block_count 0;dn-next nn-datanodes;nn-datanodes dn;pthread_mutex_unlock(nn-mutex);printf([NameNode] DataNode注册: %s (%s:%d)\n, node_id, host, port);return 0;}// 心跳更新void namenode_heartbeat(hdfs_namenode_t *nn, const char *node_id,long long disk_free, char **blocks, int block_count) {pthread_mutex_lock(nn-mutex);datanode_t *dn nn-datanodes;while (dn) {if (strcmp(dn-node_id, node_id) 0) {dn-last_heartbeat time(NULL);dn-disk_free disk_free;dn-block_count block_count;for (int i 0; i block_count i 1024; i) {strcpy(dn-blocks[i], blocks[i]);}break;}dn dn-next;}pthread_mutex_unlock(nn-mutex);}// 选择DataNode存储块按磁盘空间datanode_t *namenode_select_datanode(hdfs_namenode_t *nn) {pthread_mutex_lock(nn-mutex);datanode_t *selected NULL;long long max_free -1;datanode_t *dn nn-datanodes;while (dn) {if (dn-status 1 dn-disk_free max_free) {max_free dn-disk_free;selected dn;}dn dn-next;}pthread_mutex_unlock(nn-mutex);return selected;}// 分配块IDchar *namenode_allocate_block(hdfs_namenode_t *nn) {pthread_mutex_lock(nn-mutex);nn-block_id_counter;char *block_id malloc(64);snprintf(block_id, 64, blk_%d_%ld, nn-block_id_counter, time(NULL));pthread_mutex_unlock(nn-mutex);return block_id;}3. DataNode实现c// 创建DataNodehdfs_datanode_t *datanode_create(const char *node_id, const char *data_dir, int port) {hdfs_datanode_t *dn malloc(sizeof(hdfs_datanode_t));strcpy(dn-node_id, node_id);strcpy(dn-data_dir, data_dir);dn-port port;dn-port_listen port;dn-running 1;pthread_mutex_init(dn-mutex, NULL);mkdir(data_dir, 0755);printf([DataNode] %s 启动数据目录: %s\n, node_id, data_dir);return dn;}// 存储块int datanode_store_block(hdfs_datanode_t *dn, const char *block_id,const char *data, int data_len) {pthread_mutex_lock(dn-mutex);char filepath[512];snprintf(filepath, sizeof(filepath), %s/%s.dat, dn-data_dir, block_id);FILE *fp fopen(filepath, wb);if (!fp) {pthread_mutex_unlock(dn-mutex);return -1;}fwrite(data, 1, data_len, fp);fclose(fp);pthread_mutex_unlock(dn-mutex);return 0;}// 读取块int datanode_read_block(hdfs_datanode_t *dn, const char *block_id,char *data, int *data_len) {pthread_mutex_lock(dn-mutex);char filepath[512];snprintf(filepath, sizeof(filepath), %s/%s.dat, dn-data_dir, block_id);FILE *fp fopen(filepath, rb);if (!fp) {pthread_mutex_unlock(dn-mutex);return -1;}fseek(fp, 0, SEEK_END);*data_len ftell(fp);fseek(fp, 0, SEEK_SET);fread(data, 1, *data_len, fp);fclose(fp);pthread_mutex_unlock(dn-mutex);return 0;}4. 文件操作c// 创建文件int namenode_create_file(hdfs_namenode_t *nn, const char *filename) {pthread_mutex_lock(nn-mutex);hdfs_file_t *f nn-files;while (f) {if (strcmp(f-filename, filename) 0) {pthread_mutex_unlock(nn-mutex);return -1;}f f-next;}f malloc(sizeof(hdfs_file_t));strcpy(f-filename, filename);f-blocks NULL;f-block_count 0;f-file_size 0;f-create_time time(NULL);f-modify_time time(NULL);f-next nn-files;nn-files f;pthread_mutex_unlock(nn-mutex);printf([NameNode] 创建文件: %s\n, filename);return 0;}// 写入文件分块int hdfs_write(hdfs_namenode_t *nn, const char *filename, const char *data, int data_len) {// 创建文件if (namenode_create_file(nn, filename) 0) {printf(文件已存在: %s\n, filename);return -1;}// 分块写入int offset 0;int block_num 0;int remaining data_len;while (remaining 0) {int chunk_size remaining BLOCK_SIZE ? BLOCK_SIZE : remaining;// 分配块IDchar *block_id namenode_allocate_block(nn);// 选择DataNodedatanode_t *dn namenode_select_datanode(nn);if (!dn) {printf(没有可用的DataNode\n);return -1;}// 写入数据到DataNode模拟// 实际通过RPC传输printf([写入] 块 %s 写入到 %s (大小: %d)\n, block_id, dn-node_id, chunk_size);// 更新元数据pthread_mutex_lock(nn-mutex);hdfs_file_t *f nn-files;while (f) {if (strcmp(f-filename, filename) 0) {block_t *b malloc(sizeof(block_t));strcpy(b-block_id, block_id);b-size chunk_size;b-offset offset;b-next f-blocks;f-blocks b;f-block_count;f-file_size chunk_size;break;}f f-next;}pthread_mutex_unlock(nn-mutex);offset chunk_size;remaining - chunk_size;block_num;free(block_id);}printf([HDFS] 文件 %s 写入完成共 %d 个块\n, filename, block_num);return 0;}// 读取文件int hdfs_read(hdfs_namenode_t *nn, const char *filename, char *data, int *data_len) {pthread_mutex_lock(nn-mutex);hdfs_file_t *f nn-files;while (f) {if (strcmp(f-filename, filename) 0) break;f f-next;}if (!f) {pthread_mutex_unlock(nn-mutex);return -1;}// 读取所有块block_t *b f-blocks;int total_len 0;while (b) {// 查找块所在的DataNode模拟printf([读取] 读取块: %s (大小: %lld)\n, b-block_id, b-size);// 实际需要从DataNode读取数据total_len b-size;b b-next;}*data_len total_len;pthread_mutex_unlock(nn-mutex);return 0;}5. 测试代码cvoid test_hdfs() {printf( HDFS分布式文件系统测试 \n\n);// 创建NameNodehdfs_namenode_t *nn namenode_create(9000);// 创建DataNodehdfs_datanode_t *dn1 datanode_create(dn-1, ./dn1_data, 9001);hdfs_datanode_t *dn2 datanode_create(dn-2, ./dn2_data, 9002);hdfs_datanode_t *dn3 datanode_create(dn-3, ./dn3_data, 9003);// 注册DataNodenamenode_register_datanode(nn, dn-1, 127.0.0.1, 9001, 1024*1024*1024);namenode_register_datanode(nn, dn-2, 127.0.0.1, 9002, 1024*1024*1024);namenode_register_datanode(nn, dn-3, 127.0.0.1, 9003, 1024*1024*1024);// 写入文件char test_data[1024 * 1024]; // 1MB数据for (int i 0; i 1024*1024; i) {test_data[i] A (i % 26);}printf(写入文件 /user/test.txt (1MB)...\n);hdfs_write(nn, /user/test.txt, test_data, 1024*1024);// 读取文件printf(\n读取文件 /user/test.txt...\n);char read_data[1024*1024];int read_len;hdfs_read(nn, /user/test.txt, read_data, read_len);printf(读取到 %d 字节\n, read_len);// 文件列表printf(\n文件列表:\n);hdfs_file_t *f nn-files;while (f) {printf( %s (大小: %lld, 块数: %d)\n,f-filename, f-file_size, f-block_count);f f-next;}printf(\nDataNode状态:\n);datanode_t *dn nn-datanodes;while (dn) {printf( %s: 状态%d, 块数%d\n,dn-node_id, dn-status, dn-block_count);dn dn-next;}free(nn);free(dn1);free(dn2);free(dn3);}int main() {test_hdfs();return 0;}---三、编译和运行bashgcc -o hdfs hdfs.c -lpthread./hdfs---四、HDFS vs 本实现特性 本实现 HDFSNameNode ✅ ✅DataNode ✅ ✅块存储 ✅ 64MB ✅ 128MB副本管理 ❌ ✅ 默认3心跳机制 ✅ ✅块均衡 ❌ ✅高可用 ❌ ✅ (HA)纠删码 ❌ ✅---五、总结通过这篇文章你学会了· HDFS的核心架构NameNode DataNode· 文件分块与元数据管理· DataNode注册与心跳· 文件写入流程分块存储· 文件读取流程块聚合HDFS是分布式存储的经典实现。掌握它你就理解了海量数据存储系统的核心设计。下一篇预告《从零实现一个分布式计算MapReduce的核心设计》---评论区分享一下你对HDFS的理解

相关新闻

IT采购必备指南:有实力的知识库系统五大核心评判维度

IT采购必备指南:有实力的知识库系统五大核心评判维度

知识库系统实力评判的核心逻辑企业数智化转型进程中,知识库作为承载内部知识资产的核心载体,选型结果直接影响组织协作效率与数据安全。当前多数企业在知识库选型阶段缺乏统一评判标准,常陷入参数模糊、资质掺水、案例空泛的决策陷阱&#xf…

2026/7/31 4:40:21 阅读更多 →
LVS负载调度

LVS负载调度

一、LVS全称 Linux Virtual Server,四种模式,十三种算法二、什么是集群集群(Cluster)是指将多台独立的计算机(服务器)通过网络连接在一起,协同工作,对外表现为一个统一的系统。同一个…

2026/7/31 4:39:21 阅读更多 →
OpenClaw客户端分发教程,Windows 与 Mac 安装包获取

OpenClaw客户端分发教程,Windows 与 Mac 安装包获取

🦞教程适配:OpenClaw v2.7.9 | 适配 Windows10/11、macOS 双系统 核心亮点:提供全程可视化图形操作界面,自动补齐全套运行依赖,数据独立存储于本地设备,兼容多款主流大模型,并采用轻量化的 45.7…

2026/7/31 4:39:21 阅读更多 →

最新新闻

AI内容检测与优化工具全评测:降AI率实战指南

AI内容检测与优化工具全评测:降AI率实战指南

1. 为什么我们需要关注AI率?在内容创作领域,AI率已经成为衡量内容原创性和人工参与度的重要指标。简单来说,AI率指的是文本中被检测出由人工智能生成的概率百分比。随着AI写作工具的普及,各大平台和学术机构都开始重视这一指标。高…

2026/7/31 5:18:41 阅读更多 →
Rust服务器数据监控系统:从日志采集到实时统计的架构与实现

Rust服务器数据监控系统:从日志采集到实时统计的架构与实现

1. 项目缘起:为什么Rust服务器需要玩家追踪与数据统计?如果你运营过一个Rust服务器,无论是作为社区服主还是大型服务器集群的管理员,你肯定经历过这样的场景:凌晨三点,服务器突然卡顿,聊天频道里…

2026/7/31 5:18:41 阅读更多 →
三菱FX3U PLC与GX Works2从零实战:硬件连接、软件配置与梯形图编程全解析

三菱FX3U PLC与GX Works2从零实战:硬件连接、软件配置与梯形图编程全解析

1. 项目概述:从零上手三菱FX3U与GX Works2 如果你刚拿到一台三菱FX3U-32M PLC和一套GX Works2软件,面对一堆线缆和复杂的软件界面感到无从下手,那么这篇分享就是为你准备的。我接触过不少从西门子、欧姆龙转过来的工程师,或者刚入…

2026/7/31 5:18:41 阅读更多 →
小米平板1刷机实战:解析TWRP Error 7与Error 255的成因与解决方案

小米平板1刷机实战:解析TWRP Error 7与Error 255的成因与解决方案

1. 项目概述与问题引入如果你是一位热衷于折腾老旧设备、尤其是小米平板1这类“上古神器”的玩家,那么刷机过程中遇到的各种报错代码,绝对是家常便饭。今天要聊的这两个错误——在刷入ROM时出现的E1001 Error: 7,以及在TWRP恢复备份时跳出的E…

2026/7/31 5:18:41 阅读更多 →
第一篇:容器化技术介绍

第一篇:容器化技术介绍

本文是个人学习使用容器技术的整理笔记(V1.0),内容来源于公开资料与实践总结,部分技术仅作概念了解,后续会持续更新和勘误。一、容器技术行业简介容器技术通过将应用及其依赖打包成可移植的容器,实现跨环境…

2026/7/31 5:18:40 阅读更多 →
Product Hunt 每日热榜 | 2026-07-30

Product Hunt 每日热榜 | 2026-07-30

1. Prelint 标语:防止AI生成代码中的产品偏差 介绍:AI以10倍的速度为你编写代码,而Prelint则确保这些代码是正确的。它会在每个合并请求(PR)之前,针对你的架构决策(ADR)、文档和过…

2026/7/31 5:17:40 阅读更多 →

日新闻

物理复制比逻辑复制好在哪?数据库复制原理详解

物理复制比逻辑复制好在哪?数据库复制原理详解

数据库复制是把主库数据同步到备库的机制,分为逻辑复制和物理复制两种。逻辑复制传输的是 SQL 语句或行变更事件,物理复制传输的是存储引擎底层的物理日志。阿里云 PolarDB(云原生数据库)采用物理复制,在同步延迟、数据…

2026/7/31 0:00:34 阅读更多 →
BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirrors/bi/Bilib…

2026/7/31 0:00:34 阅读更多 →
有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

当前,游戏行业的“DataAI融合”已从概念验证进入价值落地阶段。根据IDC 2025年数据,中国AI游戏云市场规模已达18.6亿元;同时,游戏研发环节AI渗透率高达86%,生成式AI内容普及率超过50%。面对庞大的市场,游戏…

2026/7/31 0:00:34 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/31 1:03:03 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/29 14:34:28 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/31 4:19:39 阅读更多 →

月新闻