【存储工程】S3 API 深度解析
全面剖析 S3 API 的工程细节——Multipart Upload、S3 Select、生命周期策略、跨区域复制、性能优化与 boto3 高级用法
发布来自土法炼钢兴趣小组的知识、笔记、进展和应用。主题包括数据结构和算法、编程语言、网络安全、密码学等。
共 260 篇文章 · 返回首页
全面剖析 S3 API 的工程细节——Multipart Upload、S3 Select、生命周期策略、跨区域复制、性能优化与 boto3 高级用法
MinIO 原理和架构:Erasure Set、Server Pool、元数据与数据共置、修复与 IAM,以及 S3 兼容集群的部署运维要点。
深入剖析纠删码的数学原理与工程实践——Reed-Solomon 编码、编码矩阵与恢复过程、参数选择、降级读性能、局部修复码,以及在 MinIO/Ceph 中的配置实战
系统分析小文件在块分配、元数据管理、磁盘寻道和网络协议四个层面的放大效应,用数据量化 slack space、inode 开销和 syscall 成本,给出应用层聚合与对象存储归档两种工程方案。
汇总本站存储工程系列文章,覆盖 HDD、SSD、NVMe、持久内存、索引结构、压缩、分布式存储与对象存储。
汇总本站数据库内核文章:PostgreSQL / MySQL InnoDB / 列存、湖仓、流处理、查询引擎、RocksDB、向量、Redis、全文检索、TiKV/HTAP、FoundationDB、SQLite 与 WiredTiger 内核,以及 LSM-Tree 实验与其它单篇。
定位专用向量检索引擎相对 ANN 算法、RAG 应用与湖仓格式的分工;以 Milvus 2.6.x 四层架构与 insert/search 最小故事建立坐标系,并交代从 SIGMOD 2021 到 Streaming 演进的谱系与常见误解。
把 HNSW、IVF、DiskANN、Flat 收成引擎侧 Train/Build/Load/Search 契约与构建期/查询期参数面;用生命周期图与召回–QPS–内存三角说明索引如何贴着 Segment,并与 db-frontier/08、第 8 篇 Knowhere 分工。
用最小故事钉住 Milvus 2.6.x 数据模型:Collection/Partition、vchannel/pchannel 与 Streaming Node 绑定,Growing/Sealed、flush 与 handoff 状态机,并纠正「一个 Collection 一张大图」等常见误解。
以一次 collection 生命周期里的 DDL/DML/DQL 请求为线索,拆解 Milvus 2.6.x 无状态 Proxy 的路由与 MPP 归并,单活跃 Coordinator 的 TSO/timetick 全序机制与任务调度,并对照 Spanner/TiDB 的时间戳设计说明工程取舍。
以一条 insert 从 SDK 到「立刻能被搜到」的最小故事为线索,拆解 Milvus 2.6.x Streaming Service 三件套、Message/TSO 写顺序、Woodpecker 零本地盘 WAL 的 MemoryBuffer/QuorumBuffer 模式,并标明官方吞吐数字的引用边界。
以 flush 后去对象存储里查看文件为线索,拆解 Milvus 2.6.x 的对象路径结构(insert_log/delta_log/stats_log/index_files)、V1 按字段拆分与 V2 按段整合 Parquet 的寻址代价差异,并给出官方文档中可核对的 API 调用量级引用。
按 Milvus 2.6.x Data Processing 与 Architecture 拆解 Query Node 对 Sealed 的加载与段级检索,说明 Streaming Node 上 Growing 路径与 Query Delegator 如何拼成一次 search,用最小故事与常见误解钉住 Segcore 与 Knowhere 的层次边界。
按官方 Knowhere 文档说明其在 Milvus 中的位置、相对 Faiss 的扩展(bitset、SIMD 选择、二进制度量)、VecIndex 类层次与 IDMAP/IVF/HNSW 等类型,用插件注册、CPU/GPU 分发与 bitset 进查询三张图钉住工程契约,并与 db-frontier/08 的算法细节分工。
按 Milvus 2.6.x Data Processing 与 Architecture 拆解 search 的多级归并树:Proxy → Streaming Node Delegator → Query Node 段级结果;用最小故事、GuaranteeTs 等待时序图与常见误解说明一致性级别如何变成排队等待。
说明 Milvus 2.6.x 中 Data Node 作为离线 Worker 如何承接 Coordinator 下发的建索引与 compaction,输入输出如何进出对象存储;用最小故事、常见误解与队列积压图说明索引堆积如何拖垮查询新鲜度与资源争用。
按 Milvus 2.6.x Bitset、Filter Templating 文档拆解表达式如何变成 bitset 再喂给 Knowhere;用最小故事、bitset 取反细节与选择度打穿 Top-k 归并的示意图,说明为何过滤会改变延迟而不只是改变结果数量;对读 db-frontier/09 的 ACORN、Filtered-DiskANN 争论。
按官方 Consistency Level 与 Timestamp 文档拆解 Strong/Bounded/Session/Eventually 如何映射到 GuaranteeTs,用最小故事、四级时间轴与 Strong 等待时序图说明「一致性」在 Milvus 里首先是一笔延迟账;对照 Abadi PACELC 定理与 Bailis PBS,说明 Bounded 是定性旋钮而非概率保证。
按 2.6.x Delete/Upsert/TTL 文档拆解软删 bitset 从逻辑不可见到 compaction 物理回收的完整生命周期,用官方 override/merge 内部步骤的时序图区分两种 upsert,并与 FreshDiskANN 的图索引删除模型对照,说明 Milvus 用「整段重建」而非「增量合并」处理删除。
按官方 In-Memory Replica 与 Streaming Service 文档拆解副本组、shard leader、Proxy 缓存 failover 与 WAL Wait for Ready;用多副本拓扑图与迁移时序图说明 Milvus 的读副本更接近只读缓存池而非共识复制,并与 Chain Replication、PacificA 对照。
对照 Qdrant 与本系列 Milvus 主线:Segment 内的向量/payload/id mapper 三件套、WAL+序号版本化、后台 optimizer 四类任务,以及 Raft 只管拓扑不管点操作的分布式模型;说明何时单进程/小集群更合适。
承接 lakehouse/21 的 Lance vs Parquet 实测口径,用官方 Table Format 规范拆开 fragment/manifest/version 与 Milvus Segment/WAL 的边界;对照两边索引异步构建的共性,并给出湖侧 snapshot 与在线引擎可见性水位的对齐方式。
用症状到机制的决策树覆盖召回/延迟/堆积/OOM 四类故障,按可见性、段状态、过滤选择度、离线队列、对象存储与副本拓扑逐层定位;用一个跨软删广播与副本改派的最小故事说明为什么同一查询会得到不稳定结果,不含未跑的集群数字。
扩展选型决策树:从单机原型到十亿级多租户,逐层加入湖上格式、SQL 同进程、存算分离运维、多一致性级别四个判断轴;用一个团队规模演进的最小故事串起决策点,并回链 llm-infra RAG 与本系列全部核心论文谱系。
以 pgvector v0.8.0 源码钉住 Index AM、8KB 页上的 HNSW element/neighbor 元组与 iterative_scan;对照 Milvus Growing/Sealed 与 Knowhere,说明同进程 SQL 扩展买到的事务边界与付掉的页模型/资源争用代价。
补齐 ANN 算法与 RAG 应用之间的生产级向量引擎层:以 Milvus 2.6.x 为主线拆解 Segment、WAL、Segcore、Knowhere、混合过滤与一致性,并用 Qdrant、LanceDB、pgvector 对照选型。
存储工程视角的向量检索入门:度量、暴力基线、LSH/HNSW/量化直觉与 FAISS 选型;算法深度与生产引擎内核外链到 db-frontier 与 vector-engine。
按 Redis OSS 7.4/8.x 源码拆解 aeEventLoop 文件/时间事件、beforeSleep 钩子与客户端 querybuf/reply 路径,并精确说明 IO threads 只卸载读写与解析、命令仍在主线程执行。
从 evict.c 拆解 volatile/allkeys 与 LRU/LFU/random/ttl 策略矩阵、24 位时钟近似 LRU、淘汰池采样,并对照算法篇真 LRU 与 MEMORY DOCTOR 信号。
定位 Lucene 9.x/10.x 库内核与 Elasticsearch 8.x 服务层相对 architecture/42、storage/29、向量引擎与 PG GIN 的分工;以最小索引故事建立坐标系,交代倒排索引学术谱系与 18 篇路线图。
从 Robertson & Zaragoza (2009) 的 BM25 公式出发,拆解 Lucene BM25Similarity 如何把 TF 饱和、文档长度归一与 IDF 落到 postings 与 norms;对照 TF-IDF 工程差异,并划定与学习排序的生产边界。
钉住 SQLite table b-tree 与 index b-tree 的字节布局差异、cell pointer array 如何做到逻辑有序物理可乱序、overflow 阈值与 balance() 分裂/合并触发条件;源码以 btree.c 函数签名为准,学术锚点是 Bayer & McCreight 1972。
定位 TiKV 7.x/8.x 在 RocksDB 单机 LSM、Raft 协议与 HTAP 范式之间补的那一层:TiDB、TiKV、PD、TiFlash 四组件各自的抽象边界,以及本系列 18 篇的读法。
拆解一次 TiKV 写请求经 propose、append、commit、apply 四个阶段落到 RocksDB 的路径,钉住 raft 线程与 apply 线程的异步边界;不编造未实测的 QPS 数字。
从 fsync 语义、写屏障与电源故障到静默损坏与端到端校验——建立存储栈各层丢失/损坏认知;算法选型见 checksum 篇,ZFS 实现见 zfs-integrity 篇。
ZFS 三层架构、Merkle 端到端校验、CoW、ARC、RAID-Z 与运维;算法选型与 field study 口径见 checksum / data-integrity 篇。
数据库存储引擎通常自己管理一块内存,维护 Buffer Pool,用 read()/pread() 把磁盘页加载进来,再用 LRU 或 Clock 算法做淘汰。这套方案灵活、可控,但代码量大、调优参数多,且引入了用户态到内核态的数据拷贝。有没有一种方式,让操作系统直接把磁盘文件映射到进程地址空间,数据库只管读指针,不管…
深入分析存储系统中的数据完整性保障——CRC32C、xxHash、SHA-256 的性能对比,静默数据损坏的检测与防护,端到端校验架构设计
从 L0 重叠与 L1+ 不重叠不变式、Size Ratio 与 base_level 动态计算,到 LevelCompactionPicker 如何选 L0→Lbase 与 Intra-L0;三种放大与 storage/31 衔接,exp10 用 db_bench stats 观察层级分布。
对照 Universal/FIFO/TTL compaction 策略,从 GetWriteStallConditionAndCause 与 WriteController 的 Stop/Delay token,到 DBImpl::DelayWrite 状态机、LOG 与 GetProperty 判读;exp11 用极低 L0 阈值触发 stall。
O_DIRECT 的语义、对齐约束、文件系统坑与何时该/不该绕过 Page Cache;io_uring 组合路径见 #79。
拆解 O_DIRECT 对齐约束与 io_uring 固定缓冲区(IORING_REGISTER_BUFFERS)如何叠加;对比 buffered/Direct I/O 的 io_uring 实测 IOPS,给出数据库与块设备场景选型。
在 distributed/54 的方法论之上,钉住 FoundationDB 如何用 Flow、模拟网络/磁盘/时钟、种子重放与 Buggify 覆盖角色恢复路径;不复述 DST 通识,只写工程接口与测试落点。
拆解 Iceberg 的四层元数据:catalog 指针 → metadata.json → manifest list(snapshot)→ manifest file → data file。讲清 snapshot 与 manifest 里的分区数据和列级 stats(lower/upper bound、null/value count)如何让一次查询不 list 目录就收敛到文件集合,并给出表规范 V1/V2/V3 的版本边界。基于 pyiceberg 0.11.1 真实建表逐层 dump。
WAL 是数据库持久性的基石,ARIES 是工业界公认最完备的崩溃恢复协议。本文从 WAL 三条规则出发,逐步拆解 ARIES 的 Analysis-Redo-Undo 三阶段,结合 InnoDB 实现分析恢复全流程。
定位文档库默认引擎 WiredTiger 相对 PG/InnoDB/SQLite/RocksDB 的生态位;钉住 Session→Cache→Reconcile→HS→Checkpoint 主线、站内分工与 17 篇阅读路线,并以 Berenson 隔离词汇与 Durable History 为学术/工程锚点。
钉住 WiredTiger 的 Connection 独占实例、Session 单线程与单事务、Cursor 归属会话等不变量;对照 MongoDB 连接池心智,并为后续 Cache/Eviction 章节提供 API 入口。
拆解 WiredTiger Cache 的 clean/dirty 计量、WT_REF/WT_PAGE 按需加载,以及 update chain / insert list 如何挂在页上;说明 cache_size 不计 session/cursor,并为 Eviction 章节铺垫 dirty 必须先 reconcile。
拆解 WiredTiger Eviction 的 server/worker/队列、target/trigger 阈值,以及 dirty eviction 经 reconciliation 把最新值写入用户表、旧版本写入 History Store;说明应用线程被迫协助驱逐的条件。
拆解 WiredTiger row-store B-Tree 的 WT_BTREE/WT_REF 结构,以及叶页上 WT_INSERT skiplist 与 WT_UPDATE 链如何承载插入与多版本;说明未提交更新不进磁盘镜像,为 Reconciliation 与 History Store 铺垫。
拆解 WiredTiger reconciliation:把 in-memory 页转为 on-disk image、按 leaf_page_max 与 split_pct 分裂,并在用户表 reconcile 时选出最新已提交值、将更旧更新写入 History Store;锚定 wiki 与 src/reconcile/。
拆解 WiredTiger 应用时间戳(oldest/stable/pinned)、事务 read/commit timestamp、快照隔离下的可见性检查,以及 prepared 的 prepare/durable 边界;为 History Store 与 Rollback-to-Stable 提供时间轴。
拆解 MongoDB WiredTiger 如何把旧版本挪到 History Store(WiredTigerHS.wt),在 reconciliation / eviction 后仍服务快照读;对照 PostgreSQL 堆版本与 InnoDB undo,并交代 Lookaside 到 Durable History 的工程分叉。
拆解 WiredTiger checkpoint 算法:先借 eviction 减压,再按用户表→History Store→元数据顺序 reconcile 并原子切换;说明 checkpoint generation 与 eviction 的可见性约束,以及与 journal 的耐久分工。
拆解 WiredTiger write-ahead log:WiredTigerLog 文件、LSN、slot 无锁写入、checkpoint 之后自动删日志,以及崩溃恢复时从最近 checkpoint 回放;并标出与 MongoDB journaling 配置的边界。
拆解 WiredTiger RTS:按 durable/stable 与 recovery checkpoint snapshot 判定不稳定更新,读 History Store 写回用户表,并在启停与 API 路径上独占运行;说明与 prepared、checkpoint、eviction 的交互边界。
拆解 WiredTiger Block Manager:块与 address cookie、无覆盖写入、checkpoint 的 alloc/avail/discard extent list,以及 allocation_size 与 checksum;压缩只作入口,不写各 codec 手册。
拆解 WiredTiger compaction 如何把文件尾块前移并依赖多次 checkpoint 才能截断文件;说明 backup cursor 期间禁用日志删除与预分配的契约,以及 background compaction 的节流条件。
对照 MongoDB 手册与本系列机制:cacheSizeGB、约 60s checkpoint、journal 与 minSnapshotHistoryWindowInSeconds 如何映射到 WT Cache/Checkpoint/Logging/HS;复制集与分片只作边界,不展开。
给出 WiredTigerHS.wt 膨胀、cache dirty/eviction 压力、长游标与备份窗口的可复现排查口径;强调禁止手工删除 HS/日志文件,并把现象映射回本系列机制篇。
按缓冲池、写前日志、MVCC 落点、脏页写出与故障模式对照 PostgreSQL、InnoDB、RocksDB 与 WiredTiger;只谈机制与代价,不写未实测延迟排名。
给出相对 PG/InnoDB/SQLite/RocksDB 的选型决策树,回收 History Store 与 cache 公平性等开放问题,并收束 WiredTiger 内核 17 篇阅读地图。
补齐文档库默认引擎内核层:从 Connection/Session、Cache/Eviction、B-Tree update chain、Reconciliation 到 Timestamps、History Store、Checkpoint/Journal 与 Rollback-to-Stable,并以 MongoDB 嵌入边界与 PG/InnoDB/RocksDB 对照收束。
本文已迁入 WiredTiger 内核系列第 08 篇,请改读新路径。
定位单文件嵌入式行存在服务器行存与 LSM 嵌入 KV 之间的生态位;钉住 SQLite 架构约束、站内分工与 17 篇阅读路线,并以 Bayer/McCreight、官方 file format、PVLDB 2022 为学术锚点。
拆解 SQLite 单文件格式:100 字节 database header 与 B-Tree 页面头的逐字段布局,用本机 3.53.2 CLI 实测 hexdump 核对 magic、page size、页类型标志,并钉住 file format 官方规范与 Bayer/McCreight 谱系。
拆解 Pager 作为 B-Tree 与操作系统文件之间的契约层:page cache 命中/未命中路径、脏页生命周期与提交前的可回滚保证,并与 PG shared_buffers、InnoDB Buffer Pool 的跨进程共享模型对照。
钉住 SQLite 把 SQL 编译成 bytecode、由 sqlite3_step 驱动虚拟机执行的路径:指令格式、寄存器、B-Tree 游标与 ResultRow;用本机 3.53.2 EXPLAIN 走通一次点查,编译管线细节留给第 6 篇。
拆开 sqlite3_prepare_v2 内部如何把 SQL 文本经词法、语法、名字解析、查询规划变成第 5 篇执行的 bytecode;用本机 3.53.2 的 EXPLAIN QUERY PLAN 钉住三种访问路径形态,并交代 schema cookie 触发 reprepare 的机制,规划算法细节留给第 11 篇。
钉住 SQLite 默认的原子提交机制:写前把原页拷进 -journal、DELETE/TRUNCATE/PERSIST 三种提交点如何实现、cache spill 何时把 journal 变成真正的 hot journal;用本机 3.53.2 实测崩溃恢复全过程,WAL 对照留给第 8 篇。
钉住 SQLite WAL 模式如何反转 rollback journal 的读写关系:原始内容留在主文件、新内容追加到 -wal,checkpoint 才把帧搬回主文件;用本机 3.53.2 实测 journal_mode=WAL 切换与 passive/truncate checkpoint 的真实帧数,读放大与 checkpoint 频率的取舍留作开放问题。
钉住官方 File Locking And Concurrency 文档定义的 UNLOCKED/SHARED/RESERVED/PENDING/EXCLUSIVE 五态锁阶梯:谁能与谁共存、PENDING 如何防写者饿死、Pager 为何只跟踪四态;用本机 3.53.2 真实双连接冲突实验验证,shared cache 与 WAL 差异只点边界,留给第 8、10 篇。
拆解 BEGIN DEFERRED/IMMEDIATE/EXCLUSIVE 三种模式的取锁时机差异,对照 Berenson et al. SIGMOD 1995 的隔离词汇与官方 Isolation In SQLite 文档;说明单写者约束下 WAL 快照为何天然回避 write skew,并用本机 3.53.2 实测三种 BEGIN 均可提交。
钉住 EXPLAIN QUERY PLAN 的 SEARCH/SCAN 判定、ANALYZE 写入 sqlite_stat1/stat4 的具体语义,以及没有统计时 SQLite 用什么默认猜测(表大小猜一百万行、重复度猜 10);对照官方 N3 join 排序算法与 PG 式穷举代价优化器的复杂度边界,本机 3.53.2 实测覆盖两条 EQP 路径。
钉住 covering index 消除的具体开销:第 4 篇 index b-tree 只存 key+rowid,命中后仍要回表这一次二次查找;用本机 3.53.2 实测 SELECT 列是否全部落在索引内如何改变 EQP 输出,并区分语句级自动索引与 sqlite_autoindex_* 约束索引这两个常被混淆的概念。
钉住 ATTACH DATABASE 的命名空间规则、super-journal 如何让跨文件事务在 rollback journal 模式下保持原子,以及官方文档明确写明的一条反常识边界:main 库或任一 attached 库切到 WAL 后,跨库事务只在单文件粒度原子,崩溃中间态可能只改了一部分文件;本机 3.53.2 实测跨库 JOIN、跨库事务提交与 DETACH 锁冲突。
拆解 PRAGMA integrity_check/quick_check 的检查范围与复杂度差异,对照官方 How To Corrupt Your Database Files 列出的四类常见损坏来源;用本机 3.53.2 实测一个刻意损坏的数据库,比较 .recover 与 .dump 在数据丢失时的真实行为差异,钉住“修复=尽力抢救,不是万能恢复”的边界。
拆解 sqlite3_backup_init/step/finish 与 CLI .backup 如何在不停机的前提下拿到一致快照;用本机 3.53.2 实测 .backup 后备份库 count(*)=3、integrity_check=ok,并实测对比:在写事务打开期间用 cp 拷贝主文件,物理文件已经比头部记录的逻辑页数更大。
用进程模型、日志、锁与缓冲池四轴对照 SQLite 与 PostgreSQL / InnoDB:说明嵌入式单文件如何删掉服务器层,以及同名 WAL、隔离、缓存概念为何不能平移运维经验;不写跨库吞吐排名。
用部署形态、写并发、查询形态与持久化需求收束 SQLite / PostgreSQL·InnoDB / DuckDB / RocksDB 选型;给出站内阅读地图、全系列学术谱系与开放问题,标志 SQLite 内核系列完成。
补齐嵌入式行存内核层:从单文件格式、Pager/B-Tree、VDBE 到 Rollback Journal/WAL、锁状态机与计划器,并以 PG/InnoDB、DuckDB、RocksDB 对照收束;承接 sqlite-billion-rows 性能叙事。
以 SIGMOD 2021 为锚点,厘清 FoundationDB 控制面与数据面角色分工,说明一次事务穿过 Proxy、Sequencer、Resolver、TLog、Storage 的路径,并与站内 distributed/39、tikv-htap 划清边界。
钉住 FoundationDB 客户端事务契约:读写缓冲、冲突范围、@transactional 自动重试,以及 5 秒上限如何约束应用设计——机制证明留给第 8–9 篇。
说明 Coordinators 如何用磁盘 Paxos 持久化事务系统配置、Cluster Controller 如何招募角色,并划清『配置共识』与『用户 mutation 共识』的边界。
拆解 FoundationDB 7.x 中 Grv Proxy 与 Commit Proxy 的分工:如何发放 read version、如何编排提交,以及批处理与 Ratekeeper 如何保护 Sequencer。
用一张读写总图串联 FoundationDB 各角色,标明哪些可水平扩展、哪些是逻辑单例,并与 TiKV 多组件分离作机制对照。
说明 Sequencer 如何分配 read version 与 commit version、为何是逻辑单点而非无高可用,以及世代恢复如何与版本推进衔接。
钉住 FoundationDB 一次写事务的提交路径:Client 经 Commit Proxy 取 commit version、Resolver 做 OCC、TLog 多数持久化后才向客户端返回成功;并划清「提交成功」与「Storage Server 可读」之间的边界。
拆解 FoundationDB Resolver 如何用 read/write conflict ranges 做乐观并发控制:冲突窗口落在 read version 与 commit version 之间,客户端自动重试;并与 TiKV Percolator 快照隔离对照机制差异,不写无实测性能结论。
说明 FoundationDB 如何用 Sequencer 版本把 OCC+MVCC 提升到严格可串行化,区分 serialization order 与实时顺序;论证 5 秒事务上限如何约束冲突窗口与恢复日志量,并点明高冲突下的开放问题。
拆解 FoundationDB Transaction Log(TLog)如何作为分布式 WAL:按复制策略同步 durable 后 Commit Proxy 才返回成功;说明 durable version、known committed version 与恢复版本的关系,以及 Storage Server 异步消费如何离开提交临界路径。
说明 FoundationDB Storage Server 如何托管 shard、按版本服务读、从 TLog 异步拉日志并参与迁移;强调读路径直达 Storage、不经过 Commit Proxy 提交流水线,以及与 Data Distributor 的边界。
梳理 FoundationDB 存储引擎谱系:SIGMOD 2021 时代的 SQLite 派生 SSD Engine 如何把 SQL 剥掉只留 B-Tree,再到 7.x 的 Redwood 多版本前缀压缩 B-Tree;划清无本地事务 WAL 的系统边界,并与 RocksDB LSM 对照机制而非性能排名。
按 SIGMOD 2021 钉住 FoundationDB 把失败收敛到同一条恢复路径:Sequencer 锁定 Coordinator、停止旧 LogServer、招募新 Proxy/Resolver/TLog、确定 RV/PEV,并说明写暂停、读边界与旧角色隔离。
拆解 Record Layer 如何在 FDB 严格可串行化 KV 上用 Protocol Buffers、Tuple/Subspace 与同事务索引维护实现记录存储;CloudKit 只引用 SIGMOD 2019 等可核实来源。
按 Unbundled 角色给出可观测的资源画像、分片热点成因与备份/DR 边界;只引用官方 Administration / Backup 文档与 SIGMOD 2021 机制,不写无来源容量公式。
用症状到机制的决策树排查四类高频问题:事务超时、冲突风暴、Sequencer 切换写暂停、Storage 落后于 TLog;回链 OCC、恢复与运维篇,不重复调参手册。
用一致性级别、事务模型与 Layer 边界收束 FoundationDB / TiKV / etcd 选型;给出站内阅读地图、全系列学术谱系与开放问题,标志 FoundationDB 内核系列完成。
补齐 FoundationDB 选型叙事与生产内核之间的一层:拆解 Proxy、Sequencer、Resolver、TLog、Storage Server 的 Unbundled 写路径,严格可串行化、Redwood 与确定性模拟,并以 Record Layer 和 TiKV/etcd 对照收束。
拆解 TiKV 的 user key + start_ts/commit_ts 编码规则与 default/lock/write 三 CF 分工,并说明为什么这套 MVCC 与 RocksDB Snapshot 的 sequence 号是两层完全不同的机制。
拆解 TiKV Region 的 range、RegionEpoch(conf_ver/version)、peer/leader 三个核心字段,纠正常见误解;split 只给直觉,机制留给第 8 篇。
拆解 TiKV 的 Multi-Raft 架构:为什么每个 Region 是独立的 Raft 组,与 etcd 单 Raft 组对照差在哪;跨 Region 事务代价作为开放问题收束,不重写 Raft 协议本身。
拆解 TiKV 落后副本如何靠 Raft Snapshot 追赶进度、Raft 日志如何在 apply 完成后安全截断(log GC),并简述 witness/learner 副本形态;TiFlash Learner 的列存链路留给第 14 篇。
拆解 PD 如何靠 store/region 心跳建立集群视图,用 balance-leader/balance-region/hot-region 等调度器算分,生成 transfer-leader、move-peer 等 Operator,再通过下一次心跳的响应把算子'建议'给 Region Leader;对照 Spanner placement driver 与 CockroachDB 去中心化再平衡的架构分歧。
拆解 TiKV Region 何时触发 size/key-count 分裂、如何用 BatchSplit 在不拷贝数据的前提下切分 RocksDB key range;PrepareMerge/CommitMerge 两阶段合并;Load Base Split 与 PD hot-region-scheduler 两层热点机制的分工,并对齐 distributed/27 的负载分裂叙事。
拆解 PD 的 TSO 如何用 46 位物理毫秒 + 18 位逻辑计数器分配全局单调时间戳,PD leader 如何靠 etcd 时间窗口做故障恢复、客户端如何批量取号;用一句话对照 Spanner TrueTime 的硬件不确定区间路线与 Milvus 的 GuaranteeTs 用法。
拆解 TiKV 如何把 Percolator 论文的 data/lock/write 三列映射到 RocksDB 的 CF_DEFAULT/CF_LOCK/CF_WRITE,key 用 memcomparable + 位反转时间戳编码;说明 short value、Rollback 记录、Lock 类型 write 等论文之外的工程补丁,以及 Async Commit 如何压缩提交路径;对照 distributed/30 的论文模型与 rocksdb/14 的单机事务 API 分层。
拆解 TiKV 悲观锁的写入路径、in-memory 优化、TTL 与心跳续期,死锁检测器的中心化选举与 wait-for-graph 检测边界,以及 GC/客户端两条 ResolveLock 路径;用锁的实际存在形态纠正「TiKV 是无锁架构」这一常见误解。
拆解 TiKV Coprocessor 如何接收 TiDB 下发的 DAG 请求、在 Region snapshot 上跑批量执行器;划清行存下推与 query-engine 系列 MPP 向量化的边界,不重讲 MPP。
只钉 TiDB SQL 层与 TiKV 之间的边界:Parser/Planner 之后的计划如何被切成按 Region 分组的 Coprocessor 任务、如何重试 Region 路由错误;不重写优化器与执行器全书。
拆解 TiFlash 如何以 Raft Learner 身份接收日志、把行存变更重放进 DeltaTree 列存引擎;锚定 Huang et al. VLDB 2020,并与 columnar-engine 系列划清分工,不重讲列存执行引擎全书。
把 TiFlash 的 ReadIndex 确认机制正式定义为 safe-ts,量化分析读的可见时延来源;回链 db-frontier/12 的 HTAP 三档新鲜度坐标,说明 TiDB+TiFlash 具体落在哪一档、为什么。
对照 CockroachDB 的 Range/Leaseholder/Raft leader 分层与 Percolator 式事务,找出 TiKV/TiDB 分离部署与 CockroachDB 单进程一体化的关键工程差异;OceanBase 一段边界,回链 distributed/39 选型对照。
用官方 Grafana 指标与系统表钉住五类高频生产故障的根因链:Region 过多、写/读热点、PD TSO 抖动、悲观锁冲突、raftstore apply 积压;给出症状到机制的决策树,不重复调参手册。
给出分布式强一致 KV 的扩展决策树:数据规模、事务需求、新鲜度要求如何在 TiKV、etcd、FoundationDB、单机 RocksDB、湖仓+CDC 之间做选型;回链全系列 18 篇,收束学术谱系与开放问题,标志系列完成。
补齐 RocksDB 单 Region、Raft 协议与 HTAP 范式之间的工程链路:以 TiKV 7.x/8.x 拆解 Region、Multi-Raft、raftstore、PD/TSO 与 Percolator 事务,并以 TiFlash Learner 收束新鲜度;CockroachDB 对照与选型。
LSM-Tree 的核心设计是把随机写转换为顺序写,但这个转换不是免费的。写入经过 MemTable 刷盘、再经过多次 Compaction 合并,每一字节的用户数据在磁盘上可能被反复读写数十次。读取一个 key 时,最坏情况下需要逐层搜索,直到命中或遍历全部层级。与此同时,旧版本数据和墓碑标记占用的额外空间,在 Co…
拆解 Lucene Index/Document/Field 与段内 docID 分配;说明 indexed、stored、docValues 三组正交开关;对照正排与倒排访问路径,为 Analyzer 与 postings 篇奠基。
拆解 Lucene Analyzer 的 CharFilter→Tokenizer→TokenFilter 管线与 TokenStream 契约;说明分词如何影响写放大与词典规模;中文分词只谈接口与运维代价,不展开 NLP 算法教程。
说明 Lucene 段内 Terms 词典如何用 FST 做前缀共享与内存映射;介绍 TermsEnum seek 与字段迭代;与 PostgreSQL GIN Entry Tree 对照一句,为 postings 定位奠基。
拆解 Lucene PostingsFormat 中 freqs/positions/offsets/payloads 各层语义;说明块编码、skip list 与 impacts 如何服务相交剪枝;解释短语查询为何依赖 positions。
拆解 Lucene IndexWriter 的 RAM 缓冲、flush 出段与 DirectoryReader.open(IndexWriter) 近实时语义;说明 Searcher 刷新与「刚写入即可搜」在库层与 ES refresh 层各自保证什么。
说明 Lucene TieredMergePolicy 如何把多段收成更少大段、软删除如何通过 liveDocs 维持可见性并延迟空间回收,以及 force merge 在 Elasticsearch 中的代价与适用边界。
从 BooleanQuery 的 SHOULD/MUST 语义出发,拆解 Lucene BooleanScorer、两阶段迭代(近似+验证)、Collector 与 TopDocs 截断,以及 galloping 相交与 postings impacts 跳跃剪枝的关系。
说明 Lucene DocValues 的列式访问模型如何服务排序、聚合与脚本,stored fields 的随机取原文代价,以及 Elasticsearch 聚合管线对 DocValues 的依赖——为第 14 篇预埋。
用保证矩阵拆解 Elasticsearch 8.x 的 refresh、flush、translog 各自承诺什么:可搜窗口、磁盘持久化、崩溃恢复;对照 refresh_interval 与 wait_for,并在单节点 8.15 上实测写入可见性。
沿 Elasticsearch 8.x 聚合执行路径说明为何 terms/date histogram 走 doc values 而非倒排,协调节点如何合并分片桶;并以 dynamic mapping 字段爆炸解释 circuit breaker 与排障入口。
只谈 Elasticsearch 8.x / Lucene 上 BM25 与 kNN 的组合接口与段内共存代价,ANN 算法与专用向量引擎细节外链 vector-engine 与 db-frontier/08;指出倒排与向量同 Segment 生命周期尚未统一的开放问题。
对照 Elasticsearch 8.x 与 OpenSearch 的许可与发行分叉,说明二者与 Solr 如何共享 Lucene 段模型;Solr 仅作边界一句,内核机制仍回链本系列 01–15 篇。
用症状到机制的决策树覆盖 circuit breaker、refresh 过频、大字段、分片过多与慢查询 explain,逐条回链本系列 Lucene 段与 ES NRT 篇章;不含未跑集群 benchmark。
给出 ES/OpenSearch、PostgreSQL GIN、ClickHouse 全文、专用向量引擎与「仅日志检索」的扩展决策树;回链 observability/08 与 llm-infra RAG,收束本系列 18 篇开放问题。
补齐搜索架构叙事与 RAG/向量引擎之间的全文检索内核层:以 Lucene 9.x/10.x 拆解 Analyzer、FST、postings、BM25 与 IndexWriter,并以 Elasticsearch 8.x 拆解分片、refresh/translog 与查询路径;OpenSearch 对照与选型收束。
定位进程内 HashMap、Memcached、Redis 与 RocksDB 嵌入 KV 在内存缓存栈中的生态位;划分与 architecture/17、storage/66、linux/redis-source 的分工,并给出本系列 16 篇阅读地图。
拆解 Redis 7.4/8.x 的 redisObject 多态层与 SDS 二进制安全字符串:type/encoding/refcount 如何分工、字符串四种编码的升级路径、OBJECT ENCODING 能读到什么,以及紧凑表示与统一抽象之间的工程争论。
从 Redis 7.4/8.x 的 dict 源码拆解链式哈希、双表渐进 rehash、rehashidx 步进与 DICT_RESIZE_AVOID 在 fork 期的行为,并对照站内哈希表内部文章说明与教科书一次性扩容的差异。
Redis 7.4/8.x 如何用 listpack、quicklist、intset 为小集合省内存:ziplist 退场原因、各 type 的 encoding 升级阈值与配置项默认值,以及紧凑表示在 CPU 与内存之间的工程争论。
Redis 7.4/8.x 有序集合的双结构 skiplist+dict 与小 listpack 编码、Pugh 跳表参数如何落地,以及 Stream 的 rax+listpack 存储与 consumer group / PEL 的最小必要语义——不扩写消息队列教科书。
拆解 Redis 7.4 的 TTL 机制:expires 辅助表、lookup 路径惰性删除、activeExpireCycle 自适应采样,以及 lazyfree 异步释放大对象对延迟的影响。
从 rdb.c 拆解 SAVE/BGSAVE 的 fork 写时复制语义、子进程快照路径,以及 REDIS 魔数与 opcode 锚定的 RDB 格式边界。
从 aof.c 拆解 AOF 多段清单、feedAppendOnlyFile 写路径、后台 rewrite 与 appendfsync always/everysec/no 各自的丢失窗口及 fsync 失败语义。
说明 Redis 7.4 默认开启的 RDB preamble + INCR AOF 如何组合恢复路径,结合 fsyncgate 与数据完整性给出 appendfsync 与混合模式的配置决策树及耐久争论边界。
按 Redis 7.4/8.x replication.c 拆解 PSYNC 部分重同步、环形 replication backlog 与 replica-read-only 语义,对照异步复制与读己之写(read-your-writes)的工程边界,说明副本滞后如何改写 Cache-Aside 一致性假设。
按 Redis Cluster Spec 与 cluster.c 拆解 CRC16 取模 16384 的 hash slot、MOVED 与 ASK 重定向语义,对照客户端一致性哈希,说明 hash tag 下同槽多 key 原子性边界与迁移期 TRYAGAIN。
对照 Facebook Scaling Memcache(NSDI'13)与 Memcached 多线程+slab 分配器,拆解 Redis 多态编码与持久化带来的角色差异,说明在 Cache-Aside 场景下何时应选纯缓存而非数据结构服务器。
按 Redis Latency Monitoring 与 INFO/SLOWLOG 信号,建立大 key、fork 延迟、阻塞命令、内存碎片四类故障的排查决策树;给出可在本机 redis-server 上执行的复现命令清单,不粘贴伪造输出。
用决策树收束 standalone、Sentinel、Cluster 与纯缓存分工,简述 Valkey ABI 社区分叉与 Redis 模块边界,列出多线程与持久化争论,并给出回到本系列、architecture/17 与 RocksDB 的阅读地图以闭合全系列。
补齐内存 KV / 缓存服务器内核层:从 ae 事件循环与 redisObject 多态编码,到 TTL/maxmemory 近似淘汰、RDB/AOF 持久化语义,再到复制、Cluster hash slot 与 Memcached 对照。
行存 vs 列存的带宽、压缩与向量化三角;ClickHouse Server 进程模型、线程池与 MergeTree 引擎家族地图;src/Storages 与 src/Processors 源码入口。对照 PG 行存与 LSM 写优化路径,版本锚定 ClickHouse 24.x LTS。
ClickHouse MergeTree Part 目录结构:columns.txt、checksums.txt、.bin、.mrk2、primary.idx 语义,Granule 与 Mark 的定位作用,Wide/Compact 布局与 MergeTreeDataPart 源码入口。版本锚定 24.x LTS。
ClickHouse 列压缩:LZ4、ZSTD、Delta、DoubleDelta、Gorilla 时序编码与列类型关系;CODEC 链顺序、LowCardinality 与 PG TOAST 对照。压缩比须本机实测,本文不编造倍数。
ClickHouse Block 列向量 batch、IProcessor Pipeline 与 filter/project/aggregate 向量实现;对照 PostgreSQL 火山模型 ExecProcNode。源码入口 src/Processors、src/Columns。24.x LTS。
MergeTree SELECT 读路径:Mark Range 定位 Granule、PREWHERE 与 WHERE、Part 级并行与 max_threads。EXPLAIN indexes=1 解读方法。24.x LTS,无伪造 EXPLAIN 输出。
MergeTree 后台 merge 触发与 selector、ReplacingMergeTree/CollapsingMergeTree 语义、ALTER UPDATE/DELETE mutation 异步路径与危害。对照 LSM compaction。源码 MergeTreeDataMergerMutator。24.x LTS。
ClickHouse PRIMARY KEY 排序键稀疏索引语义、Data Skipping Index(minmax/set/bloom_filter)与 Mark Range 协同;对照 PostgreSQL B-Tree。24.x LTS。
主选 ClickHouse 拆解 MergeTree 存储格式、向量化执行与分布式协调;DuckDB 作为嵌入式 OLAP 对照。覆盖列存文件布局、merge 机制、跳数索引与生产故障模式,面向数据平台工程师与从 PG/MySQL 转 OLAP 的 DBA。
从 RocksDB 内核侧补全 Flink KeyGroup 前缀与增量 checkpoint SST 上传机制,对照 TiKV Region 引擎与 Kafka Streams changelog 容错;不重复 stream/12 作业侧全文,给出 Docker 复现步骤而不伪造 checkpoint 指标。
从 log::Writer 的 32KB Block 分片 record、WriteBatch 二进制布局,到 DBImpl::WriteImpl 中 Group Commit 与 sync/fsync 语义,钉住写路径第一步:先 WAL 后 MemTable 的提交顺序与原子性边界。
从 SkipList MemTableRep、MemTableList 的 immutable 双缓冲队列,到 FlushJob::WriteLevel0Table 与 VersionSet 安装 L0 文件,闭合 WAL 之后 MemTable 如何变成 SST,并对照 lsm-tree DIY 实现。
从 BlockBasedTable 的 Data/Index/Filter Block 与 Footer 定界,到 VersionEdit 增量记录与 VersionSet::LogAndApply 如何维护 LSM 快照,并用 sst_dump 对照磁盘布局。
从 RocksDB 3.0 引入的 Column Family 出发,拆解共享 WAL、独立 MemTable/SST/Version 链、`ColumnFamilyHandle` 生命周期与 DBOptions/ColumnFamilyOptions 分层;并对照 Flink 多 state 变量到 CF 的映射边界。
拆解 Checkpoint 同盘硬链接快照、BackupEngine 增量备份目录布局、SstFileWriter 离线建表与 IngestExternalFile 的 sequence 分配及 write stall 边界——对接 Flink 增量 checkpoint 与 bulk load 运维路径。
补全存储引擎三角最后一角:从 LevelDB 基线与 RocksDB 架构演进,到 WAL/MemTable/SST 写路径、Get/Iterator 读路径、Leveled/Universal compaction 与 write stall,再到 Column Family、事务、Checkpoint 与 Flink/TiKV 嵌入对照。
以 LevelDB 1.23 为对照基线:拆解单后台 compaction 线程、无 Column Family 的 DBImpl 结构,以及 Write 队列 group commit、Get 层级查找与 SST/MANIFEST 最小语义,为 RocksDB 9.x diff 地图打底。
从 DBImpl::GetImpl 层级查找路径出发,拆解 LookupKey、sequence number 编码、SuperVersion 引用与 Snapshot 可见性边界;对照 PostgreSQL MVCC 的 txn id 语义差异。
沿 DBImpl::NewInternalIterator 拆解 InternalIterator 栈、MergeIterator 多路归并与 LevelIterator;说明 DBIter 上 tombstone/range del 的可见性裁剪及与 compaction 归并堆的同构关系。
对照 WriteBatch 原子性与 Snapshot MVCC,拆解 TransactionDB 悲观锁、OptimisticTransactionDB 提交时冲突检测、WritePrepared 的 prepare/commit 与 CommitCache 边界;TiKV 分布式事务仅作 B 级前瞻,不替代 Percolator 正文。
闭合存储引擎三角的最后一角:对照 PG B-Tree 与列存 scan,定位 LSM 写优化引擎在 TiKV、Flink、Kafka Streams、ClickHouse Embedded 中的嵌入方式,并划分本系列与 lsm-tree DIY、storage/31–32、stream/12 的分工边界。
对照 LevelDB 1.23,用 diff 表与源码路径梳理 RocksDB 9.x 的多线程 flush/compaction、Column Family、RateLimiter、Direct IO、Statistics 与并发 MemTable 写,建立后续读 db_impl 子文件的坐标系。
沿 TableCache 与 BlockBasedTable 读路径说明 Block Cache、Table Cache、Full/Ribbon Filter 与 Partitioned Index 如何裁剪点查 I/O;读放大度量与调参边界引用 storage/68,不重复全文推导。
从 CompactionJob 的 Prepare/Run/Install 与 subcompaction 并行,到 Env 高低优先级线程池、MaybeScheduleFlushOrCompaction 调度,以及 GenericRateLimiter 的 kWritesOnly 与 DelayWrite 的争抢关系;exp12 三路中位数对比方法论。
用 GetProperty 与 LOG 钉住 L0 堆积、compaction 落后、Block Cache 未命中与 ENOSPC write stall 四类生产故障;交叉引用 storage/76 磁盘耗尽链,给出 db_bench 复现步骤而不伪造 stats 数字。
用决策树收束 RocksDB 与 InnoDB、列存、湖仓的适用边界;给出存储引擎三角 + 数据平台全栈阅读地图,对接 query-engine/18 与 postgresql-kernel,并标注 HTAP/TiKV 续作入口。
Hive 目录式分区表把『表』等同于『一组目录加 metastore 里的分区行』,于是没有原子提交、planning 要 LIST 目录、schema 与分区演进常要重写。本文用这三个硬伤切入,讲清 lakehouse 把表拆成『不可变数据文件 + 可变元数据指针 + catalog』三层后各自解决了什么,并给出全系列的分层地图。
拆 Parquet 的物理结构:file → row group → column chunk → page,footer 里的 FileMetaData(Thrift)与 PAR1 magic。讲清 PLAIN/RLE-bitpacking/字典/DELTA_BINARY_PACKED/BYTE_STREAM_SPLIT 各自压谁,Dremel 的 repetition/definition level 如何表达嵌套,column index/offset index 与 split-block bloom filter 怎样让谓词在读盘前裁掉 page。基于本机 pyarrow 24.0.0 真实 dump footer 与编码。
ORC 用 stripe 而非 row group、用三级统计(file/stripe/row-group index)而非独立 page index、用 PRESENT/DATA 等 stream 而非 page 组织一列。本文按 ORC 规范拆其文件尾(postscript + footer)、stripe 内部结构与 RLEv2 整数编码,并用本机 pyarrow 24.0.0 把同一份 30 万行数据写成 ORC 与 Parquet,对比真实体积与物理布局,最后给出什么场景仍用 ORC。
拆解 Arrow 列式内存布局(validity bitmap + value buffer + offset buffer)、零拷贝从何而来,以及 C Data Interface、IPC、Flight 三层跨边界传递。讲清 Arrow(内存计算格式)与 Parquet(磁盘存储格式)如何分工衔接。含 pyarrow 实测 C Data Interface 同地址零拷贝。
拆解 Parquet 的两层缩减:专用编码(dictionary / RLE / DELTA_BINARY_PACKED / BYTE_STREAM_SPLIT)降熵,再用 zstd/snappy/lz4/gzip 压字节。用 pyarrow 在同一列上实测不同编码+压缩组合的体积与读取耗时(3M 行,7 轮中位数),并与 ClickHouse CODEC 做同思想不同落地的对照。
对象存储不是网络版 POSIX 文件系统。本文用 S3 官方语义钉住四件事:强一致模型的边界、LIST 随对象数线性增长的代价、没有原子 rename(只能 copy+delete)、条件写(If-None-Match/If-Match)对提交协议的意义,并讲清 multipart 与对象不可改写。
目录式分区表(Hive 表)在对象存储上有三处硬伤:并发写部分提交、list planning 太贵、缺快照隔离与原子提交。本文拆开放表格式补上的四件事——原子提交、快照隔离、文件级统计裁剪、schema 与分区演进,并抽象出三家共有的『元数据指针 + 不可变数据文件』骨架。
拆解 Iceberg 的 partition spec 与 transform(identity/bucket[N]/truncate[W]/year/month/day/hour/void):隐藏分区如何让查询不写分区列谓词也能裁剪,分区演进为何不重写历史数据(文件携带所属 spec),以及与 Hive 静/动态分区的本质差异。基于 pyiceberg 0.11.1 真实演进 spec 并观察新旧文件。
Iceberg 在不可变文件上做行级删除的两条路线:copy-on-write(重写整文件)与 merge-on-read(写 delete 文件,读时合并)。讲清 position delete 与 equality delete 的语义、字段与作用域规则,写放大/读放大的取舍,V2 delete file 到 V3 deletion vector(Puffin 承载)的差异与迁移,以及读路径如何把 data file 与 delete 合并出可见行。基于 pyiceberg 0.11.1 实测 CoW 写放大并观察 MoR 回退。
没有数据库进程,Iceberg 怎么在对象存储上做原子提交与并发控制?拆解提交=catalog 对元数据指针做 compare-and-swap,乐观并发如何基于当前 snapshot 生成新 snapshot、冲突按操作类型与隔离级别重试,不同 catalog 的原子性来源(DB 行锁/CAS、REST 后端、对象存储条件写、文件系统 rename),以及 REST Catalog 的 requirements+updates 提交语义。基于 pyiceberg 0.11.1 实测并发冲突与重试。
拆解 Delta Lake 的 _delta_log:有序 JSON commit 里的 add/remove/metaData/protocol/commitInfo/txn 七类 action、每 N 次 parquet checkpoint 与 _last_checkpoint、protocol 版本与 reader/writer table features、deletion vector(Delta 的 merge-on-read)、liquid clustering 与 Z-order,以及乐观并发如何完全基于日志做冲突检测。
拆解 Apache Hudi 的内核:CoW 与 MoR 两种表类型、.hoodie 下的 timeline 与 instant 三态、file group/file slice 的存储模型、base file 与 log file、compaction/clustering/cleaning,以及 bloom/simple/record-level/bucket 索引体系为何让 Hudi 强在 upsert,最后讲 snapshot/read-optimized/incremental 三种查询类型。锚定 Hudi 1.x 官方文档。
把前面 08–13 章拆过的 Iceberg、Delta、Hudi 放在一个坐标系里对照:元数据模型、行级更新、并发控制、引擎生态四维,每维标清口径。再讲两条互通路线——Delta UniForm(写时同步生成 Iceberg/Hudi 元数据)与 Apache XTable(事后转换元数据),以及它们的边界。最后给一棵按写入模式/引擎栈/更新频率展开的选型决策树,不做排名。
拆解 lakehouse catalog 的两件核心职责——表名到当前元数据指针的映射、以及原子提交点;对比 Hive Metastore、Iceberg REST Catalog、JDBC、Hadoop、Glue、Nessie、Gravitino 的锁与原子性语义,单列 Apache Polaris 与 Unity Catalog 开源后的形态、权限模型与 REST 规范互通。
讲清 Iceberg 的 snapshot 过期、回滚与按时间/快照读如何工作;schema evolution 为何按 field ID 而非位置来增删改名重排;以及演进对老数据文件与老 reader 的兼容边界与陷阱,附 PyIceberg 真实实验验证字段映射与时间旅行。
拆解 lakehouse 小文件的根因(频繁提交、流式、过细分区),以及 bin-pack、sort/z-order/clustering、rewrite manifests、expire snapshots、remove orphan files 这套治理操作;讲清 Puffin 中 Theta NDV sketch 对查询 planning 的作用,附 PyIceberg 真实实验对比 compaction 前后文件数与 planning 耗时。
拆解查询引擎读 Iceberg/Delta 的下推链路:partition pruning(manifest)→ file pruning(manifest stats)→ row-group/page pruning(Parquet column index)→ 字典过滤。对照 Trino/Spark/DuckDB/DataFusion/ClickHouse 的能力差异,讲清 planning 在哪一层完成、stats 从哪来,并用本机 pyiceberg + DuckDB 实测裁剪效果。
拆解流式数据进入 Iceberg/Delta/Hudi 的入湖侧机制:Flink/Kafka Connect/Spark sink 如何提交、exactly-once 怎样把引擎 checkpoint 与表格式的原子提交对齐、CDC 如何借 equality delete 与 record index 做 upsert,以及高频提交与小文件、compaction 的拉扯。只讲入湖侧,流处理引擎本身的窗口与状态留给后续。
把前面 19 篇的机制落到工程决策:从 Hive 表迁移到 Iceberg 的三条路径与风险、湖仓 benchmark 的口径陷阱、生产里最常见的故障模式(孤儿文件、元数据膨胀、提交冲突风暴、快照过期误删、catalog 单点),以及一份可执行的运维清单。
湖仓如何承接 AI 负载:embedding/特征/训练样本存湖、按 snapshot 固定数据版本做可复现训练,以及 Parquet 在随机访问和向量检索上的短板。用本机实测对比 Lance 与 Parquet 的顺序扫描与按行随机 take,讲清 Lance 为何为随机访问与向量而生,并划清湖侧存储与专用向量引擎的边界。
拆解 lakehouse 的两层基础:列式文件格式(Parquet/ORC/Arrow)与开放表格式(Iceberg/Delta/Hudi)。讲清没有数据库进程时,如何在对象存储上做 ACID、行级更新、快照与并发,以及 catalog、查询引擎、流式入湖如何拼成可运维的湖仓。面向数据平台工程师与从 OLAP/数仓转型的开发者。
fsync() 返回 EIO 后再调一次为什么会成功?为什么这反而是灾难?从 2018 fsyncgate 到 Linux errseq_t,再到本机内核 6.6 上用 dm-error 单块故障注入的实测,讲清 writeback 失败时脏页被标记 clean、数据静默丢失的真相,以及 PostgreSQL 为什么选择 PANIC。
逐层拆解 ext4、XFS、Btrfs、ZFS 从 70% 填充到 100% 耗尽过程中的块分配退化、碎片化加剧和 ENOSPC 故障模式,给出各文件系统的容量红线、监控阈值和应急恢复方法。
拆解 POSIX 文件锁三大 API 的语义差异,深入 close-any-fd 释放陷阱、OFD 锁机制、F_GETLK 竞态和 NFS 锁恢复的工程真相,给出每种场景的正确选择。
深度复盘 GitLab 2017 数据库事故和 GitHub 2018 存储故障的完整时间线与根因分析,提取跨事故的通用模式,给出构建抗事故存储实践的工程建议。
深入剖析云块存储——分布式块存储架构原理、AWS EBS与阿里云ESSD架构分析、云盘性能规格解读、性能测试方法与选型成本优化
深入剖析云对象存储——S3的11个9持久性实现、元数据-索引-存储三层架构、跨AZ复制策略、存储类别实现差异与成本模型分析
深入剖析计算存储分离——Aurora日志即存储、TiDB的TiKV+TiFlash分层、Snowflake对象存储+缓存、ClickHouse存算分离模式的架构对比与选型指南
深入剖析新硬件技术——ZNS SSD编程模型、CXL内存扩展对缓存层的影响、计算存储设备(CSD)与DPU在存储路径中的角色与工程实践
展望存储技术未来——DNA存储与冷数据归档、光存储、存内计算(PIM)、统一存储接口(文件+对象+块融合)、AI驱动存储管理与技术雷达
深入剖析存储基准测试的方法论——fio 参数解析、filebench 工作负载定义、YCSB 数据库基准、测试陷阱规避与性能回归测试集成
系统梳理 Linux I/O 性能分析工具——iostat、blktrace、BCC/bpftrace、ftrace、perf 的使用方法,以及 I/O 瓶颈排查流程与常见问题模式
深入分析存储多级缓存架构——Page Cache、Buffer Pool、应用缓存的协同设计,缓存淘汰算法对比,缓存穿透/击穿/雪崩的防护策略
深入分析存储写入性能优化——WAL 分组提交、批量写入、Write Buffer 调优、fsync 频率控制、写入限速与写停顿分析
深入分析存储读取性能优化——索引设计、Bloom Filter 调优、块缓存、压缩的 CPU-I/O 权衡、预读策略与读放大测量
全面剖析存储全链路延迟——从应用到硬件的逐层延迟分解、尾延迟分析、延迟热图、biolatency/ext4dist/fileslower 工具实战
深入分析数据持久性的工程计算——故障率模型、多副本与纠删码的持久性推导、相关故障的影响、实际数据丢失案例与持久性计算器实现
全面分析存储系统的静默故障——比特翻转、扇区错误、丢失写、撕裂写、固件 bug 与灰色故障,以及 CERN/Google 的大规模数据损坏研究
系统剖析存储备份策略——全量/差异/增量备份、逻辑 vs 物理备份、WAL 连续归档、备份验证与恢复测试、MySQL 与 PostgreSQL 备份方案实战
全面剖析灾难恢复架构——RPO/RTO 等级设计、同城双活与异地灾备、两地三中心架构、故障切换机制与灾备演练方法论
深入分析数据生命周期管理——热/温/冷/归档数据分层、自动分层策略、对象存储生命周期规则、数据合规与保留策略、存储成本优化
全面剖析存储层的混沌工程实践——磁盘故障注入、慢 I/O 模拟、数据损坏测试、Chaos Mesh IOChaos、LitmusChaos 与慢盘检测算法
系统剖析分布式存储中的数据分片——哈希分片与范围分片的工程权衡、一致性哈希与虚拟节点、跳跃一致性哈希,以及分片策略在实际系统中的应用
深入分析分布式存储中的数据复制——同步/异步/半同步复制、链式复制、多主复制与冲突解决、Quorum 复制的工程实践
深入分析分布式存储的元数据架构——集中式 vs 分布式 vs 无元数据方案、元数据分片与缓存、HDFS NameNode 与 Ceph CRUSH 的工程实践
深入分析分布式存储的数据均衡——扩容缩容时的数据迁移策略、在线重分片、迁移限速与优先级、Ceph PG 自动均衡与 TiKV Region 调度
全面剖析多租户共享存储集群的工程实践——配额管理、QoS 调度、噪音邻居问题、存储级 RBAC、加密隔离与审计日志
深入分析存算分离架构——Shared-Nothing vs Shared-Disk vs Shared-Storage 的工程权衡,Snowflake/Aurora/TiDB 的存算分离实践,本地缓存策略与网络带宽需求
深入分析对象存储的设计哲学——文件系统与对象存储的本质差异、CAP 权衡、最终一致性到强一致性的演进,以及 S3 API 核心操作实战
深入分析 S3 兼容性工程——各厂商兼容差异、对象存储网关架构、跨云数据迁移工具与多云对象存储策略
全面剖析对象存储的性能优化——大文件并发分片、小文件打包策略、列表操作陷阱、CDN 集成、传输加速与基准测试方法论
深入剖析存储系统中的核心编码技术——变长整数、差值编码、字典编码、游程编码、位图编码与位打包,分析各编码方式的空间效率和解码速度
系统对比 LZ4、Zstd、Snappy、Brotli 等压缩算法在存储引擎中的工程实践——压缩率、速度、CPU 开销与选型指南
系统对比 Protobuf、FlatBuffers、Cap'n Proto、MessagePack 等序列化格式——性能基准、零拷贝反序列化、兼容性设计与存储系统中的选型实践
全面剖析静态数据加密的工程实践——块级加密、文件级加密与应用级加密的架构对比,AES-XTS/AES-GCM 选型,密钥层次与轮转,硬件加速性能分析
一条典型的分析查询只访问表中数百列里的三四列,行式存储却把整行数据从磁盘搬进内存,绝大多数字节在读入后立刻被丢弃。列式存储(Columnar Storage)把同一列的值连续存放,查询只需要读取涉及到的列,I/O 量可以降低一到两个数量级。但 I/O 减少只是故事的一半——列式布局还为压缩、向量化执行(Vectoriz…
上一篇我们讨论了列式存储(Columnar Storage)的核心思想:把同一列的数据连续存放,让分析查询只读取需要的列,而不是扫描整行。这个思想落地到具体文件格式时,需要回答一系列工程问题:文件内部怎么组织数据才能同时支持并行读取和列裁剪?同一列的数据用什么编码方式才能最大化压缩率?如何在不读取全部数据的前提下跳过不…
在大数据和分析系统的演进过程中,一个反复出现的性能瓶颈不是计算本身,而是数据在不同系统之间搬运时的序列化(Serialization)与反序列化(Deserialization)开销。Pandas 把数据交给 Spark,Spark 把结果传给 R,R 再把子集喂给 TensorFlow——每一次跨系统传递,数据都要从…
监控系统每秒钟从数万台机器上采集 CPU 使用率、内存占用、磁盘 IOPS、网络流量;物联网(IoT)网关把传感器温度、湿度、振动频率汇聚到云端;金融交易系统以毫秒级粒度记录每一笔报价和成交。这些数据有一个共同特征——每条记录都带有一个时间戳(Timestamp),按时间顺序源源不断地涌入,几乎只追加(Append-O…
数据湖(Data Lake)的核心思想是把海量异构数据以开放格式存储在廉价的对象存储(Object Storage)上,用计算引擎按需查询。Apache Parquet 解决了列式编码(Columnar Encoding)问题,让分析查询的 I/O 效率提升了一个数量级。但 Parquet 只是一个文件格式,它不管事务…
在存储引擎(Storage Engine)的设计谱系中,Bitcask 占据着一个独特而优雅的位置: 它用最简单的数据结构——哈希表(Hash Table)与追加日志(Append-Only Log)—— 组合出了一个在特定工作负载下性能极其出色的键值存储引擎。 本文将从核心思想出发,逐层拆解 Bitcask 的架构、…
从 Column Family、Write Buffer、Block Cache、Compaction、Rate Limiter 到 Direct I/O 和监控,系统拆解 RocksDB 在生产环境中的关键配置与故障模式,并给出 SSD 场景下的配置模板和 db_bench 基准测试方法。
当我们提到"数据库"时,多数人首先想到的是 MySQL、PostgreSQL 这类以独立进程运行的数据库服务器。客户端通过网络协议连接到服务器,服务器管理存储、索引、事务和并发控制。然而,还有一类存储系统以库(Library)的形式直接链接到应用进程中,不需要独立的服务器进程,不需要网络通信,不需要序列化和反序列化——…
数据库系统的架构可以划分为两大层:上层的查询处理层负责解析 SQL、生成执行计划、优化查询;下层的存储引擎(Storage Engine)负责把数据持久化到磁盘,并在需要时高效地把数据取回来。查询处理层决定"做什么",存储引擎决定"怎么存、怎么取"。同一个查询处理层可以对接不同的存储引擎——MySQL 的 InnoDB…
数据库要把数据存到磁盘上,又要以尽可能少的磁盘 I/O 把数据找回来。这个矛盾催生了一系列面向磁盘的索引结构(Disk-oriented Index),其中最成功的就是 B-Tree 家族。从 1970 年 Rudolf Bayer 和 Edward McCreight 在波音科学研究实验室提出 B-Tree 起,这个…
数据库为什么不直接使用操作系统的 Page Cache,而要自己管理一块内存?本文从 double buffering 问题讲起,拆解 Buffer Pool 的架构、页面替换算法、脏页刷新策略、预读机制,再分别剖析 MySQL InnoDB 和 PostgreSQL 的实现细节,最后落到大小调优与监控诊断。
数据库事务的四大特性 ACID 中,隔离性(Isolation)是最复杂的一项。原子性靠 WAL 保证(参见 [WAL 与崩溃恢复](../27-wal-aries/wal-aries.html)),持久性靠 fsync 落盘,一致性是应用层语义——唯独隔离性,需要存储引擎在并发控制层面做出大量取舍。SQL 标准定义了…
数据库里存了一亿行数据,要找出 userid 42 的那一行。没有索引的做法是全表扫描(Full Table Scan)——从第一个数据页读到最后一个数据页,逐行比对。假设每个数据页 16 KB,一亿行占 20 GB,即使顺序读能跑到 500 MB/s,也需要 40 秒。加一个 B+Tree 索引,三次磁盘 I/O 就…
在传统的磁盘分区方案中,分区大小在创建时即被固定,后续调整代价极高。逻辑卷管理(Logical Volume Manager,LVM)在物理磁盘与文件系统之间插入一个抽象层,将离散的物理存储资源池化为可灵活分配的逻辑卷,从根本上解决了静态分区带来的容量规划难题。
RAID(Redundant Array of Independent Disks),即独立磁盘冗余阵列(Redundant Array of Independent Disks),是一种将多块物理磁盘组合成一个逻辑存储单元的技术。RAID 最初由加州大学伯克利分校的 David Patterson、Garth Gib…
拆解 Linux Device Mapper 框架的内核架构、映射表机制与七种核心 target driver,从 dm-linear 到 dm-verity,覆盖 dmsetup 实战和容器存储应用。
在存储系统的安全防线中,加密是最后一道也是最重要的一道屏障。当物理安全措施失效——磁盘被盗、服务器被非法访问、退役硬盘未彻底销毁——只有加密能确保数据不被未授权方读取。块级加密(Block-Level Encryption)在存储栈的最低层工作,对上层文件系统和应用程序完全透明,不需要修改任何一行应用代码就能保护磁盘上…
存储系统有两个看似独立、实则紧密交织的能力:快照(Snapshot)和精简配置(Thin Provisioning)。快照解决的是"时间维度"的问题——在任意时刻冻结数据状态,用于备份、回滚或测试;精简配置解决的是"空间维度"的问题——让存储容量按需分配,避免预先占满物理磁盘。两者的交叉点在于写时复制(Copy-on-…
磁盘是一个线性的块数组,但没有人愿意用"第 48372 号扇区"来定位自己的文档。文件系统(File System)就是那个把"名字"映射到"数据"的翻译层——它把一片平坦的块空间组织成人类可以理解的层级结构,同时维护着每个文件的权限、大小、时间戳等元数据(Metadata)。
ext4 是 Linux 世界中使用最广泛的本地文件系统(Local Filesystem)。从 2008 年合入内核主线至今, 它已经在无数生产服务器、嵌入式设备以及桌面系统上稳定运行了十余年。本文将从磁盘布局、 核心数据结构、日志机制、分配策略等维度,对 ext4 进行全面剖析,并结合实际调优场景给出 可落地的最佳…
XFS 诞生于 1993 年的硅谷图形公司(Silicon Graphics, Inc.),最初运行在 IRIX 操作系统上。 SGI 的核心业务是高性能计算和影视后期制作,客户需要处理的文件动辄几十 GB 甚至数 TB。 当时主流的 EFS(Extent File System)在面对这类工作负载时已经力不从心:元数…
ext4 和 XFS 走的是"就地更新"路线:数据写到哪个块,就直接覆盖那个块。这条路线简单、高效,但有一个根本性的问题——如果写到一半断电,磁盘上的数据处于半新半旧的状态,文件系统就损坏了。日志(Journal)机制可以缓解这个问题,但它本质上是"先写一遍日志,再写一遍数据",写放大不可避免。
在生产环境中,文件系统(Filesystem)的选择直接影响存储栈的性能上限、数据安全边界和运维复杂度。本文将从设计目标、元数据性能、数据吞吐、典型业务场景、基准测试方法论等多个维度,对 ext4、XFS、Btrfs(B-tree Filesystem)、ZFS(Zettabyte File System)四种主流文件…
当应用程序调用一次 write() 系统调用(System Call)时,数据并不会立刻落到磁盘扇区上。 它需要穿越内核中七个以上的软件层次,每一层都有独立的职责、数据结构和延迟开销。 理解这条完整路径,是进行存储性能调优和故障诊断的基础。
文件系统把"写这个文件"翻译成"写这些逻辑块",但逻辑块怎么变成磁盘控制器能执行的命令?中间那一层就是块设备层(Block Layer)。它做的事不复杂——把上层的 I/O 请求收集、合并、排序,然后交给设备驱动——但做得好不好,直接决定了存储栈的吞吐和延迟。
应用程序每一次 read() 或 write() 系统调用,感觉像是直接在操作磁盘上的文件,但实际上,内核在中间插入了一层透明的缓存——页缓存(Page Cache)。这层缓存用物理内存保存最近访问过的文件数据,使得绝大多数读操作不需要触发磁盘 I/O,而写操作可以先落到内存,再由后台线程异步刷回存储设备。
在高吞吐存储系统中,同步 I/O 是性能的天花板。本文系统梳理 Linux 下三代异步 I/O 方案——POSIX AIO、Linux Native AIO(libaio)和 io_uring——的设计原理、编程接口、性能特征与工程实践,帮助你在实际项目中做出正确的技术选型。
HDD 已经被 SSD 抢去了大部分聚光灯,但全球 90% 以上的数据仍然存储在旋转磁盘上。理解 HDD 的物理结构和性能特征,是理解整个存储栈设计决策的基础——从文件系统的块分配策略到数据库的 WAL 设计,几乎每一个存储优化都能追溯到'旋转延迟'和'寻道时间'这两个物理约束。
SSD 已经在大多数性能敏感场景中取代了 HDD,但 SSD 并不是"没有机械部件的硬盘"——它是一个完全不同的存储架构,带来了一组全新的工程约束。理解这些约束,需要从 NAND Flash(NAND 闪存)的物理特性开始,逐层向上推导出 FTL(Flash Translation Layer)、垃圾回收(Garbag…
存储接口(Storage Interface)是连接主机与存储介质的桥梁,其协议设计直接决定了数据访问的延迟、吞吐量和并发能力。从早期的并行接口到现代的非易失性内存快捷通道(Non-Volatile Memory Express,NVMe),存储协议经历了数十年的演进。本文将系统梳理存储接口的发展历程,深入剖析 NVM…
现代计算系统的性能瓶颈,往往不在处理器本身,而在数据的存取速度。从寄存器(Register)到磁带(Tape),存储层次结构跨越了十余个数量级的延迟差异。持久化内存(Persistent Memory,简称 PMem)的出现,试图在易失性内存与持久化存储之间架起一座桥梁,从根本上改变应用程序访问数据的方式。
存储性能不是一个数字,而是 IOPS、吞吐量和延迟在特定工作负载下的函数关系。本文从排队论模型出发,用 fio 实测验证,覆盖从 HDD 到 NVMe SSD 的性能画像,最终落到容量规划和监控体系的工程实践。
存储选型不是'SSD 比 HDD 快所以选 SSD'这么简单。不同工作负载对 IOPS、吞吐、延迟、容量、成本的权重完全不同。本文从性能、可靠性、成本三个维度对比 HDD、SATA SSD、NVMe SSD、Optane/PMem 和磁带,给出面向具体工作负载的选型决策框架和分层存储架构设计方法。