【列存引擎内核】ReplicatedMergeTree
ReplicatedMergeTree 副本协调:Log entry、ClickHouse Keeper/ZooKeeper 路径、副本同步与 recovery。双节点实验步骤(本环境未部署)。24.x LTS 默认推荐 Keeper。
发布来自土法炼钢兴趣小组的知识、笔记、进展和应用。主题包括数据结构和算法、编程语言、网络安全、密码学等。
共 106 篇文章 · 返回首页
ReplicatedMergeTree 副本协调:Log entry、ClickHouse Keeper/ZooKeeper 路径、副本同步与 recovery。双节点实验步骤(本环境未部署)。24.x LTS 默认推荐 Keeper。
ClickHouse Distributed 表的分片键、写入路由与 SELECT 下推;GLOBAL IN/JOIN 的代价与替代方案;与 ReplicatedMergeTree 副本层的关系;对照 PG Citus 的边界。
从批、流、微批四维度对比出发,建立「可重放日志 + 有状态计算」心智模型,厘清 Lambda/Kappa 边界与流表对偶,并给出与 lakehouse 入湖侧对称的全系列地图。
拆解 event time、processing time、ingestion time 三种时间语义,给出 watermark 的形式化含义与 bounded-out-of-orderness 等生成策略,并说明侧输出、allowed lateness 如何处理迟到数据;附 event-time 与 processing-time 窗口对比的可复现实验步骤。
从 WindowAssigner 三类(Tumbling、Sliding、Session)出发,讲清窗口 state 如何随 key 与窗口实例增长,Trigger 与 Evictor 如何改变 firing 与清理节奏,GlobalWindow 自定义 Trigger 的边界,并与批式 GROUP BY 时间分桶对照;附三种窗口 state 观测的可复现步骤。
从 Topic、Partition 到 Log Segment 的 .log/.index/.timeindex 文件布局,讲清 offset 单调性、分区内有序、顺序写与 sendfile 读路径,以及 Kafka 3.x KRaft 模式下元数据与日志目录的分工,为副本与 consumer 语义打底。
从 Leader/Follower 复制、HW/LEO/ISR 到 acks 与 min.insync.replicas 的 durability 边界,再到 consumer group 分区分配、rebalance 代价,以及 offset 提交与 Flink checkpoint 的分工。
从幂等 producer 的 PID 与 sequence 去重,到事务 producer 的 init/begin/commit/abort 生命周期、__transaction_state 与 read_committed 隔离,讲清 Kafka 3.x 单集群 EOS 边界及其与 Flink checkpoint 的衔接。
从 JobManager、TaskManager、Slot 到 StreamGraph→JobGraph→ExecutionGraph 的四层编译链,讲清 operator chain、并行度、SlotSharingGroup 如何决定任务在集群上的物理形态,并与 Kafka 消费位点提交分工衔接。
拆解 Source/Transform/Sink 数据流图、rebalance/keyBy/broadcast 等 shuffle 策略、keyBy 到 KeyGroup 的映射,以及 ProcessFunction 与 TimerService 如何承载事件时间逻辑,并引入算子状态与键控状态的分工边界。
系统拆解 ValueState、ListState、MapState、ReducingState、AggregatingState 的语义与适用场景,对比 HashMapStateBackend 与 EmbeddedRocksDBStateBackend 选型,讲清 State TTL 的更新/可见性/清理策略,并给出窗口 state 与 RocksDB 磁盘占用的估算方法。
从 Chandy-Lamport 分布式快照到 Flink aligned/unaligned checkpoint:CheckpointCoordinator 触发—ack—完成生命周期,Kafka source 如何把 partition offset 写入 checkpoint,以及 interval、timeout、min-pause、concurrent checkpoints 的调优边界。
对比 Savepoint 与 Checkpoint 的生命周期与格式取舍;讲清 operator uid、rescale、schema evolution 规则,cancel/stop with savepoint 流程,Flink 版本升级恢复,以及 key serializer 不兼容等故障的排查与 State Processor API 边界。
拆解 Flink EmbeddedRocksDBStateBackend 的物理布局:每个 subtask 独立 RocksDB 实例、ColumnFamily 与 KeyGroup 前缀映射、写路径 memtable→WAL→flush→compaction 与 lsm-tree 系列对照、读路径 block cache 与读放大、增量 checkpoint 与全量 snapshot 的 IO 差异。
在 RocksDB state backend 读写路径之上,拆解窗口 state 膨胀、LSM 写放大与 checkpoint 争抢磁盘、Flink managed memory 与 RocksDBOptionsFactory 调参边界,以及 hot key 导致单 subtask 过热时的诊断与「改 state 设计 vs 拧参数」取舍。
用 Source、引擎、Sink 三层模型拆解 at-most-once、at-least-once、exactly-once 的组合规则与最弱环决定律;对照 Flink checkpoint 模式、Kafka 事务与幂等 producer、重复消费/重复写入的三类修复手段,为两阶段提交 sink 铺垫。
拆解 Flink GenericTwoPhaseCommitSink 协议:preCommit 进 checkpoint、commit 挂 notifyCheckpointComplete;对照 Kafka 事务 sink、JDBC 与 Iceberg 2PC 落点,以及 commit 前/后崩溃与重复 commit 的幂等边界——与 lakehouse/11 CAS、lakehouse/19 入湖侧对读,不重复表格式全文。
从 Debezium 变更事件信封(op、before/after、source)入手,拆解 snapshot 与 streaming 两阶段、Kafka Connect 的 connector task 与 offset/schema history 主题,并说明引擎侧如何保证主键顺序与幂等,衔接 lakehouse 第 19 章 upsert 入湖。
从 Flink 作业侧拆解 checkpoint 间隔如何锁定 Iceberg 提交频率与小文件数量、背压如何拖慢 commit、并行 writer 如何触发 lakehouse/11 的乐观并发冲突,以及预聚合、bucket 分区与异步 compaction 和表治理的分工边界。
收束流式数据处理系列:Flink credit-based 背压如何沿算子链传播、Web UI 指标怎么读;数据倾斜、checkpoint 超时连锁、Kafka rebalance 风暴、RocksDB OOM、savepoint 不兼容五类生产故障的诊断与止血;Flink / Kafka Streams / Spark Structured Streaming / RisingWave 在状态模型、交付语义、运维与入湖成熟度上的对照表与选型决策树,不做排名。
承接数据湖流式入湖:从 Kafka 日志与副本语义,到 Flink 事件时间、watermark、窗口、RocksDB 状态与 checkpoint,再到端到端 exactly-once 与 Debezium CDC 入湖。面向数据平台与实时工程师,补全批式湖仓之外的实时计算层。
从 OLTP/OLAP/HTAP 边界、嵌入式 DuckDB 与分布式 Trino/Spark 分工、批式扫描与交互式查询延迟口径出发,闭合 lakehouse 与 stream-processing 之间的查询层缺口,并给出本系列 18 篇地图。
从 Parser/AST、Analyzer 与 Catalog 元数据到 LogicalPlan 算子树;对照 PostgreSQL parse/rewrite/plan 边界,并用 DuckDB 1.5.4 实测 EXPLAIN 与 Trino 476+ 文档中的 logical plan 结构对读。
RelNode、Convention、Trait 与 Rule-based 改写链;VolcanoPlanner/Cascades memo 搜索;Trino 476+ 自研 planner 与 Calcite 借鉴边界,对照 Spark Catalyst 优化阶段。
Table/column 统计、NDV 与 histogram、Iceberg Puffin/manifest 统计来源;Trino CostCalculator 与 CPU/IO/network 权重;统计过期导致全表扫与 join 中间结果膨胀;对照 PostgreSQL pg_statistic。
Join order enumeration、Hash/Merge/Nested Loop 适用条件;Trino broadcast vs partitioned join 与 shuffle 网络代价;Dynamic partition pruning 与 runtime filter;DuckDB HASH_JOIN 实测与 Spark AQE 对照边界。
从 Graefe Volcano 论文的 Open/Next/Close 接口出发,拆解 pull 语义、Sort/Hash Agg 等 pipeline breaker,并对照 PostgreSQL ExecutorRun 与 Trino 476+ Operator/Driver 的 Page 流水线。
拆解列向量 batch、SelectionVector 与 flat/dictionary 编码;对照 columnar-engine/04 的 ClickHouse Block 直觉,说明 DuckDB morsel-driven 与 Trino Page 流在 MPP 上的落地,并给出本机 DuckDB 1.5.4 实测。
从 Trino TableScanOperator 与 ConnectorSplit 出发,讲 column pruning、谓词/limit 下推在 ConnectorMetadata 的落点,以及必须留在引擎内的 Filter/Project 边界;与 lakehouse/18 读湖漏斗衔接。
拆解 hash join build/probe 内存布局、outer join 标记,以及 partial/final 两阶段聚合在 MPP 上的语义;对照 Trino 476+ spill/revocable memory 与 DuckDB 本机 HASH_JOIN 实测。
拆解 Trino Coordinator 与 Worker 的职责边界,从 Query 到 Stage、Task、Driver、Operator 的五层执行模型,Split 调度与 data locality,并与 Spark Driver/Executor/Stage 对照。
拆解 Trino 的 partitioning scheme(HASH、BROADCAST、REPLICATE、ROUND_ROBIN)、LocalExchange 与 Remote Exchange、PartitionedOutput 数据路径,以及 skew 在 EXPLAIN ANALYZE 上的判读;对照 Spark shuffle 与 AQE 边界。
主线拆解 Trino Coordinator 上 SqlQueryExecution 的生命周期:analyze、plan、fragment、Stage 调度到 Worker Task;Iceberg connector 如何从 snapshot/manifest 过滤生成 Split;Page 在 Operator 链上流动;EXPLAIN 与 EXPLAIN ANALYZE 字段判读。
拆解 Spark 3.5+ Catalyst 的 Analyzed / Optimized / Physical 计划链、whole-stage codegen 与 shuffle 边界、AQE 的动态 coalesce/skew join/broadcast;并与 Trino 476 及 Iceberg V2 reader 下推能力对照。
从单进程向量化 pipeline 与 morsel-driven 并行出发,对照 DuckDB 1.5.4 与 Apache DataFusion 的 planner/executor 边界;说明何时选嵌入式读湖、何时必须上 Trino MPP;与 columnar-engine DuckDB 存储篇分工,并用本机实测 EXPLAIN 与 Parquet 投影下推数据锚定结论。
与 lakehouse/18 分工:那边讲四层读湖漏斗是什么;本篇讲 Trino/Spark/DuckDB 在 SQL 优化链的哪一步把谓词变成 layout constraint、谁调用 Iceberg planning、split 如何携带残余谓词。引用官方文档与 lakehouse/18 本机 PyIceberg 实测,不伪造 Trino 计划输出。
拆解 Trino query/user/cluster 内存账户、revocable 与 non-revocable 内存、join/aggregation/order-by 的 spill 路径与 resource group 并发隔离;与 stream-processing 背压对照交互式 OLAP 的资源语义。依据官方文档,不伪造 OOM 或 spill 指标。
按全表扫、大 shuffle 倾斜、OOM/spill 失败、straggler task、metastore/catalog 超时五类生产故障,给出 planner/运行时观测入口与止血步骤;串联第 4–16 篇机制,不伪造 Trino UI 或 Spark 指标。
用决策树收束 Trino/Spark/ClickHouse/DuckDB/DataFusion/PostgreSQL 的适用边界:交互式联邦、批 ETL、嵌入式分析、流批一体各走哪条路径;给出能力对照表(无吞吐排名)与 postgresql→columnar→lakehouse→stream→query-engine 全栈阅读顺序,闭合数据平台栈。
闭合数据平台栈最后一块:从 SQL 解析与 Calcite 式优化,到 Volcano/向量化执行、Trino Coordinator/Worker 与 shuffle,再到 Iceberg connector 下推与生产排查。承接 lakehouse 第 18 章读湖视角,补全「谁在做 planning」的引擎内核层。
64 篇深度长文,从系统模型到前沿研究,覆盖分布式系统的每一个核心主题。
汇总本站分布式系统系列文章,覆盖系统模型、共识、复制、事务、分布式存储、计算框架与验证工程。
分布式系统的物理时钟从来不精确:石英振荡器每天最多漂移 8.6 秒,NTP 校准依赖对称网络假设,闰秒可以在凌晨击垮 Linux 内核。本文拆解石英漂移的物理根源、NTP/PTP 协议的校准机制、时钟跳变对超时逻辑的破坏、Spanner TrueTime 和 AWS Clockbound 的工程方案,以及工程师应该遵守的墙上时钟与单调时钟使用规范。
两个数据中心几乎同一时刻修改了同一个用户的购物车:北京的节点把商品 A 的数量从 1 改成 3,新加坡的节点删除了商品 B。合并的时候,系统该保留哪个版本?还是两个都保留?
共识到底在解决什么问题?Agreement、Validity、Termination 三个性质的精确含义是什么?Safety 和 Liveness 的区分为什么如此关键?FLP 不可能定理对工程实践意味着什么?本文从形式化定义出发,逐步展开共识的变体、原子广播的等价性,以及状态机复制这个最重要的应用。
Paxos 是分布式共识的理论基石。本文从 Single-Decree Paxos 的精确语义和安全性证明出发,逐步推导 Multi-Paxos 的工程优化,分析 Dueling Proposers、性能瓶颈和实现困难,最后给出一份可运行的 Go 实现。
从 Oki 和 Liskov 1988 年提出的 Viewstamped Replication,到 Castro 和 Liskov 1999 年的 PBFT,共识协议经历了从崩溃容错到拜占庭容错的质变。本文深入拆解 VR 的正常操作、视图切换与恢复协议,对比 PBFT 的三阶段提交、O(n²) 消息复杂度与水位机制,分析从 CFT 到 BFT 的本质代价。
PBFT 的 O(n²) 视图切换是 BFT 共识的性能瓶颈。HotStuff 用门限签名将消息复杂度压到 O(n),用三轮投票统一正常路径和视图切换。Chained HotStuff 进一步把三轮流水线化为每个视图只需一轮 Generic 投票。本文从 PBFT 瓶颈出发,拆解 HotStuff 的核心设计,追踪 DiemBFT、Tendermint、Narwhal-Bullshark 等现代 BFT 的演化脉络,并讨论 BFT 在非区块链场景的实际价值。
一份数据写到一个节点,怎么安全地复制到其它节点?同步复制保证强一致但拖慢写入;异步复制延迟低但 Leader 崩溃可能丢数据;半同步在两者之间找平衡。本文拆解 PostgreSQL Streaming Replication、MySQL Semi-Sync / Group Replication、Galera Cluster 的工程实现,深入分析复制延迟的三类一致性陷阱和故障转移中的脑裂与数据丢失问题。
单主复制只有一个节点能写入,跨数据中心延迟高、写入吞吐有上限。多主复制(Multi-Leader Replication)让每个数据中心都有自己的 Leader,写入延迟降到本地网络级别——但代价是并发写入可能产生冲突。本文深入拆解向量时钟的冲突检测机制、五种主流冲突解决策略(LWW、自定义合并函数、CRDT、OT、无冲突 Schema 设计)以及 CouchDB 的多主实战案例,帮你判断什么场景值得趟这趟浑水。
主从复制依赖 Leader 串行化写入,Leader 挂了就得等故障转移;多主复制解决了跨数据中心延迟,但冲突解决极其复杂。无主复制(Leaderless Replication)走了第三条路:去掉 Leader,任何节点都能接受读写,用 Quorum 机制保证读到最新值。本文从 Amazon Dynamo 论文出发,深入拆解 R+W>N 公式的数学本质、Sloppy Quorum 与 Hinted Handoff 的可用性权衡、Read Repair 与 Anti-Entropy 的收敛机制,并结合 Cassandra 和 DynamoDB 的工程实现给出生产级调优建议。
在分布式系统的复制协议中,我们通常会第一时间想到 Raft 或 Paxos。这些基于共识(Consensus)的复制方案已经成为工业界的主流选择,从 etcd 到 CockroachDB,从 Consul 到 TiKV,几乎所有需要强一致性保证的系统都在使用它们。但在 2004 年,Cornell 大学的 Robber…
在分布式系统中,一致性模型定义了并发操作的行为边界。线性一致性(Linearizability)作为最强的一致性保证,为分布式对象提供了与单机原子操作相同的语义。它让程序员可以像推理本地变量一样推理分布式系统,但实现代价高昂。本文深入探讨线性一致性的形式化定义、实现方法、优化技术以及验证手段。
分布式系统中的复制机制离不开日志。无论是数据库的主从复制、消息队列的分区副本,还是共识算法中的状态同步,背后都依赖某种形式的复制日志(Replication Log)。但并非所有日志设计都是相同的——根据复制的粒度和抽象层次,我们可以将复制日志分为三大类:物理复制(Physical Replication)、逻辑复制(…
当单台机器无法容纳全部数据时,我们需要将数据分散到多台机器上,这就是分区(Partitioning)。哈希分区是最常见的分区策略之一,通过哈希函数将数据均匀分布到各个节点。本文将深入探讨哈希分区的演进历程:从最朴素的取模哈希,到解决扩容问题的一致性哈希(Consistent Hashing),再到 Google 提出的…
深入探讨范围分区的原理、分裂与合并策略、热点处理,以及 TiKV 和 HBase 的实现细节
深入探讨分布式数据库中二级索引的实现策略,对比本地索引和全局索引的设计权衡,分析 DynamoDB GSI 和 Elasticsearch 的实现细节。
在上一篇文章中,我们讨论了分布式系统中的二级索引问题。本文将深入探讨数据再平衡(Rebalancing)的核心策略和实现细节。当分布式系统运行一段时间后,数据分布可能会变得不均匀,节点可能会加入或离开集群,这时就需要再平衡机制来重新分配数据,保证系统的负载均衡和高可用性。
2PC 在 Coordinator 崩溃时会阻塞所有参与者;本文精确分析三类故障窗口,拆解 Presumed Abort 优化原理,对比 Spanner/CockroachDB/TiDB 的现代方案。
2PC 阻塞时协调者宕机怎么办?3PC 试图用额外一轮消息解决,却撞上网络分区。Saga 放弃全局锁,用补偿事务换取可用性。本文从 Skeen 论文推导 3PC 的非阻塞证明,分析其分区缺陷,再到 Saga 编排/协同、补偿陷阱、Temporal 工程实践和 TCC 资源预留——把分布式事务的理论与工程讲清楚。
Percolator 在 Bigtable 之上用三列设计实现了跨行分布式事务,其核心思路是把事务协调状态编码进数据本身,从而消除了对专用协调者节点的依赖。本文拆解其两阶段提交流程、冲突检测与锁清理机制,并分析 TiDB 对该模型的工程改进。
在分布式系统中,时间一直是一个令人头疼的问题。不同机器的时钟会产生漂移,网络延迟让时间同步变得困难,而许多一致性协议又严重依赖时间排序。Google 的 Spanner 系统通过一个大胆的想法打破了这个困境:既然软件无法完美解决时间问题,为什么不用硬件来解决?TrueTime API 就是这个思路的产物——通过 GPS…
在分布式事务处理领域,2012 年是极为特殊的一年。这一年,Google 发表了著名的 Spanner 论文,展示了如何通过 TrueTime API 和原子钟实现全球范围内的强一致性事务。同年,耶鲁大学的 Daniel Abadi 和 Alexander Thomson 在 SIGMOD 上发表了 Calvin 论文…
在分布式数据库的事务处理领域,快照隔离(Snapshot Isolation,SI)已经成为工业界最主流的隔离级别实现。从 Oracle 到 PostgreSQL,从 CockroachDB 到 TiDB,SI 凭借其优秀的并发性能和相对简单的实现复杂度,在理论的严格性与工程的实用性之间找到了一个绝佳的平衡点。然而,S…
自 Google 在 2012 年发表 Spanner 论文以来,分布式数据库领域掀起了一场深刻的变革。Spanner 向世界证明了一个长期被认为不可能的命题:在分布式系统中,我们可以同时获得水平扩展能力、强一致性和 SQL 语义。这打破了传统 NoSQL 系统"为了扩展性而牺牲一致性"的惯例,开启了所谓的 NewSQ…
Jay Kreps 在 2013 年的博客文章"The Log: What every software engineer should know about real-time data's unifying abstraction"中提出了日志(Log)作为分布式系统基础抽象的思想。日志不是应用程序的调试日志,而是…
2007 年,Amazon 在 SOSP 会议上发表了《Dynamo: Amazon's Highly Available Key-value Store》论文,这篇论文彻底改变了分布式存储系统的设计思路。与追求强一致性的传统数据库不同,Dynamo 选择了一条完全不同的道路:牺牲一致性,换取可用性和分区容错性。这个设…
Google 在 2003 年 SOSP 上发表的 GFS 论文,定义了现代分布式文件系统的基本架构模式。十几年过去,GFS 的设计思想深刻影响了开源世界的 HDFS、工业界的后继者 Colossus,以及我们对分布式存储的理解。本文深入分析 GFS 的核心设计决策,特别是单 Master 架构的利弊权衡;探讨 HDF…
一个 200 节点的 HDFS 集群,NameNode 进程 OOM,整个集群立即不可读写。运维团队花了 40 分钟从备份恢复元数据镜像,重放 EditLog,等待所有 DataNode 上报块信息。在这 40 分钟里,依赖该集群的数据管线全部停滞。
一个典型的架构评审场景:团队需要一个分布式键值存储来承载新系统的元数据。候选方案三个——etcd、TiKV、FoundationDB。三者都提供强一致性保证,都经过大规模生产验证,但设计目标截然不同。选错了,轻则性能不达标,重则数据丢失后无法恢复。这篇文章从架构、实现、性能和局限四个维度,把三个系统拆开来看。
某电商团队的订单库跑在 MySQL 上,单表 12 亿行,64 个分片散布在 16 台物理机。每到大促,DBA 手动执行扩容脚本:新建分片、配置路由、灰度迁移、双写校验——一整套流程需要 72 小时。更麻烦的是跨分片的事务:用户下单时需要同时扣减库存和写入订单,中间件层勉强用 XA 两阶段提交撑着,但超时重试导致的数据…
两个用户同时在协作文档的同一段落各自插入了一句话。没有中心服务器协调,两台设备在断网状态下各自完成编辑,重新上线后需要合并。如果简单地用"后写入者胜出"策略,必然丢弃一方的修改;如果走共识协议,断网期间就无法写入。有没有一种数据结构,能让每个副本独立更新,在任意顺序收到对方的更新后自动收敛到同一状态,且不丢失任何修改?
三个节点同时对同一个购物车执行"添加商品"操作,网络恢复后购物车里应该有几件商品?如果两个用户在协同文档里同时输入文字,合并后的文本是否会出现乱序或丢字?这些问题看似简单,但背后对应的数据结构设计空间却异常庞大。CRDT(Conflict-free Replicated Data Type,无冲突复制数据类型)正是为了…
两个人同时编辑同一段文字。用户 A 在位置 3 插入字符 "x",用户 B 删除位置 2 的字符。这两个操作在各自的本地副本上独立执行,没有问题。但当 A 的操作传到 B 那里时,位置 3 已经因为 B 的删除而偏移了——如果直接应用,文档就乱了。
一个 OR-Set(Observed-Remove Set)部署在 100 个节点上,每个节点维护的集合包含 10000 个元素。在 state-based CRDT 的经典设计里,每一轮反熵(anti-entropy)同步都要把整个状态发给邻居节点。单个节点的状态序列化后大约 200KB(假设每个元素连同唯一标签占…
你有 20TB 的网页爬虫数据,需要统计每个词出现了多少次。一台机器,内存 64GB,磁盘吞吐 200MB/s——光读一遍数据就要将近 28 小时。你可以把数据切成 2000 份,分到 2000 台机器上并行处理,理论上几分钟就能跑完。但问题马上变了:哪台机器处理哪一份?中间结果怎么汇总?其中 50 台机器跑到一半挂了…
假设你在 Hadoop MapReduce 上跑一个 PageRank 迭代:每轮迭代要从 HDFS 读全量数据,做一次 map-shuffle-reduce,再把结果写回 HDFS。20 轮迭代意味着 20 次全量磁盘读写。一个 100 GB 的图数据集,每轮迭代光磁盘 I/O 就要几分钟,整个作业跑下来几个小时。问…
一个支付系统每秒接收数万笔交易事件,需要按 5 分钟窗口统计每个商户的交易总额。问题来了:网络延迟导致一笔 14:59:58 产生的交易在 15:00:03 才到达系统。如果按数据到达时间(处理时间)划分窗口,这笔交易会被错误地归入 15:00-15:05 的窗口,导致 14:55-15:00 窗口少算了一笔,15:0…
某电商平台的数据团队维护着两套代码:一套 MapReduce 任务每天凌晨跑全量订单统计,另一套 Storm 拓扑实时计算 GMV 大屏指标。两套系统使用不同的编程模型,实现同一份业务逻辑——按区域统计销售额、按品类计算转化率。问题从第一天就存在:批处理代码更新了折扣计算规则,流处理代码忘了同步,导致实时大屏与 T+1…
深入拆解 ZooKeeper 的核心机制:ZAB 协议的三阶段流程、ZNode 数据模型、Watch 一次性通知、会话管理,以及分布式锁、Leader 选举、配置管理等典型用法。分析惊群效应等已知问题,并梳理 ZooKeeper 在 Kafka、HBase、Hadoop 生态中的角色。
深入剖析 etcd 的核心机制:持久化 Watch 与 Revision 追溯、Lease 租约机制、基于 BoltDB 的 MVCC 存储引擎、与 Raft 共识的联动方式,以及在 Kubernetes 中的关键角色。涵盖性能调优策略、容量限制与规模化方案。
完整还原 Kleppmann 与 Antirez 关于 Redlock 的技术争论,拆解 Fencing Token 方案的原理与实现,对比基于 etcd 和 ZooKeeper 的分布式锁正确实现,讨论锁粒度、Advisory Lock 与 Mandatory Lock 的区别,以及用版本号代替锁的替代思路。
2020 年 11 月 25 日,Google 全球范围的服务连锁故障。根因是内部 RPC 框架的一个默认超时配置:当身份认证服务响应变慢时,数十万个 RPC 调用阻塞在等待认证结果上,连接池耗尽,请求堆积如山,最终拖垮了包括 Gmail、YouTube、Google Cloud 在内的几乎所有面向用户的服务。一个看起…
一个 1000 节点的集群里,某台机器的磁盘满了。这个信息需要多久才能传遍整个集群?
三个副本需要以相同顺序执行同一批写操作。节点 A 先广播 x1,再广播 x2;节点 B 收到的顺序却是 x2 然后 x1。副本状态分叉了——A 认为 x2,B 认为 x1。更糟糕的是,如果 A 在发完第一条消息后崩溃,某些节点收到了 x1,另一些没收到。此时系统中存在两类节点:知道 x1 的和不知道的。后续所有基于 x…
一个 RPC 调用耗时 500 微秒,其中网络往返占了 490 微秒。一次分布式事务需要两轮 RPC,总耗时超过 1 毫秒。为了掩盖这个延迟,工程师不得不引入批处理、异步流水线、预取缓存——系统复杂度因此翻了好几倍。过去三十年,几乎所有分布式系统的设计都建立在一个核心假设之上:网络比本地内存慢三到四个数量级。Share…
一个电商平台的核心交易数据库运行在三节点集群上,每个节点配备 64 核 CPU、512 GB 内存和 8 TB NVMe SSD。年底大促结束后,数据量从 5 TB 膨胀到 18 TB,存储空间告急。但 CPU 利用率在非促销期长期低于 15%。运维团队提交了扩容工单:要么给每个节点挂载更大的磁盘——但这要求停机迁移数…
一个后端工程师写了一段 50 行的 Node.js 函数:接收 HTTP 请求,从数据库查一条记录,做一次格式转换,返回 JSON。他把这段代码上传到 AWS Lambda,配好 API Gateway,五分钟后就拿到了一个能承受每秒数万请求的线上接口。不需要配置服务器,不需要操心容量规划,不需要写自动伸缩策略,甚至不…
2013 年,一组研究人员对 Raft 协议的多个开源实现进行了系统性审查。其中一个实现通过了开发者编写的全部 3000 余条单元测试和数十个集成测试,在长达六个月的生产环境运行中未出现任何可观测的故障。然而,当研究人员用一个精心构造的网络分区序列去测试它时,系统在 47 秒内就违反了线性一致性(Linearizabi…
「用 2PC 就行了」——说这话的人大概没在生产环境里被 Coordinator 挂掉后全员阻塞的锁堵过三小时。2PC 的真实失败模式、Percolator 的精妙设计、Saga 与 TCC 的工程取舍,分布式事务远比教科书复杂。
从 Gossip 协议的 SI 传播模型出发,深入拆解 SWIM 故障检测协议的直接探测、间接探测和怀疑机制,分析 HashiCorp Memberlist 的源码实现,对比 Serf 与 Consul 的成员管理策略,并提供基于 Memberlist 构建集群成员管理的完整 Go 代码示例。
分布式系统中一致性模型不是二选一,而是一条光谱。本文从线性一致性、顺序一致性讲到因果一致性、最终一致性及其变体,用反例区分每一级的差异,用 Go 代码实现操作历史的一致性检测,并把 ZooKeeper、Spanner、DynamoDB、Cassandra 映射到这条光谱上。
最终一致性承诺'最终'收敛,但没说收敛之前用户会看到什么。你改了头像刷新后消失、余额先涨后跌、回复比原帖先出现——这些都是缺少会话保证的症状。Terry 等人在 1994 年定义了四种会话保证,COPS 和 Eiger 把因果一致性做到了跨数据中心,Bailis 的 Bolt-on 方案让老系统也能补上因果语义。
从性能基准、选型决策、隐藏成本三个维度,系统对比 Raft、Multi-Paxos、EPaxos 三大共识协议在工程实践中的真实表现,帮助架构师做出有据可依的选型决策。
分布式系统的正确性证明和协议设计都建立在系统模型之上。同步还是异步?崩溃还是拜占庭?这些看似学术的分类,直接决定了你能用什么协议、不能用什么协议。本文拆解通信模型、故障模型和进程模型三个维度,把 Paxos、Raft、PBFT、Bitcoin 放回它们各自的模型空间。
FLP 说异步系统中共识不可能,但 Raft 跑得好好的。CAP 说三选二,但 Spanner 声称兼得。矛盾不在定理本身,在于读定理时跳过了精确条件。本文回到 FLP、CAP、共识数和收割/产出四篇原始论文,逐一拆解它们的真实陈述、证明思路与工程边界。
Saltzer、Reed、Clark 1984 年的端到端论证解释了为什么很多'看上去合理'的中间层优化最终是错的。本文从原始论文出发,拆解端到端论证在幂等性、exactly-once 语义、E2E 加密中的现代应用,附带 Go 幂等性实现。
Raft 论文 18 页就能读完,但 etcd/raft 用了 15000 行 Go 才把它变成能在生产环境跑的代码。这篇文章从论文的每一个核心机制出发,逐一拆解工程实现中论文没说的东西:PreVote、ReadIndex、LeaderTransfer、ConfChange V2、流水线复制、Async Apply,以及 TiKV 的 Multi-Raft 实践。最后做一次精确的 Paxos 对比,并坦诚讨论 Raft 的已知缺陷。
Multi-Paxos 和 Raft 都依赖单一 Leader 排序所有写请求,Leader 成为吞吐瓶颈和延迟下限。EPaxos 用无主依赖图替代全序日志,Flexible Paxos 用不对称 Quorum 让写路径绕过多数节点。两条路的核心机制、隐含假设、工程代价和已知陷阱。
教科书把故障分成 crash 和 Byzantine 两种,但生产环境里最常见、最难处理的故障恰恰是两者之间的灰色地带:静默数据损坏、时钟跳变、GC 停顿、慢磁盘。本文从故障层级模型出发,逐层拆解五种故障类型,结合真实事故案例分析检测手段与工程应对策略。
顺序算法用时间复杂度和空间复杂度就能衡量好坏。分布式算法多了消息复杂度、轮次复杂度和容错数量三个维度,三者之间存在不可调和的 trade-off。本文从选主、共识、广播三个典型问题出发,梳理这些度量指标的定义、下界和工程影响。
物理时钟对不齐,逻辑时钟丢物理信息,向量时钟太重。HLC 用物理时间 + 逻辑计数器找到了平衡。但 Google 选了另一条路:用原子钟和 GPS 把物理误差压到几毫秒。这篇文章从 HLC 的算法正确性证明、CockroachDB 源码实现、TrueTime 工程架构,一直讲到 AWS Clockbound 的开源方案——在物理和逻辑之间,每种选择都是一笔工程账。
Raft 保证强一致,但 Leader 一挂全卡。CRDT 不需要共识也能合并——代价是元数据膨胀、只能单调、最终一致。G-Counter、LWW-Register、OR-Set 的 Go 实现,正确性验证,以及什么时候该用 Raft、什么时候该用 CRDT。
分布式系统里最难的问题之一:如何定义事件的先后?物理时钟对不齐,逻辑时钟丢信息,向量时钟太重。HLC 用物理时间 + 逻辑计数器找到了平衡点。从 Lamport 时钟一路推导到 CockroachDB 的工程实现。
Raft 论文 18 页,etcd raft 库 ~15000 行 Go。中间的差距不是代码量,是论文没提的工程 edge case:PreVote、流水线复制、ReadIndex、joint consensus。
Paxos 被引用了几千次,能正确实现它的人不超过几十个。Raft 用可理解性换工程落地,它的 Leader Election、Log Replication 和 Safety 三板斧,撑起了 etcd、TiKV 和大半个云原生基础设施。