从零实现一个分布式文件系统:GFS的核心设计
前言你有没有想过Google是怎么存储EB级别的数据的GFSGoogle File System是Google分布式存储的基石支撑了搜索、YouTube、Gmail等所有服务。今天我们用C语言从零实现GFS的核心设计· Master元数据管理· ChunkServer数据存储· 文件分块Chunk· 副本复制Replication· 心跳与健康检查· 读取与写入流程---一、GFS核心原理1. 架构图┌─────────────────────────────────────────────────────────────┐│ Client │└─────────────────────────────────────────────────────────────┘│ │▼ ▼┌─────────────────────────────────────────────────────────────┐│ Master ││ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││ │ 文件元数据 │ │ Chunk位置 │ │ 操作日志 │ ││ │ 命名空间 │ │ (缓存) │ │ (WAL) │ ││ └─────────────┘ └─────────────┘ └─────────────┘ │└─────────────────────────────────────────────────────────────┘│ │▼ ▼┌─────────────────────────────────────────────────────────────┐│ ChunkServer 集群 ││ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ││ │Chunk A │ │Chunk B │ │Chunk C │ │Chunk A │ ││ │(主副本) │ │(副本1) │ │(副本2) │ │(主副本) │ ││ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │└─────────────────────────────────────────────────────────────┘2. 核心概念概念 说明Master 单点管理元数据和Chunk位置Chunk 固定大小64MB的数据块ChunkServer 存储Chunk的节点副本 每个Chunk默认3个副本租约 主副本的写入权限3. 读写流程写入流程Client → Master获取主副本位置→ 主副本写入数据→ 二级副本同步数据→ Client确认读取流程Client → Master获取Chunk位置→ ChunkServer读取数据→ Client返回数据---二、完整代码实现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#include arpa/inet.h#define MAX_FILENAME 256#define MAX_CHUNK_ID 64#define MAX_CHUNK_SERVERS 10#define CHUNK_SIZE 64 * 1024 * 1024 // 64MB#define REPLICATION_FACTOR 3#define HEARTBEAT_INTERVAL 5// Chunk句柄typedef struct chunk_handle {char chunk_id[MAX_CHUNK_ID];char primary_server[32];char secondary_servers[REPLICATION_FACTOR][32];int version;int ref_count;} chunk_handle_t;// 文件元数据typedef struct file_metadata {char filename[MAX_FILENAME];chunk_handle_t *chunks;int chunk_count;time_t create_time;time_t modify_time;struct file_metadata *next;} file_metadata_t;// ChunkServertypedef struct chunk_server {char server_id[32];char host[32];int port;int disk_free;int status; // 0: offline, 1: online, 2: busytime_t last_heartbeat;struct chunk_server *next;} chunk_server_t;// Mastertypedef struct gfs_master {file_metadata_t *files;chunk_server_t *servers;char chunk_dir[256];pthread_mutex_t mutex;int running;pthread_t heartbeat_thread;} gfs_master_t;// ChunkServer节点typedef struct gfs_chunkserver {char server_id[32];char chunk_dir[256];int port;pthread_mutex_t mutex;int running;pthread_t heartbeat_thread;} gfs_chunkserver_t;2. Master实现c// 创建Mastergfs_master_t *master_create(const char *chunk_dir) {gfs_master_t *m malloc(sizeof(gfs_master_t));memset(m, 0, sizeof(gfs_master_t));strcpy(m-chunk_dir, chunk_dir);m-running 1;pthread_mutex_init(m-mutex, NULL);mkdir(chunk_dir, 0755);mkdir(./metadata, 0755);printf([Master] GFS Master启动Chunk目录: %s\n, chunk_dir);return m;}// 注册ChunkServerint master_register_server(gfs_master_t *m, const char *server_id,const char *host, int port) {pthread_mutex_lock(m-mutex);chunk_server_t *cs m-servers;while (cs) {if (strcmp(cs-server_id, server_id) 0) {cs-status 1;cs-last_heartbeat time(NULL);pthread_mutex_unlock(m-mutex);return 0;}cs cs-next;}cs malloc(sizeof(chunk_server_t));strcpy(cs-server_id, server_id);strcpy(cs-host, host);cs-port port;cs-status 1;cs-disk_free 1024 * 1024 * 1024; // 1GBcs-last_heartbeat time(NULL);cs-next m-servers;m-servers cs;pthread_mutex_unlock(m-mutex);printf([Master] 注册ChunkServer: %s (%s:%d)\n, server_id, host, port);return 0;}// 心跳更新void master_heartbeat(gfs_master_t *m, const char *server_id, int disk_free) {pthread_mutex_lock(m-mutex);chunk_server_t *cs m-servers;while (cs) {if (strcmp(cs-server_id, server_id) 0) {cs-last_heartbeat time(NULL);cs-disk_free disk_free;cs-status 1;break;}cs cs-next;}pthread_mutex_unlock(m-mutex);}// 创建文件int master_create_file(gfs_master_t *m, const char *filename) {pthread_mutex_lock(m-mutex);// 检查是否存在file_metadata_t *f m-files;while (f) {if (strcmp(f-filename, filename) 0) {pthread_mutex_unlock(m-mutex);return -1; // 已存在}f f-next;}// 创建新文件f malloc(sizeof(file_metadata_t));strcpy(f-filename, filename);f-chunks NULL;f-chunk_count 0;f-create_time time(NULL);f-modify_time time(NULL);f-next m-files;m-files f;pthread_mutex_unlock(m-mutex);printf([Master] 创建文件: %s\n, filename);return 0;}// 分配Chunkchunk_handle_t *master_allocate_chunk(gfs_master_t *m, const char *filename) {pthread_mutex_lock(m-mutex);// 查找文件file_metadata_t *f m-files;while (f) {if (strcmp(f-filename, filename) 0) break;f f-next;}if (!f) {pthread_mutex_unlock(m-mutex);return NULL;}// 创建Chunkchunk_handle_t *chunk malloc(sizeof(chunk_handle_t));snprintf(chunk-chunk_id, sizeof(chunk-chunk_id),chunk_%s_%d, filename, f-chunk_count);chunk-version 1;// 选择ChunkServer简化轮询chunk_server_t *cs m-servers;int idx 0;for (int i 0; i REPLICATION_FACTOR cs; i) {if (cs-status 1 cs-disk_free CHUNK_SIZE) {if (i 0) {strcpy(chunk-primary_server, cs-server_id);} else {strcpy(chunk-secondary_servers[i-1], cs-server_id);}// 模拟分配空间cs-disk_free - CHUNK_SIZE;cs cs-next;} else {// 找下一个可用服务器cs cs-next;i--;}if (!cs) {// 从头开始找cs m-servers;}}// 添加到文件chunk-next f-chunks;f-chunks chunk;f-chunk_count;pthread_mutex_unlock(m-mutex);printf([Master] 分配Chunk: %s (主: %s)\n,chunk-chunk_id, chunk-primary_server);return chunk;}3. ChunkServer实现c// 创建ChunkServergfs_chunkserver_t *chunkserver_create(const char *server_id,const char *chunk_dir, int port) {gfs_chunkserver_t *cs malloc(sizeof(gfs_chunkserver_t));strcpy(cs-server_id, server_id);strcpy(cs-chunk_dir, chunk_dir);cs-port port;cs-running 1;pthread_mutex_init(cs-mutex, NULL);mkdir(chunk_dir, 0755);printf([ChunkServer] %s启动端口: %d\n, server_id, port);return cs;}// 存储Chunkint chunkserver_store_chunk(gfs_chunkserver_t *cs, const char *chunk_id,const char *data, int data_len) {pthread_mutex_lock(cs-mutex);char filepath[512];snprintf(filepath, sizeof(filepath), %s/%s.dat, cs-chunk_dir, chunk_id);FILE *fp fopen(filepath, wb);if (!fp) {pthread_mutex_unlock(cs-mutex);return -1;}fwrite(data, 1, data_len, fp);fclose(fp);pthread_mutex_unlock(cs-mutex);return 0;}// 读取Chunkint chunkserver_read_chunk(gfs_chunkserver_t *cs, const char *chunk_id,char *data, int *data_len) {pthread_mutex_lock(cs-mutex);char filepath[512];snprintf(filepath, sizeof(filepath), %s/%s.dat, cs-chunk_dir, chunk_id);FILE *fp fopen(filepath, rb);if (!fp) {pthread_mutex_unlock(cs-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(cs-mutex);return 0;}// 心跳发送void *chunkserver_heartbeat_thread(void *arg) {gfs_chunkserver_t *cs (gfs_chunkserver_t*)arg;while (cs-running) {sleep(HEARTBEAT_INTERVAL);printf([ChunkServer] %s 心跳\n, cs-server_id);// 实际应通过网络发送心跳到Master}return NULL;}4. 客户端操作c// GFS客户端typedef struct gfs_client {char master_host[32];int master_port;char server_id[32];} gfs_client_t;// 创建客户端gfs_client_t *client_create(const char *master_host, int master_port) {gfs_client_t *c malloc(sizeof(gfs_client_t));strcpy(c-master_host, master_host);c-master_port master_port;snprintf(c-server_id, sizeof(c-server_id), client-%d, getpid());return c;}// 写入文件int client_write(gfs_client_t *c, const char *filename, const char *data) {printf([Client] 写入文件: %s, 大小: %zu\n, filename, strlen(data));// 1. 向Master获取主ChunkServer位置// 2. 向主ChunkServer写入数据// 3. 主ChunkServer同步到副本// 4. 返回确认// 模拟实现return 0;}// 读取文件int client_read(gfs_client_t *c, const char *filename, char *data) {printf([Client] 读取文件: %s\n, filename);// 1. 向Master获取Chunk位置// 2. 从最近的ChunkServer读取// 3. 组装返回strcpy(data, GFS file content);return 0;}5. 测试代码cvoid test_gfs() {printf( GFS分布式文件系统测试 \n\n);// 创建Mastergfs_master_t *master master_create(./chunks);// 创建ChunkServergfs_chunkserver_t *cs1 chunkserver_create(cs-1, ./cs1_data, 8001);gfs_chunkserver_t *cs2 chunkserver_create(cs-2, ./cs2_data, 8002);gfs_chunkserver_t *cs3 chunkserver_create(cs-3, ./cs3_data, 8003);// 注册到Mastermaster_register_server(master, cs-1, 127.0.0.1, 8001);master_register_server(master, cs-2, 127.0.0.1, 8002);master_register_server(master, cs-3, 127.0.0.1, 8003);// 创建文件master_create_file(master, /user/data.txt);// 分配Chunkchunk_handle_t *chunk master_allocate_chunk(master, /user/data.txt);if (chunk) {// 存储数据到ChunkServerchar test_data[] Hello GFS!;chunkserver_store_chunk(cs1, chunk-chunk_id, test_data, strlen(test_data));chunkserver_store_chunk(cs2, chunk-chunk_id, test_data, strlen(test_data));chunkserver_store_chunk(cs3, chunk-chunk_id, test_data, strlen(test_data));printf(\n✅ 数据已存储到3个副本\n);}// 读取数据char read_data[1024];int len;chunkserver_read_chunk(cs1, chunk-chunk_id, read_data, len);printf(从ChunkServer读取: %s\n, read_data);// 清理cs1-running 0;cs2-running 0;cs3-running 0;free(cs1); free(cs2); free(cs3);free(master);}int main() {test_gfs();return 0;}---三、编译和运行bashgcc -o gfs gfs.c -lpthread./gfs---四、GFS vs 其他分布式文件系统特性 GFS HDFS CephMaster 单点 单点 无中心Chunk大小 64MB 128MB 4MB副本数 3 3 可配置适用场景 大文件 大文件 通用一致性 弱一致性 强一致性 强一致性---五、总结通过这篇文章你学会了· GFS的核心架构Master ChunkServer· 文件分块和副本机制· 元数据管理· 心跳和健康检查· 读写流程GFS是分布式存储系统的开创者。掌握它你就理解了HDFS、Ceph等系统的设计基础。下一篇预告《从零实现一个分布式缓存Redis Cluster的核心设计》---评论区分享一下你对分布式文件系统的理解

相关新闻

AI发展趋势-2

AI发展趋势-2

接上篇二、AI形态跃迁:从被动对话框→主动AI智能体Agent(未来3年最大风口)这是AI最本质的质变:传统AI是“你提问、它应答”的被动工具;Agent智能体是有目标、会拆解任务、自动调用软件/网页/API、自主执行、复盘迭代、…

2026/7/2 6:33:58阅读更多 →
谈谈长连接(Keep-Alive)在超大规模爬虫抓取中的性能差距

谈谈长连接(Keep-Alive)在超大规模爬虫抓取中的性能差距

大家好,欢迎回到我的技术专栏。在日均抓取量突破千万级别的爬虫场景里,连接管理是决定单机 QPS 和机器成本的关键因素。很多团队在初期用短连接跑得很顺,但当规模膨胀到某个临界点后,往往会发现加机器也拉不动了——此时的性能瓶颈…

2026/7/2 6:33:58阅读更多 →
终极Notepad++实时Markdown预览插件:5分钟实现高效文档创作

终极Notepad++实时Markdown预览插件:5分钟实现高效文档创作

终极Notepad实时Markdown预览插件:5分钟实现高效文档创作 【免费下载链接】MarkdownViewerPlusPlus A Notepad Plugin to view a Markdown file rendered on-the-fly 项目地址: https://gitcode.com/gh_mirrors/ma/MarkdownViewerPlusPlus 你是否厌倦了在Not…

2026/7/2 6:33:58阅读更多 →
ESP-SR语音识别框架:嵌入式开发者的终极入门指南

ESP-SR语音识别框架:嵌入式开发者的终极入门指南

ESP-SR语音识别框架:嵌入式开发者的终极入门指南 【免费下载链接】esp-sr Speech recognition 项目地址: https://gitcode.com/gh_mirrors/es/esp-sr 你是否正在为智能设备寻找一个高效、低功耗的语音交互解决方案?ESP-SR语音识别框架正是你需要的…

2026/7/2 7:54:04阅读更多 →
紧急上线前Git冲突爆发!,资深架构师压箱底的3层防御机制:Pre-Merge Check + Diff Preview + Atomic Rollback

紧急上线前Git冲突爆发!,资深架构师压箱底的3层防御机制:Pre-Merge Check + Diff Preview + Atomic Rollback

更多请点击: https://codechina.net 第一章:紧急上线前Git冲突爆发!资深架构师压箱底的3层防御机制全景图 当凌晨两点收到CI流水线中断告警,主干分支合并失败,数十个未解决的merge conflict赫然在目——这不是演习&am…

2026/7/2 7:54:04阅读更多 →
教育资源的智能革命:tchMaterial-parser开启电子课本下载新纪元

教育资源的智能革命:tchMaterial-parser开启电子课本下载新纪元

教育资源的智能革命:tchMaterial-parser开启电子课本下载新纪元 【免费下载链接】tchMaterial-parser 国家中小学智慧教育平台 电子课本下载工具,帮助您从智慧教育平台中获取电子课本的 PDF 文件网址并进行下载,让您更方便地获取课本内容。 …

2026/7/2 7:54:04阅读更多 →
LangChain Models 篇章学习笔记 — 从模型到 Agent 的认知闭环

LangChain Models 篇章学习笔记 — 从模型到 Agent 的认知闭环

LangChain Models 篇章学习笔记 — 从模型到 Agent 的认知闭环本文基于 LangChain 官方文档 Models 章节学习整理,梳理大语言模型的核心能力、标准化接口与 Agent 协作模式,适合 AI Agent 开发入门者建立系统性认知。一、开篇:大语言模型是什…

2026/7/2 7:54:04阅读更多 →
查看文件/grep etc/passwd字段含义/cut

查看文件/grep etc/passwd字段含义/cut

1.cat格式:cat 【参数】 文件名参数;-n 显示行号-b 所有非空行显示行号,1开始tac命令用于倒序输出2.more/lessmore/less用于查看内容较多的纯文本文件,可以使用空格键或回车键向下翻页,q退出,而cat命令查看长文本文件时…

2026/7/2 7:54:04阅读更多 →
Corrective RAG与Real-Time PPO协同实践:构建可纠错、能权衡的企业级RAG系统

Corrective RAG与Real-Time PPO协同实践:构建可纠错、能权衡的企业级RAG系统

1. 这不是又一篇“RAG综述”,而是一份实操者手记:当检索不再只是“找文档”,大模型开始真正学会“纠错”与“权衡”你有没有遇到过这样的场景:用RAG系统查技术文档,结果返回的段落里混着一个早已废弃的API参数&#xf…

2026/7/2 7:49:04阅读更多 →
AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

6个月前的2025年12月,Boris Cherny 公开宣布自己卸载了 IDE。一时间,Vibe Coding 成了全行业最热的话题。6个月后,当我们回过头来拉一份真实账本,发现事情远没有"一句话生成一个App"那么浪漫。本文从产品经理和研发两个…

2026/7/1 4:42:14阅读更多 →
审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

引言:审计结束三个月了,审计员的权限还没关某城商行每年按照监管要求开展至少一次数据安全审计。审计期间,内审部门需要抽样检查各类业务数据——交易流水、客户信息、员工操作日志、权限配置记录。这些数据分布在不同系统中,审计…

2026/7/1 5:19:01阅读更多 →
塞尔达传说旷野之息存档修改器:3分钟掌握海拉鲁世界自由定制技巧

塞尔达传说旷野之息存档修改器:3分钟掌握海拉鲁世界自由定制技巧

塞尔达传说旷野之息存档修改器:3分钟掌握海拉鲁世界自由定制技巧 【免费下载链接】BOTW-Save-Editor-GUI A Work in Progress Save Editor for BOTW 项目地址: https://gitcode.com/gh_mirrors/bo/BOTW-Save-Editor-GUI 想在《塞尔达传说:旷野之息…

2026/7/2 0:03:01阅读更多 →
告别 AccessKey:多云平台 CLI OAuth 免密认证完全指南

告别 AccessKey:多云平台 CLI OAuth 免密认证完全指南

在本地开发环境使用云厂商 CLI 时,传统的 AccessKey(AK)方式需要手动创建、下载和保管密钥,不仅繁琐,还存在泄漏风险。其实,主流云平台都已提供基于 OAuth 2.0 的免密认证方案,让开发者可以通过浏览器登录一次性完成授权,CLI 自动管理临时凭证的刷新,兼顾了便利与安全…

2026/7/2 0:03:01阅读更多 →
基于13DOF传感器与PIC32MZ的高精度嵌入式导航系统设计

基于13DOF传感器与PIC32MZ的高精度嵌入式导航系统设计

1. 项目背景与核心价值在嵌入式系统开发领域,高精度定位与导航一直是极具挑战性的技术方向。传统方案往往面临成本、精度和实时性难以兼顾的困境。这个项目通过13DOF(13自由度)传感器组合与PIC32MZ2048EFH100高性能MCU的协同工作,…

2026/7/2 0:03:01阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/2 0:33:58阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/2 1:32:11阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/2 1:50:13阅读更多 →