分布式系统(31):Ray 的 Future、对象血缘与重试边界
Ray 把远程函数的返回值立即表示成 ObjectRef,它在概念上类似论文所称的 future。调用者可以继续把这个引用交给下游任务,不必先等待真实值,于是普通 Python 函数调用扩展成执行期间不断生长的分布式 DAG。代价也随之出现:引用、对象值、生产任务和外部副作用有不同的故障命运。 分布式系统(30):Spark/RDD 的血缘、物化与故障重算 RDD 以数据集转换为中心;Ray 的基本节点更细,可以是一项任意远程任务及其 future。两者都能沿依赖重算,但 Ray 当前产品的对象 ownership、task retry 和 actor 规则不能直接从 RDD 类比推出。 ObjectRef 是未来值,不是结果副本 f.remote() 提交一个 task 并返回 ObjectRef。下游 task 接收引用时,Ray 记录依赖;参数值可用后,下游才具备运行条件。ray.get 把等待显式带回调用者。 flowchart LR A[f.remote → ObjectRef A] --> C[h.remote A B] B[g.remote ...
分布式系统(30):Spark/RDD 的血缘、物化与故障重算
迭代计算有两种基本恢复思路:每一轮都把完整中间状态写到可靠存储,或者保留“这份数据怎样算出来”的配方,丢失后只重算需要的分区。MapReduce 倾向前者,Spark RDD 把后者做成了核心抽象。差别不是“磁盘与内存”的口号,而是恢复证据放在哪里、何时必须物化。 分布式系统(29):Kafka 的日志、消费位点与事务边界 第 29 篇用日志位点保存重放起点。RDD 没有用一个消费 offset 表示恢复位置,而是保存分区依赖图;shuffle、cache 和 checkpoint 又会在图上形成性质不同的边界。本篇用同一个四分区迭代负载比较这些边界。 RDD 保存的是分区与配方 RDD 论文把 RDD 定义为分区的只读记录集合。程序从可靠输入创建 RDD,再用 map、filter、join、reduceByKey 等转换得到新的 RDD。转换是惰性的;action 需要结果时,调度器才沿依赖图生成任务。 flowchart LR I[可靠输入] --> M[map] M --> F[filter] F --> S[reduceByKey / sh...
分布式系统(29):Kafka 的日志、消费位点与事务边界
一条 Kafka 记录已经“提交”,不代表业务已经处理;消费者提交了 offset,也不代表外部扣款成功;Kafka 事务提交,更不代表任意 HTTP 服务与数据库都一起提交。三个动作都叫 commit,却属于不同状态机。 分布式系统(28):缓存失效、填充与旧值竞态 第 28 篇把数据库状态、缓存值和填充资格拆开。Kafka 也需要同样的拆分:分区副本决定哪段日志可承诺,consumer group 保存从哪里恢复,transaction coordinator 决定一组 Kafka 写入是否可见。外部副作用若没有加入同一个原子协议,仍在边界之外。 本文用五个可观察量贯穿故障时间线:已复制并提交的日志位置、消费者当前位置、消费组已提交位点、事务状态、外部副作用次数。 四层状态不能合成一个“已处理” Kafka topic 被分成多个 partition。每个 partition 是有序追加日志,offset 只在该 partition 内有意义。传统 consumer group 把一个 partition 在同一时刻分配给一个成员,成员按 offset 拉取;跨 partit...
分布式系统(28):缓存失效、填充与旧值竞态
数据库已经是 v2,缓存也删过了,系统却还能重新缓存 v1。这里没有缓存节点“回滚”,也不需要消息乱序:一个较早开始的读请求在失效之后才把旧查询结果写回,就足以让旧值复活。 分布式系统(27):FaRM 的乐观验证、RDMA 与提交路径 第 27 篇的事务协议会认证读写集并保存共同决定。cache-aside 路径通常没有这样的统一协议:数据库是权威源,Memcached 是可丢失的派生状态,应用分别调用两边。本文从这条边界出发,复现旧值回填,并比较 TTL、延迟双删、lease、版本栅栏和单 key 串行化。 先写清 cache-aside 的状态机 读取流程通常是:先查缓存;miss 后查数据库;再把结果写入缓存。写入流程通常是:提交数据库,然后删除缓存。后续读者通过 miss 获取新值。 flowchart LR R[读取请求] --> G{cache get} G -->|hit| V[返回缓存值] G -->|miss| D[读取数据库] D --> S[cache set] S --> V W[...
分布式系统(27):FaRM 的乐观验证、RDMA 与提交路径
两笔事务都读到 x=0,随后都想把 x 写成 1。锁住其中一个写者并不难。更麻烦的是,两笔事务分别写 x 和 y,同时读取对方正在修改的对象。它们没有争抢同一个写锁,仍可能一起通过不完整的验证,留下任何串行顺序都解释不了的结果。 分布式系统(26):Spanner 的时间区间、提交等待与一致快照 FaRM 把这类冲突检测放在内存事务的提交路径上,又用 RDMA 把读取和日志复制做得很轻。低 CPU 的数据搬运并没有消除事务协议:乐观并发控制要回答“这组读写能否串行化”,复制要回答“故障后写值还在不在”,原子提交要回答“多个 region 是否形成同一个终局”。本文以 SOSP 2015 论文为主,2014 年版本只用于解释协议演进。 先固定论文的系统模型 FaRM 面向单数据中心的内存驻留数据。全局地址空间被切成 2 GiB 的 region;每个 region 有一个 primary 和 f 个 backups,并放到不同的 failure domains。对象只从 primary 读取:本地对象用普通 load,远端对象可用 one-sided RDMA。应用线程与存储服务运...
计算机网络 E08:IP 组播、覆盖网络与内容分发
同一份内容交付给多个接收者时,发送端逐一建立单播连接最容易部署,却会在共享路径上重复发送相同字节。IP 组播把复制点下沉到网络分支,应用层覆盖把复制点放在中继节点,边缘缓存则利用内容在不同请求之间的可复用性。三种方案减少的重复范围不同,承担的状态也不同。 第 11、12 篇说明路由选择,第 23 篇讨论 HTTP 缓存,第 32 篇讨论负载均衡。本篇在固定树形拓扑上比较流量与状态成本,不把静态模型写成公网部署或性能测量。 先定义“少发一份”的计量单位 设对象大小为 B,一条路径经过的每条有向链路都传输一次完整对象。本文用“对象副本·链路”计数,再乘 B 得到 MiB·链路。这个量表示网络中各链路承载字节数的总和,不是吞吐率、费用或完成时间。 固定拓扑含一个源站、一个核心节点、四个区域节点,每个区域有两个接收者。源站到核心、核心到区域、区域到接收者各算一跳,共有八个接收者。对象大小为 4 MiB。 直接单播需要为每个接收者走三跳,因此成本为 8 × 3 × 4 = 96 MiB·链路。源站还要发送八份对象。这个基线不需要网络保存组播组状态,但发送端或代理仍要处理八条交付关系。 模式...
计算机网络 E07:实时音视频、RTP、抖动缓冲与 NAT 穿越
实时媒体不能无限等待迟到报文。抖动缓冲增大时,更多报文可能赶上播放期限,交互等待也随之增加。NAT 穿越解决的是双方怎样找到可用路径,不会替应用决定该等多久或怎样处理丢帧。 第 13 篇说明 UDP 交付边界,第 21 篇讨论名字解析,第 31 篇讨论 NAT。本篇用固定 RTP 到达轨迹比较两种播放延迟,并区分 ICE、STUN 和 TURN。 RTP 提供序号与媒体时间线 RTP(Real-time Transport Protocol)报头包含序号和时间戳。序号帮助接收端检测丢失与恢复顺序,时间戳表示媒体采样时间,二者用途不同。序号连续也不等于按时到达,时间戳也不是可直接与本机墙钟相减的全球时间。 RTCP 可以携带接收报告、丢包和抖动等控制信息。RFC 3550 的 interarrival jitter 是传输时间差变化的统计估计,不等同于抖动缓冲长度,也不直接等于某个报文的播放延迟。 实时应用通常在截止时间前等待乱序或抖动报文。截止时间后才到达的媒体即使网络最终交付,也可能对当前播放无用。恢复、隐藏、重传和前向纠错策略取决于媒体类型与时延预算。 模式提炼:可靠交付与按...
计算机网络 E06:RDMA、RoCE 与数据中心拥塞
RDMA 可以减少远端内存操作中的 CPU 参与和数据复制,但它没有让链路容量、交换机队列或突发流量消失。RoCE 把 RDMA 传输带到以太网;可靠传输语义、链路级暂停和端到端拥塞控制仍是不同层次的问题。 第 20 篇讨论队列与 ECN,第 35 篇讨论数据中心 incast。本篇依据 RoCE、PFC 和 DCQCN 资料分析一条固定优先级队列,不给没有硬件支撑的性能结果。 RDMA 约束数据搬运语义 RDMA(Remote Direct Memory Access)允许一端通过注册内存和队列对执行远端读写或消息操作。应用需要管理内存注册、访问密钥、队列对状态和完成事件。少一次内核数据路径复制不等于没有协议处理,也不等于业务事务已经提交。 RoCE 使用以太网承载 InfiniBand 传输。RoCE v2 可在 IP/UDP 网络上路由,但具体队列对类型、重传、排序和错误处理必须按设备与传输模式核查。“UDP 不可靠”不能直接推出所有 RoCE 操作没有恢复语义;“可靠连接”也不能推出网络可以无限丢包而无代价。 模式提炼:把可靠性与拥塞控制拆开 操作完成语义 ≠ 队列不溢出...
计算机网络 E05:eBPF/XDP、DPDK 与内核旁路
“绕过内核一定更快”不是可复查的性能结论。收包成本可能来自中断或轮询、驱动、内存分配、队列同步、包解析、复制、缓存失效和发送完成;offload 与丢包口径不同,还会让两个数字失去可比性。 第 29、30 篇讨论事件循环和 Linux 主机路径。本篇区分 eBPF、XDP、AF_XDP 与 DPDK 的执行位置,并建立固定负载的成本账本。没有相应设备与权限时,只验证计数守恒,不报告吞吐排名。 eBPF 是执行机制,XDP 是挂点 eBPF 程序经过验证后在内核定义的挂点运行。不同程序类型具有不同上下文和可用 helper,不能把任意 eBPF 程序放到任意路径。 XDP 位于网络接收路径的较早位置,可对报文执行 PASS、DROP、TX、REDIRECT 等动作。具体运行在原生驱动、通用模式还是硬件 offload,会显著影响路径和能力。写“启用了 XDP”仍不足以解释成本。 AF_XDP 用环形队列在用户空间与 XDP 路径之间交换报文描述符。零拷贝需要驱动与配置支持;复制模式也可能工作。需要从实际绑定模式和统计确认,不能根据 API 名称宣称零拷贝。 模式提炼:先画数据所有权...
计算机网络 E04:SDN、OpenFlow/P4 与可编程数据面
转发表发生变化后,报文可能换一个出口,也可能在更高优先级规则处被丢弃。SDN 把控制逻辑与转发执行分开,OpenFlow 定义控制器操作交换机表项的协议,P4 则描述可编程包处理管线;三者不能当作同义词。 第 10 篇讨论路由器查表与转发,第 30 篇讨论 Linux 主机路径。本篇用固定软件模型验证规则变化,不把模型结果当作 Open vSwitch、P4 软件交换机或硬件 ASIC 的运行证据。 控制面安装规则,数据面逐包执行 OpenFlow 交换机包含一个或多个流表。流表项通常具有匹配字段、优先级、计数器和指令;报文按管线匹配后执行输出、修改、丢弃或转入下一张表等动作。表未命中时的行为也必须由配置或规范语义决定。 SDN 控制器根据拓扑和策略计算规则,再通过南向接口下发。控制器“希望安装”与交换机“已经安装并用于报文”是两个事件,需要事务回复、表项读取和数据面探测分别取证。 P4_16 描述 parser、可编程 control 和 deparser 等抽象。P4 程序能表达什么还受目标架构、表容量、动作能力、编译器和硬件资源限制。可编程不等于任意程序都能以线速运行。P4...






