computer-science / systems
系统剖析
Git、PostgreSQL、Redis、Kubernetes、Linux 容器——真实系统内部到底怎么运作
48 篇
Git 的对象模型:为什么分支是廉价的
Git's Object Model — Why Branches Are Cheap
在一个二十年历史、上百万次提交的仓库里敲 git branch feature-x,回车之后光标立刻就回来了。同一台机器上复制一份工作目录要等几十秒,而 Git 建分支的耗时与仓库大小完全无关。
Git · 内容寻址 · 哈希
SQLite:世界上部署最广的数据库
SQLite: The World's Most Widely Deployed Database
你从来没有安装过它,但你身上大概带着几十份它。
SQLite · 嵌入式数据库 · 预写日志
PostgreSQL 的 MVCC:读不阻塞写的代价
PostgreSQL MVCC: The Price of Readers Never Blocking Writers
一个再普通不过的场景:财务在跑一份要花八分钟的月度报表,与此同时,几百个用户正在下单、改地址、退款。报表读的是账户表,用户写的也是账户表。
PostgreSQL · 并发控制 · 事务隔离
Redis 的单线程模型:为什么不并行反而更快
Redis's Single-Threaded Model: Why Refusing Parallelism Made It Fast
买一台 32 核的服务器,装上 Redis,打开监控——你会看到 31 个核几乎在闲着。
Redis · 事件循环 · I/O 多路复用
Linux 容器:它不是虚拟机
Linux Containers: Not a Virtual Machine
在一台跑着 Debian 的机器上敲 docker run --rm -it ubuntu:24.04 bash,一秒之内你会拿到一个 Ubuntu 的 shell。cat /etc/os-release 说这是 Ubuntu,apt 能用,/usr/lib 里躺着 Ubuntu 版本的 libc。
容器 · 命名空间 · cgroups
Kubernetes 的控制器模式:声明式系统怎么收敛
The Kubernetes Controller Pattern: How Declarative Systems Converge
敲下 kubectl apply -f deployment.yaml,命令一秒返回,三个容器过一会儿就跑起来了。直觉会告诉你:这条命令去创建了三个容器。
Kubernetes · 调谐循环 · 声明式配置
Kafka:把消息队列还原成一个日志
Kafka: Reducing the Message Queue to a Log
2011 年,LinkedIn 的 Jay Kreps、Neha Narkhede、Jun Rao 在 NetDB 研讨会上发表了《Kafka: a Distributed Messaging System for Log Processing》。这篇论文里没有新算法,也没有新协议。
Kafka · 仅追加日志 · 分区
LLVM 的中间表示:编译器生态的枢纽
LLVM IR — The Hub of the Compiler Ecosystem
Rust、Swift、Julia、C++、Fortran 是五门差异极大的语言;x86-64、AArch64、RISC-V、NVIDIA 的 PTX、WebAssembly 是五套差异同样极大的指令集。今天这两侧的绝大多数组合都能编译成功,而世界上并没有二十五个独立的编译器。
编译器 · 中间表示 · 静态单赋值
Nginx 的事件驱动架构:一个进程如何扛住十万连接
Nginx's Event-Driven Architecture: How One Process Holds a Hundred Thousand Connections
2002 年,Igor Sysoev 在俄罗斯门户站点 Rambler 做系统管理。他遇到的不是"服务器慢",而是一个更硬的墙:Apache 的连接数一旦爬到几千,机器就开始换页、卡顿、拒绝服务,而此时 CPU 使用率并不高,磁盘也没跑满。资源明明还在,服务却已经不能用了。
Nginx · 事件驱动架构 · I/O 多路复用
TLS 与证书生态:陌生人之间如何建立信任
TLS and the Certificate Ecosystem: How Strangers Establish Trust
你在地址栏敲下一个域名,几十毫秒之后,你的浏览器和一台从未见过的机器已经共享了一串只有它们两个知道的字节。中间隔着你家的路由器、运营商的骨干网、若干个数据中心的负载均衡器,任何一环都能读到全部流量,也能篡改全部流量。
TLS 握手 · 证书链 · 证书透明度
etcd:把 Raft 变成能用的东西
etcd: Turning Raft Into Something Usable
Raft 论文只有十六页。读完之后你会有种错觉:这东西我能实现。选举、日志复制、安全性约束,每一条都写得清清楚楚,伪代码就在图 2 里。
etcd · Raft 共识 · 预写日志
Linux 调度器:从 CFS 到 EEVDF
The Linux Scheduler: From CFS to EEVDF
你的笔记本上现在大概跑着一千多个线程,而 CPU 只有八到十六个逻辑核。每过几毫秒,内核就要回答一次同一个问题:下一微秒,这个核给谁?
Linux 内核 · 进程调度 · 公平共享
Chromium 的站点隔离:把进程边界当作安全边界
Chromium's Site Isolation: Making the Process Boundary the Security Boundary
在 Chrome 里按 Shift+Esc 打开自带的任务管理器,然后只开一个标签页去看一个普通的新闻网站。你大概率会看到不止一行:主文档一行,广告位的 iframe 一行,社交分享按钮的 iframe 又一行,统计脚本所在的 iframe 再一行。一个标签页,四五个操作系统进程。
站点隔离 · 进程模型 · 沙箱
对象存储:S3 如何改变了存储的形状
Object Storage: How S3 Reshaped What Storage Is
2006 年 3 月 14 日,Amazon 上线了一个只有四个主要动词的存储服务:PUT、GET、DELETE、LIST。定价是每 GB 每月 0.15 美元,外加每 GB 传出 0.20 美元。它没有目录,没有文件句柄,不能定位到文件中间某个字节去改写,也不能把一个名字改成另一个名字。
对象存储 · 纠删码 · 一致性模型
xz 后门:一次针对开源信任结构的社会工程
The xz Backdoor — Social Engineering Against the Trust Structure of Open Source
2024 年 3 月下旬,微软的 PostgreSQL 开发者安德烈斯·弗罗因德在自己那台 Debian sid 机器上跑数据库基准测试。他注意到一件不该发生的事:ssh 登录变慢了,而且慢在 CPU 上——即使用户名是错的、连接立刻被拒,sshd 进程也要多烧掉大约半秒的 CPU 时间。
供应链攻击 · 后门 · 开源维护
构建系统:从 Make 到可复现构建
Build Systems — From Make to Reproducible Builds
一个几乎所有程序员都干过的动作:改了代码,make,跑起来行为没变,怀疑人生半小时,最后敲了 make clean && make,一切正常。
构建系统 · 增量构建 · 内容寻址
V8 的分层 JIT:动态语言如何跑得快
V8's Tiered JIT: How a Dynamically Typed Language Runs Fast
在 C 里写 p->x,编译出来是一条指令:从 p 指的地址往后数固定的字节数,取值。偏移量是编译期算好的常数,因为结构体的布局写在类型里,类型在编译期就定死了。
即时编译 · V8 · 隐藏类
Rust 的借用检查器:把内存安全变成编译期问题
Rust's Borrow Checker: Turning Memory Safety into a Compile-Time Problem
C 语言里有一类 bug,它的特征是出错的位置和崩溃的位置没有关系。你在某处 free(p),程序继续跑了两毫秒、经过了三十个函数,某个完全无辜的地方读到一块已经被别人重新分配走的内存,返回一个看似合理的数字。没有信号、没有异常、没有栈回溯指向真凶。等它终于崩溃时,现场早已被清理干净。
内存安全 · 所有权 · 借用检查
QUIC:把传输层搬进用户态
QUIC: Moving the Transport Layer into User Space
一个网页有 80 个资源要下载。HTTP/2 说:不用开 6 条连接了,一条就够,80 个请求在同一条 TCP 连接上并行跑,互不阻塞。
队头阻塞 · 用户态传输 · 协议僵化
Envoy 与服务网格:把网络逻辑从应用里搬出来
Envoy and the Service Mesh: Moving Network Logic Out of the Application
2015 年前后的 Lyft 正处在一段很典型的迁移里:一个 PHP 单体被拆成几十个 Python 和 Go 服务。拆完以后出现了一类新的故障——请求失败了,但没有任何一个服务认为自己出了错。
Envoy · 服务网格 · sidecar 代理
ZFS:不覆盖写,与端到端校验
ZFS: Never Overwrite, Always Verify
磁盘没坏,SMART 全绿,读请求正常返回,没有任何一层报错——但返回的那 4 KiB 不是你当年写进去的内容。可能是固件把数据写到了错误的扇区,可能是控制器的 DMA 传输翻了一个比特,可能是缓存声称"已经落盘"其实没有。
文件系统 · 写时复制 · 数据完整性
被 1 个领域引用(哲学思想)
Lucene:搜索引擎内部的倒排索引
Lucene: The Inverted Index Inside a Search Engine
一个装了两千万篇文档的系统,你输入"量子纠缠",两百毫秒之内屏幕上出现十条结果,还按相关度排好了序。
Lucene · 倒排索引 · 全文检索
Prometheus:拉模型与时序数据的代价
Prometheus: The Pull Model and the Price of Time Series
2012 年 11 月 24 日,Prometheus 仓库收到第一个公开提交。写下它的 Matt T. Proud 和 Julius Volz 刚刚离开 Google 加入 SoundCloud,手里带着一套用惯了的东西的记忆——Borgmon,Google 内部那个基于时间序列做告警的监控系统。
Prometheus · 拉模型 · 时序数据库
curl:一个人维护的全球基础设施
curl — Global Infrastructure Maintained by One Person
手边任何一台联网设备,多半正在用 curl 说话。手机应用拉一张图、机顶盒检查固件更新、车机后台下载地图、打印机去查耗材余量、游戏主机同步存档——这些请求里有相当一部分不是应用自己写的网络代码,而是一个叫 libcurl 的 C 库替它们发出去的。curl 项目在 2025 年给出的估算是:全球约三百亿份装机。
开源维护 · 网络传输库 · 向后兼容
seL4:被证明的微内核
seL4: The Kernel That Was Proved
2009 年 10 月,美国蒙大拿州 Big Sky 的 SOSP 上,Gerwin Klein 一队人把一份听起来过分的结果摆上桌:一个通用微内核的 C 实现,与一份抽象规格之间,存在机器检查过的精化关系。内核大约 8700 行 C,外加约 600 行汇编。证明脚本大约 20 万行 Isabelle/HOL。
seL4 · 形式化验证 · 微内核
Dynamo:最终一致的键值存储
Dynamo: Eventually Consistent Key-Value Storage
2004 年到 2007 年,亚马逊的购物车不能停。一次“加入购物车”若因为某台存储节点宕机而失败,页面上就是真金白银的放弃。Giuseppe DeCandia 一队人要的不是全局事务,而是一句更土的承诺:写操作在部分机器挂掉时仍然成功。2007 年 SOSP 上的论文把这套系统叫 Dynamo。
Dynamo · 最终一致性 · 一致性哈希
Spanner:用时钟换外部一致性
Spanner: Buying External Consistency with Clocks
2012 年 OSDI 上,Google 的 James C. Corbett 一队人描述了一套全球数据库:数据按目录切开放进 Paxos 组,事务跨组用两阶段提交,而时间戳不来自逻辑时钟,来自一个叫 TrueTime 的 API。
Spanner · TrueTime · 外部一致性
Firecracker:微型虚拟机
Firecracker: MicroVMs
AWS Lambda 的计费粒度是毫秒,租户是陌生人。容器共享宿主机内核,启动快,边界宽;传统虚拟机边界窄,启动却要拖着一整套模拟设备。
Firecracker · microVM · KVM
PyTorch:动态图与自动微分
PyTorch: Dynamic Graphs and Automatic Differentiation
2017 年的 NeurIPS 自动微分研讨会上,Adam Paszke、Sam Gross、Soumith Chintala 等人把 PyTorch 的核心机制写成一篇短文:前向计算一边跑,一边在磁带上记下用过的函数;反向时把磁带倒放,用向量—雅可比乘积把梯度送回每个叶子张量。
PyTorch · autograd · dispatcher
vLLM:把 KV 缓存当成虚拟内存
vLLM: PagedAttention and the KV Cache as Virtual Memory
2023 年 SOSP 上,加州大学伯克利分校 Sky Computing Lab 的 Woosuk Kwon、Zhuohan Li 与同事描述了 vLLM:一套为大语言模型在线服务设计的内存管理器。他们的观察很具体。
vLLM · PagedAttention · KV 缓存
JVM:字节码、JIT 与垃圾回收
The JVM: Bytecode, JIT, and Garbage Collection
HotSpot 这个名字来自一个经验判断:程序里真正值钱的是一小撮反复执行的热点,而不是每一字节码都值得同等待遇。它的前身是 Animorphic 的 Strongtalk,血统接到 Self 语言那一套类型反馈与内联缓存。Sun 在 1997 年买下这项技术,2000 年的 Java 1.3 把它做成默认虚拟机。
HotSpot · 即时编译 · 分层编译
CPython 的 GIL
CPython's GIL
CPython 的全局解释器锁(GIL)是一把进程里的互斥锁:同一时刻只允许一个线程执行 Python 字节码。它不是语言标准的一部分。PyPy、Jython、IronPython 各自用过不同的策略。但它是默认解释器上那条最被抱怨、也最被依赖的边界。
CPython · GIL · 引用计数
Neo4j 属性图:当邻居指针取代 JOIN
Neo4j Property Graphs: When Neighbor Pointers Replace Joins
把好友关系、供应链、分子键画成圆点和箭头,几乎人人都会。把这张图画进数据库,很多人的第一反应却是:再加一张关联表,用 JOIN 把两边拼回去。这条路能走通,也把图查询最贵的那一步藏进了优化器:每多走一跳,就要再做一次基于索引的查找。
Neo4j · 图数据库 · 属性图
HNSW 与向量近邻:当距离代替关键词
HNSW and Vector ANN: When Distance Replaces Keywords
倒排索引回答的是“哪些文档含有这些词”。向量索引回答的是另一句:给定一个高维点,谁在几何上离它最近。推荐、以图搜图、以及把句子编成嵌入再检索,都把问题收成近似 k 近邻(ANN)。精确扫一遍全部向量,在百万、千万规模上太贵。近似的意思是:允许漏掉少数真近邻,换回可接受的延迟。
HNSW · 近似近邻 · 向量检索
GFS:单主节点、大块与可忍受的不一致
GFS: Single Master, Large Chunks, and Consistency MapReduce Could Live With
2003 年 10 月,SOSP 在纽约州博尔顿兰丁开会。
GFS · 分布式文件系统 · 块复制
Bigtable:稀疏表、Tablet 与时间戳单元
Bigtable: Sparse Tablets and Timestamped Cells
2006 年 11 月,OSDI 在西雅图开会。
Bigtable · Tablet · SSTable
Chubby:松耦合系统上的锁服务,不是又一套数据库
Chubby 2006: Lock Service for Loosely-Coupled Distributed Systems
2006 年,OSDI 上 Mike Burrows 交出的不是又一套能扛吞吐的存储,而是 Google 已经跑了一年多的粗粒度锁服务。接口看起来像一套很小的文件系统:目录、整文件读写、劝告式读写锁,再加上文件被改、句柄失效这类事件。论文把目标写得很窄。
Chubby · 锁服务 · Paxos
ZooKeeper:等待自由的协调,不是又一套 Chubby 说明书
ZooKeeper 2010: Wait-free Coordination for Internet-scale Systems
2010 年 6 月,USENIX ATC 上,Yahoo Grid 的 Patrick Hunt、Mahadev Konar 与 Yahoo Research 的 Flavio P. Junqueira、Benjamin Reed 交出的不是又一套锁服务说明书,而是已经在 Yahoo 生产里跑着的协调内核。
ZooKeeper · znode · watch
Chord:标识符环上的查找,不是中心目录
Chord 2001: Identifier Ring, Successor, and Finger Table
2001 年 8 月,SIGCOMM 在圣地亚哥开会。
Chord · 手指表 · 后继
Kademlia:XOR 距离上的 k-bucket,不是环上的手指
Kademlia 2002: XOR Distance, k-buckets, and Iterative Lookup
2002 年 3 月,第一届 IPTPS 在麻省剑桥开会。
Kademlia · XOR 距离 · k-bucket
Pastry:前缀表、叶集与邻近集,不是环上的手指
Pastry 2001: Prefix Routing, Leaf Set, and Neighborhood Set
2001 年 11 月,IFIP/ACM Middleware 在海德堡开会。
Pastry · 前缀路由 · 叶集
Viewstamped Replication:视图、主副本与盖章请求,不是又一份 Paxos
Viewstamped Replication 1988: Views, Primary Copy, and Stamped Requests
1988 年,麻省理工学院计算机科学实验室的布莱恩·奥基(Brian M. Oki)与芭芭拉·利斯科夫(Barbara H. Liskov)在第七届 ACM PODC 上交出一篇十页论文,会议录页码 8 至 17,DOI 10.1145/62546.62549。
Viewstamped Replication · 主副本 · 视图戳
Tapestry:邻接表、代理路由与就近副本,不是把对象搬到键上
Tapestry 2001: Neighbor Maps, Surrogate Routing, and Nearby-Copy Location
2001 年 4 月,加州大学伯克利分校计算机科学部发出技术报告 UCB/CSD-01-1141。
Tapestry · 邻接表 · 代理路由
CAN:笛卡尔分区与贪心转发,状态不随规模涨
CAN 2001: Cartesian Zones, Greedy Routing, and N-Independent State
2001 年 8 月,SIGCOMM 在圣地亚哥开会。
CAN · 内容寻址网络 · 笛卡尔空间
ISIS 1985:进程组、flush 与虚拟同步,不是又一份 ZooKeeper
ISIS 1985: Process Groups, Flush, and Virtual Synchrony
1985 年 12 月,康奈尔大学的肯尼斯·伯曼(Kenneth P. Birman)在第十届 ACM SOSP 上交出八页论文,会议录页码 79 至 86,DOI 10.1145/323627.323636。题目是 Replication and Fault-Tolerance in the ISIS System。
ISIS · 虚拟同步 · 进程组
Demers 1987:谣言与反熵怎样维护副本,不是 Dynamo
Epidemic Algorithms for Replicated Database Maintenance
1987 年 8 月,第六届 ACM PODC 在温哥华开会。
流行病算法 · 反熵 · 谣言传播
Terry 1994:会话保证怎样把弱一致副本写成客户视角
Terry 1994: Session Guarantees for Weakly Consistent Replicated Data
1994 年 9 月,第三届 International Conference on Parallel and Distributed Information Systems(PDIS)在奥斯汀开会。
会话保证 · Bayou · 读己之写
Schneider 1990:副本确定性、输出一致与状态机方法,不是又一份 Paxos
Schneider 1990: Replica Determinism, Output Agreement, and the State Machine Approach
1990 年 12 月,康奈尔大学的弗雷德·B·施奈德(Fred B. Schneider)在 ACM Computing Surveys 第 22 卷第 4 期发表一篇二十一页教程,页码 299 至 319,DOI 10.1145/98163.98167。
状态机复制 · 副本确定性 · 输出一致