分布式系统(26):Spanner 的时间区间、提交等待与一致快照
一笔转账同时修改两个分片。两边最终都提交,只解决了共同终局;报表还需要在一次读取中看到完整的转账结果。如果转账已经向客户端报告成功,随后发起的强一致读取也不能因为选择了较慢的时钟而退回转账之前。 分布式系统(25):分布式事务的决定、补偿与消息边界 Spanner 把这些要求组合在同一个数据库里:每个复制组保存可恢复的状态,跨组事务决定共同结果,并发控制约束冲突操作,时间戳和多版本读取决定快照内容。TrueTime 提供带误差边界的时间区间,提交等待把时间戳顺序与真实先后连接起来。机制推导以 OSDI 2012 原论文为准,课程结构对应 MIT 6.5840 和 Stanford CS244b;现行云产品的隔离级别单独说明。 复制、事务与时间各自约束什么 设账户 x 位于组 A,账户 y 位于组 B。一次事务要从 x 扣款并向 y 加款。每个组内部有多个副本,通过 Paxos 复制状态;A、B 作为两个业务参与组,通过两阶段提交协调这笔转账。组内复制多数与跨组全部参与者是两个不同集合:A 的多数派确认,不能代替 B 的准备结果。 flowchart TB T[跨分片转账 T]...
分布式系统(25):分布式事务的决定、补偿与消息边界
订单记录已经提交,支付消息却没有发出。把顺序反过来,支付消息可能已经被处理,订单事务随后回滚。两个系统各自正确地完成一次操作,仍然不能保证这两次操作具有共同的结果。 分布式系统(24):分片与在线迁移的归属边界 前篇解决一个分片迁移后由谁服务。跨分片下单还需要回答另一件事:订单、库存和支付分别位于不同资源时,哪些变化必须一起提交,哪些中间结果允许出现,失败后还剩什么义务。站内既有的分布式事务覆盖更多方案名称;这里沿同一条订单链路推导失败路径,再用本地实验检查原子边界。 两次成功调用之间存在失败窗口 先限定业务含义。订单服务创建的是“待支付订单”,消息是“请求扣款”,消费者在自己的账本里扣款。订单创建成功不代表支付完成。若业务要求两个资源共同提交或共同中止,需要跨资源原子提交;若还要求读者看不到部分结果,还必须设计跨资源的隔离与读规则。若允许订单先进入待处理状态,则可以持久保存后续动作,由工作流继续推进。这是对可观察行为的选择。 sequenceDiagram participant S as 订单服务 participant D as 订单库 participant ...
计算机网络 26:HTTP/2 的多路复用解决了哪一层阻塞,帧、流、HPACK 与窗口
一个慢响应还没结束,同一连接上的小响应能不能先完成?如果能,为什么丢失一个 TCP 段仍可能让多个响应一起等待?这两个问题分别涉及 HTTP 消息的组织方式和底层字节流的交付条件。 前置是第 18 篇接收窗口、第 22 篇消息边界与第 24 篇 TLS。本篇把流标识、字段压缩、接收窗口和 TCP 顺序交付分开,避免把“多路复用”解释成每个请求拥有独立网络通道。 消息拆成帧后,响应可以交错 HTTP/1.1 流水线允许前一个请求尚未收到响应时继续发送请求,但响应仍按请求顺序返回。一个响应占用字节流时,后一个响应不能随意把正文插进去,否则接收者无法按原有消息规则区分归属。 HTTP/2 在帧头中携带流标识。接收端先识别帧,再把内容交给相应的流。一个连接可以同时存在多个未关闭的流,因此服务器能够在一个大响应的两个 DATA 帧之间发送另一个流的响应。请求和响应仍保留 HTTP 语义,改变的是表达方式。 RFC 9113 §4.1规定固定 9 字节帧头,包括长度、类型、标志和流标识。长度描述帧载荷,不包含这 9 字节。流标识 0 用于连接范围的控制,不能当成普通请求编号;客户端发起的流使...
从零编写操作系统 28 - 窗口管理:Z 序、焦点与拖动
Day 27 已经把鼠标字节变成坐标、按键和边沿,但屏幕上仍然只有一个直接重绘的字符终端。窗口管理要再回答三件事:重叠位置显示谁,点击交给谁,拖动过程中谁持续拥有指针。 本篇实现一个固定双窗口管理器。窗口表保存几何和文本,Z 序单独保存遮挡关系;命中从顶向底查找,绘制从底向顶执行。左键按下标题栏后建立拖动捕获,键盘字符只写入焦点窗口。每次状态变化仍重建完整 320×200 画面,以最小机制先验证所有权和遮挡恢复。 窗口表与 Z 序承担不同职责 两个窗口的内容放在固定表中: 1234567891011121314struct demo_window { int32_t x, y; uint32_t width, height; uint8_t body_color; char name; char text[8]; uint32_t text_length;};struct demo_window windows[2] = { {20, 40, 150, 100, 1, 'A',...
计算机体系结构 16:缓存基础
缓存基础 同一个求和循环里,处理器不断访问相邻数组元素,也会反复取循环体那几条指令。若每一次都从更慢的下层存储取数据,流水线前几篇讨论的前递、停顿和分支恢复很快就被访存等待淹没。缓存的基本承诺很小:把最近用过或附近可能要用的一块数据放在更靠近处理器的位置,下一次地址命中时少走一段路。 本篇的核心问题是:给定一串地址,怎样判断每一次访问落在哪个 set、比较哪个 tag、替换哪一行,以及一次 miss 是冷缺失、容量缺失还是冲突缺失?核心案例使用 16B block、4 个 cache line 的有限模型,对同一地址序列分别跑直接映射和两路组相联。证据等级为功能执行,所有数字来自可复跑 Python 模型;它不是 gem5 仿真,也不是本机硬件计数器。 实验目录为 examples/computer-architecture/cache/。本文附件包括 mapping.json.txt、cache_model.py.txt 和 run_cases.py.txt。附件扩展名使用 .txt,便于博客直接下载查看。 从地址到 block、set 和 tag 缓存不按单个字节管理数据,而...
计算机体系结构 17:多级缓存与写入
多级缓存与写入 读 miss 只需要把缺失的 block 带到更近的位置。写访问多了一层约束:处理器已经修改了一份副本,下层存储何时看见这个修改?若替换时还有未写回的数据,旧 block 能否直接丢弃?这些问题决定了写策略、dirty bit 和多级缓存的平均访问时间。 本篇的核心问题是:write-through、write-back、write-allocate 和 no-write-allocate 分别改变哪条流量;脏块逐出怎样计入代价;AMAT 的条件概率公式何时能用?核心案例用 1 set × 2 way × 16B 的 write-back/write-allocate cache 追踪五次访问,并补一个 no-write-allocate 写 miss 的反例。证据等级为功能执行加手算。 实验目录为 examples/computer-architecture/cache/。本文附件包括 writeback_amat.json.txt、cache_model.py.txt 和 run_cases.py.txt。 四个写策略词不要混成一个选择 write-throu...
计算机体系结构 18:DRAM 与内存控制器
DRAM 与内存控制器 cache miss 以后,请求并不是掉进一个统一的“主存延迟”黑箱。DRAM 有 bank、row buffer、列访问、预充电、刷新和总线仲裁。同样是读取 16B,命中已经打开的 row、换到同一 bank 的另一行、撞上 refresh,等待和服务时间都不同。 本篇的核心问题是:怎样在公开声明的教学时序模型里区分 row hit、row conflict、refresh wait,以及请求等待时间和服务时间?核心案例使用 2 个 bank、64B row、16B block 的小型控制器。证据等级为教学时序模型;参数名参考 gem5 DRAMInterface,但数值是本文题设,不是某款 DRAM 器件。 实验目录为 examples/computer-architecture/cache/。本文附件包括 dram.json.txt、cache_model.py.txt 和 run_cases.py.txt。 地址先映射到 bank 和 row 本文映射函数很小: 123block = address // 16bank = block % 2ro...
计算机体系结构 19:隐藏访存延迟
隐藏访存延迟 一次 cache miss 的原始延迟可能很长,但程序不一定完全停住。若后面还有独立 miss,非阻塞 cache 可以让多个请求同时在路上;若后面的地址依赖前一次 load 的结果,处理器只能等。预取则尝试在需求访问前把数据带来,但它也会消耗带宽、占 cache line,甚至挤掉后续需要的数据。 本篇的核心问题是:MSHR 怎样让独立 miss 重叠,同一 block 的 miss 怎样合并,依赖链为什么无法重叠;预取命中率之外还要统计什么流量和污染?核心案例使用两个 MSHR entry、10 周期 miss latency 和 next-line prefetch。证据等级为教学时序模型,关键反例由功能断言保护。 实验目录为 examples/computer-architecture/cache/。本文附件包括 mshr_prefetch.json.txt、cache_model.py.txt 和 run_cases.py.txt。 非阻塞 cache 保存“还没回来”的 miss MSHR(Miss Status Holding Register)可以理...
计算机体系结构 21:页故障与映射修改
计算机体系结构 21:页故障与映射修改 核心问题 上一篇把地址翻译分成三类结果:TLB miss 后成功、权限失败产生 page fault、翻译成功后再进入数据缓存。本篇继续追踪 page fault 之后发生什么。 一个页故障不是“硬件把问题修好”。硬件报告故障信息,软件决定要不要修复映射、如何更新页表、何时让当前 hart 的旧翻译失效、是否通知其他 hart。本文用一个有限状态轨迹回答三个问题: page fault 报告了什么。 软件补映射后,为什么还要本地 SFENCE.VMA。 多 hart 场景下,为什么本地 fence 不等于远端 shootdown。 异常处理要区分“报告、修复、重试、广播”。硬件只完成报告和控制流转移;页表修改、失效范围和远端协调是软件协议。 边界 一手依据仍然是 RISC-V Privileged Architecture 的 supervisor 规范。2026-09-22 通过可读官方 supervisor 页面核对到 Supervisor-Level ISA 1.13;固定版本 URL 当前不可直接读取,因此正文引用可读官方 UR...
计算机体系结构 23:缓存一致性与所有权转移
计算机体系结构 23:缓存一致性与所有权转移 核心问题 第 16 到第 22 篇把单核视角里的 cache、DRAM、TLB、异常和数据布局串起来。多核一出现,同一个地址可能同时存在于多个核心的私有 cache 中。问题不再只是“这次访问命中哪一级”,而是:某个核心写了一个地址后,其他核心还能不能读到旧副本;某个 cache line 的最新值到底来自内存,还是来自另一个核心的脏副本。 缓存一致性解决的是单个地址的副本管理。它不保证所有地址上的操作都像单线程那样排成一个全局序列;跨地址顺序属于内存一致性模型,第 24 篇单独处理。本篇只回答一个可验收的问题:对一个 cache line,如何用失效、共享、独占和脏所有者转移,维持“同一时刻最多一个可写副本”和“读到的值来自最近一次有效写入”。 本文附件: mesi_cases.py.txt mesi_trace.json mesi_summary.txt 证据等级:功能执行。模型是 Python 标准库写成的单 cache line 教学状态机,复跑时会检查 SWMR 断言、失效确认、脏数据来源和最终内存值。它不是商品处理器 ...







