深入 Hadoop 03 - 文件读取路径与副本选择
上一篇讲了写入路径——客户端通过 Pipeline 把字节推到三个 DataNode。本篇讲读取路径。 HDFS 读文件常被描述成"客户端从 HDFS 把数据读出来"。这个描述和写路径一样把机制掩盖了。准确的说法是:客户端先问 NameNode 拿 block 列表 + 每个 block 的副本所在 DataNode 列表(按距离排序),然后按距离顺序直连 DataNode 拉取数据,读完后切到下一个 block。任何 DataNode 慢或失败时,客户端透明切换到该 block 的下一个副本。 本篇只抓一个问题:客户端怎么挑副本、本地短路与零拷贝怎么工作、Hedged Read 在什么场景下值得打开。 读取路径的五个步骤 一次完整的 HDFS 读展开成五步: 12345671. open(/path) 客户端调用 NameNode 打开文件2. NameNode 返回:[blk-1 副本列表, blk-2 副本列表, ...] 每个 block 的副本按距离客户端由近到远排序3. 客户端按 block 顺序处理: 3a. 取 blk-N 的副本列表第一个...
深入 Hadoop 02 - 文件写入路径与流水线
上一篇把 HDFS 切成 NameNode、DataNode、Client 三层职责。本篇展开 Client 写文件时的具体路径。 HDFS 写文件常被描述成"客户端把数据写到 HDFS"。这个描述把数据传输机制掩盖了。准确的说法是:客户端通过一个由 NameNode 提前挑选的 DataNode 链(Pipeline)以流水线方式逐包写入数据,每个包从链头流到链尾再返回 ACK,写完一个 block 后客户端向 NameNode 申请新 block。这种 Pipeline + ACK 队列的设计是 HDFS 写入路径的核心抽象,决定了 HDFS 写入吞吐、副本一致性和写入失败恢复的全部行为。 本篇只抓一个问题:客户端写到 HDFS 的字节是怎么一步步落到三个 DataNode 磁盘上的,以及为什么 HDFS 选择 Pipeline 而不是客户端并行写三份。 写入路径的六个步骤 把一次完整的 HDFS 写入展开,可以拆成六个步骤: 1234561. create() 客户端调用 NameNode 创建文件元数据2. addBlock() 客户端向 NameNo...
深入 Hadoop 01 - HDFS 架构与三层切分
上一篇把 Hadoop 整体压成一句话:以"节点总会失败"为前提,HDFS 切大文件、YARN 切资源、MapReduce 切计算。本篇进入 HDFS。 HDFS 常被介绍为"分布式文件系统"。这个说法没错但不够准确。准确的说法是:HDFS 是一个把元数据、数据块、节点监控切成三层独立职责的分布式文件系统。三层职责分离是 HDFS 设计的核心抽象,决定了 HDFS 的所有后续行为——为什么元数据全内存、为什么写文件要 Pipeline、为什么读文件可以就近选副本、为什么 NameNode 是单点。 本篇只抓一个问题:NameNode、DataNode、客户端这三层职责是怎么切开的,以及这种切法为什么会让 HDFS 长成现在的样子。 三层职责切分 HDFS 的架构可以用一张三层图概括: 1234567891011121314151617181920212223┌─────────────────────────────────────────────────────────────────┐│ NameNod...
深入 Hadoop 00 - 导读:节点总会失败
Hadoop 常被介绍为"HDFS + YARN + MapReduce 三驾马车"。这个分类把重点放错了位置。把存储、调度、计算切成三件独立的事情,读者很难回答下面这个问题:为什么这三个子系统会一起出现在同一个项目里,而不是像 Spark、Flink、Kafka 那样作为独立组件存在? 更准确的说法是:Hadoop 是一组关于"如何构建运行在大量廉价节点上的分布式系统"的前提假设在三个不同层面的具体化。这组前提把整个项目串成一条主线——节点总会失败、数据总是巨大、廉价比专用更重要。HDFS、YARN、MapReduce 各自处理这组前提下的一个子问题:HDFS 把大文件切成块并多副本放置,YARN 把集群资源切成容器并按策略分配,MapReduce 把大计算切成任务并按失败重试执行。 本系列只抓一个问题:Hadoop 这套以"节点总会失败"为前提假设的工程化方案,在 HDFS、YARN、MapReduce 三个层面是如何具体实现的,每个实现里有哪些可以迁移到其他分布式系统的设计模式。 GFS 论文留下的设计遗产 要理解...
各种各样的 Case:一份工程术语家谱
代码评审、用例设计、算法分析里到处是「XX case」:edge case、corner case、boundary case、happy path、worst case、base case……而且经常被当成同义词换着用。它们其实分布在几条互不相干的轴上,老家也分别在硬件工程、数学、算法分析和需求分析里,没有一个是测试专有的词。把它们各自摆回所属的轴,混淆就散了。 这些「case」大致落在四条轴上:输入空间里的位置、程序执行的场景走向、输入的刁钻程度、递归的收敛结构。 轴一 · 输入空间的位置 把每一个输入参数看成一根坐标轴:数组长度是一根轴,取值范围是一根轴,并发数是一根轴,时间是一根轴……所有参数张成一个高维空间。合法输入落在这个空间内部,被称作正常情况(normal case)。问题往往不出在中间,而出在这个空间的表面、棱和顶点上。 拿一个二维矩形打比方最直观。矩形的内部是正常区域,四条边是它的边界,四个角是两条边的交点。edge 对应边,corner 对应角,这不是巧合。两个术语最早就是从模拟电路和硬件工程的这套几何语言里借来的。 normal case(正常情况) 落...
导读:React 不是模板引擎,是一个渲染调度系统
本文只抓一个问题:React 到底在解决什么问题?答案不是"简化 DOM 操作",而是把 UI 更新从命令式的逐步操作变成声明式的状态映射。理解这个范式转移,是后续所有文章的前提。 同一个需求,两种写法 需求:页面上有一个计数器,点击按钮数字加一。 jQuery 写法: 12345678910// jQuery:告诉浏览器"怎么做"$(document).ready(function() { let count = 0; $('#counter').text(count); $('#increment').click(function() { count++; $('#counter').text(count); // 手动把新值写到 DOM });}); React 写法: 1234567891011// React:告诉框架"应该是什么样"function Counter() { co...
导读:TypeScript 不是给 JavaScript 加注解,是给 JavaScript 加类型系统
本文只抓一个问题:TypeScript 到底在 JavaScript 之上加了什么?答案不是"类型注解",而是一整套结构化类型系统。理解这个区别,是后续所有文章的前提。 一个反直觉的例子 123456789101112interface Cat { name: string; meow(): void;}interface Dog { name: string; meow(): void;}const dog: Dog = { name: "Buddy", meow() { console.log("woof?"); } };const cat: Cat = dog; // 编译通过,没有任何警告 Cat 和 Dog 是两个完全不同的 interface,名字不同,语义不同,但 TypeScript 认为它们可以互相赋值。 把同样的事情放到 Java 里: 12345interface Cat { String getNam...
Agent 会话边界设计:Session、Context Window 与工作状态转移
多阶段 Agent 工作流常遇到一个问题:前一阶段已经结束,消息历史仍然带着大量搜索结果、失败命令和废弃路径;下一阶段需要其中的约束,却不需要完整过程。此时应该继续同一会话、做一次 compact、派发子 Agent,还是从 checkpoint 启动新会话? 这个问题不能靠在 messages 数组里寻找某个神奇下标解决。需要设计的是工作状态怎样越过边界,以及边界后的 Agent 怎样证明自己已经恢复到可执行状态。 四种边界经常被混在一起 “会话”在不同产品和讨论里可能指四件事: 边界 它分隔什么 典型操作 主要风险 Context Window 边界 当前一次模型调用可见的工作集 prune、compact、重新装配 关键信息遗漏、摘要失真 Durable Session 边界 可恢复的事件日志或产品会话 resume、fork、clear、新建 session 把持久日志误当成模型当前输入 Work Phase 边界 规划、实现、验证等工作阶段 checkpoint、handoff、验收门 阶段输出没有形成可验证契约 Agent / Role 边...
2026 Coding Harness 实现图谱:Skill、上下文与扩展系统
AI Coding 产品常被放进一张“功能对比表”,但模型、API、Harness 和最终产品并不在同一层。把 Kimi 模型和 Claude Code 的本地文件扫描放在一起比较,或者用 API 的 Prompt Cache 解释 CLI 的 Skill 热更新,都会制造错误结论。 更稳定的比较单位是 Coding Harness:它位于模型与代码仓库之间,负责发现指令、装配上下文、暴露工具、执行 Hook、派生子 Agent,并在长会话里处理压缩与恢复。 核验日期:2026-07-17。表格只记录官方文档和官方更新日志能够支持的事实。未公开的实现统一标成“未知”,不根据相似产品补齐。 先确定比较层级 层级 主要职责 不应混入的结论 模型 推理、上下文容量、工具调用格式、多模态能力 不负责扫描本地 SKILL.md API / Provider 请求协议、鉴权、缓存计费、托管工具 不等于 CLI 每轮如何装配上下文 Coding Harness 指令发现、Skill 目录、工具运行、compact、Hook、子 Agent 本文的主要比较对象 能...
AI Coding Agent 的 Skill 加载机制深度解析
Skill 加载看起来像一个文件读取问题,实际包含两条不同的链路: 宿主进程何时扫描、解析并缓存 SKILL.md Skill 内容何时进入模型可见的上下文 两条链路可能一早一晚。OpenCode 会在宿主侧初始化 Skill registry,但模型仍要调用 skill 工具才会看到正文;Claude Code、Codex、Cursor 和 Kimi Code 也都把轻量目录与完整说明分开处理。用“启动时有没有读文件”判断是否按需加载,很容易得出相反结论。 更准确的问题有三个:模型启动时看到了什么,正文以什么形式进入会话,长会话压缩后哪些内容能够恢复。 核验日期:2026-07-17。产品实现会持续变化。正文把官方公开契约、源码观察和未知行为分开标注,不用一个产品的行为推断另一个产品。 比较对象必须处在同一层 模型、API、Harness 和最终产品经常共用一个名字,但它们负责的事情不同。 层级 负责什么 例子 模型 上下文上限、推理、工具调用能力、多模态 Claude、GPT、Kimi K2 API / Provider 请求协议、缓存计费、Too...




