HackerTube English?
软件边界与变化 →

一条记录能同时回答「现在」和「当时」吗?

两次查询得到了不同答案。先问你在读哪个时刻的值,再问谁能修改它。保存历史与协调写入解决的是不同的问题。

本文的问题 · 15
  1. 查询模型之外,还要决定是否保留事实的时间
  2. 从状态的时间依赖走向带时间的事实
  3. 从不可变快照扩展到信息值的设计
  4. 时间模型解释了状态为何造成纠缠
  5. 隐藏突变不会自动消除并发耦合
  6. 从访问模式出发,再选择数据项的协调方式
  7. 局部对象各自加锁,不保证组合起来仍然安全
  8. 两个副本都同意,是否等于两笔操作都保住了?
  9. 为什么每一笔都是真账,备份还是少了一百元?
  10. 读起来一直是同一个值,里面做了多少次工作?
  11. 逐块替换与完整复制,会留下同一条历史吗?
  12. 一天里进来了多少,与此刻还剩多少,能用同一个数吗?
  13. 分支名没变,为什么代码已经不是昨天那份?
  14. 备份了五份,猜密码的机会也增加五倍吗?
  15. 重现昨天的结果,还需要哪一版规则?

查询模型之外,还要决定是否保留事实的时间

DynamoDB 讲解要求先枚举访问模式,再按查询组织单表、索引和事务;Hickey 则强调事实包含时间,新事实不应让过去的事实变成错误或消失。连接这两点可以把存储设计从“怎样高效读当前实体”推进到“是否需要表达历史事实”,提示读者将时间与访问模式一并纳入建模。

对照原文与时间戳 · 2
understand every access pattern I need to know
AWS re:Invent 2018: Amazon DynamoDB Deep Dive: Advanced Design Patterns for DynamoDB (DAT401) · ▶ 27:59–28:05
no they don't because facts incorporate time how is
The Value of Values with Rich Hickey · ▶ 20:30–20:41

DynamoDB 演讲中的版本控制例子并不等同于完整的事件溯源或历史事实模型;Hickey 的主张是信息建模原则,不是具体数据库实现指南。

从状态的时间依赖走向带时间的事实

Simple Made Easy 讨论可变状态的理解负担;The Value of Values 提出保留带时间的事实,避免用当前位置覆盖历史。可把后者当作处理信息历史的具体方向,但它没有证明所有状态都应永久保存,也没有直接给出数据库实现。

对照原文与时间戳 · 2
Having state in your program is never simple, right?
"Simple Made Easy" - Rich Hickey (2011) · ▶ 36:01–36:08
no they don't because facts incorporate time how is
The Value of Values with Rich Hickey · ▶ 20:30–20:41

同一讲者不同层次的设计论述,不是独立实验证实,也不构成立场逆转。

从不可变快照扩展到信息值的设计

两者都明确把不可变性作为值的属性;The Value of Values 进一步突出语义透明、比较与跨边界共享。适用层次由进程内时间模型延伸到信息表达,而非立场改变。

对照原文与时间戳 · 2
key characteristic of a value is that it's immutable
Are We There Yet - Rich Hickey · ▶ 24:48–24:53
values are immutable right and values are semantically transparent
The Value of Values with Rich Hickey · ▶ 10:43–10:54

同一讲者不同层次的设计论述,不是独立实验证实,也不构成立场逆转。

时间模型解释了状态为何造成纠缠

Are We There Yet? 把值定义为不可变快照,并把身份与状态演进拆开;Simple Made Easy 则从理解成本解释可变状态的复杂性。前者提供机制模型,后者给出设计判断框架。这不是两个独立实验相互验证,也不是对状态的全面禁止。

对照原文与时间戳 · 2
key characteristic of a value is that it's immutable
Are We There Yet - Rich Hickey · ▶ 24:48–24:53
Having state in your program is never simple, right?
"Simple Made Easy" - Rich Hickey (2011) · ▶ 36:01–36:08

同一讲者不同层次的设计论述,不是独立实验证实,也不构成立场逆转。

隐藏突变不会自动消除并发耦合

范畴论导论指出对象封装仍会隐藏突变与数据竞争;Bloch 用日期格式化器和可变尺寸对象说明外观简单的 API 也可能暗含共享状态,因此建议尽量不可变。

对照原文与时间戳 · 2
They hide mutation – they mutate some state inside, right?
Category Theory 1.1: Motivation and Philosophy · ▶ 10:48–10:57
feels like an immutable object, except that it has state inside it.
How To Design A Good API and Why it Matters · ▶ 41:10–41:16

这不是宣称所有对象或可变 API 都不安全;需要明确所有权、生命周期和并发契约。

从访问模式出发,再选择数据项的协调方式

DynamoDB 讲解要求事先了解访问模式并围绕查询设计数据布局;WhatsApp 的讲解展示了另一项访问设计选择:同一记录的操作被路由到单一进程。两者可作为互补问题来读——先确定需要如何访问数据,再决定如何组织数据和协调对同一记录的并发访问。

对照原文与时间戳 · 2
access on a single record is going through a single process
Erlang Factory 2014 - That's 'Billion' with a 'B': Scaling to the Next Level at WhatsApp · ▶ 14:38–14:43
understand every access pattern I need to know
AWS re:Invent 2018: Amazon DynamoDB Deep Dive: Advanced Design Patterns for DynamoDB (DAT401) · ▶ 27:59–28:05

前者讨论 DynamoDB 的表与索引建模,后者讨论 Erlang/Mnesia 系统中的进程路由;不能把单进程访问当作 DynamoDB 的设计建议。

局部对象各自加锁,不保证组合起来仍然安全

这里讨论共享可变状态的协调成本,并未断言所有锁或所有对象设计都有错。

对照原文与时间戳 · 3
values aggregate to values all the benefits apply to Aggregates
The Value of Values with Rich Hickey · ▶ 16:07–16:16
and unfortunately locks don't compose either, right. That's the problem with locks.
Category Theory 1.1: Motivation and Philosophy · ▶ 12:16–12:26
as soon as you have objects being shared encapsulation just flies out the window
Object-Oriented Programming is Bad · ▶ 20:59–21:10

两个副本都同意,是否等于两笔操作都保住了?

两台 ATM 各看到同一百元余额时,检查和扣款要作为一个整体,否则两次各自合法的操作合起来可能越界。编辑器碰到另一种并发:两个人都插入了一个字。按时间戳只保留一方可以让副本一致,却没有保住两次插入;Kleppmann 演示了按不同顺序应用操作仍得一致结果的思路。设计前先问哪条约束最重要:钱不能被取两遍,文字则可能需要两笔输入都在。一致副本本身回答不了这个业务问题。

原文与时间戳 · 3
the account balance check and the withdrawal are basically done not at all or in full
Lecture 1 | Programming Paradigms (Stanford) · ▶ 10:05–10:14
as being the winner and the other ones were just going to throw away
Conflict Resolution for Eventual Consistency • Martin Kleppmann • GOTO 2016 · ▶ 16:19–16:23
apply operations in a different order and still get the same outcome
Conflict Resolution for Eventual Consistency • Martin Kleppmann • GOTO 2016 · ▶ 29:38–29:46

为什么每一笔都是真账,备份还是少了一百元?

甲乙两个账户原本各有 500 元。备份先读收款方乙,读到 500;此后甲向乙转账 100 元并提交。备份再读付款方甲,读到扣款后的 400。于是备份合计 900,实际总额却始终是 1,000。两笔都符合「已提交」的要求,却可能拼成现实中从未出现的余额组合。Kleppmann 用这个例子拆开单条记录与一致快照。Hickey 讲 Clojure refs 时换到写的一侧:把需要一起改变的东西放进同一协调操作,读者再从一致的时间点观察。保留一堆不可变值很有用,但仍要定义哪些值必须属于同一个观察。

原文与时间戳 · 2
you've seen different parts of the database at different points in time
"Transactions: myths, surprises and opportunities" by Martin Kleppmann · ▶ 16:34–16:42
refs allow you to change more than one thing in a coordinated operation
Clojure Concurrency - Rich Hickey · ▶ 61:50–61:59

读起来一直是同一个值,里面做了多少次工作?

从调用者看,一位内存仍存着 1;从 DRAM 的单元看,电容上的电荷却在流失。动画演示存储体如何定期刷新。这给「保持状态」补上了一个容易忘的条件:若实现承诺在某段时间内可读,维持这个承诺所需的刷新本身也得按时完成。

原文与时间戳 · 2
charge leaks out over time.
How does Computer Memory Work? 💻🛠 · ▶ 21:33–21:39
The refresh operation occurs once every 64 milliseconds for each bank
How does Computer Memory Work? 💻🛠 · ▶ 22:53–22:58

逐块替换与完整复制,会留下同一条历史吗?

传送器的思想实验故意使副本在所有可检查属性上匹配;忒修斯之船则让替换有一个可追踪的顺序。把它借到版本系统里,两个文件按字节相同可以通过内容校验,但若问题是「哪一次审阅产生了它」,仍要查提交路径。先说清本次要核验内容、历史还是对象的连续身份,才能决定要存哪种记录。

原文与时间戳 · 2
Or a copy that thinks it's you?
Why Teleportation Would Kill You · ▶ 0:48–0:51
eventually no piece is original.
Why Teleportation Would Kill You · ▶ 2:33–2:39

一天里进来了多少,与此刻还剩多少,能用同一个数吗?

Grey 提醒读者,摄入持续一段时间时身体也在处理已经进入的物质。把这个例子简化成一个容器,已知总流入量却不知道何时流入、何时流出,仍无法重建某一刻的存量。下次看见按日累计的数据,先问曲线记录的是事件、净变化还是当前状态,再决定能否从它推回一个时点。

原文与时间戳 · 2
It takes about 40 coffee beans to make one shot of espresso.
Your Coffee Addiction Is Probably Good for You · ▶ 0:57–1:01
while you're busy getting the coffee in, your body is busy getting it out
Your Coffee Addiction Is Probably Good for You · ▶ 1:48–1:56

分支名没变,为什么代码已经不是昨天那份?

把一个分支名发给同事,并不等于交给他一个固定版本。课程的猫和狗示例里,新增提交会让 cat 这个引用指向新节点,而原有提交及父子关系仍然保留。这里可以把「会变的身份」和「某一刻的值」分开看:分支名便于追踪正在推进的工作,提交标识便于指认一次具体快照。若要解释昨天的行为,先写下当时解析到哪个提交,再检查运行输入和环境是否也保留了。代码快照解决了其中一层,不能单凭一个提交号就宣称整个运行可复现。

原文与时间戳 · 2
this entire graph is actually immutable.
Lecture 6: Version Control (git) (2020) · ▶ 24:15–24:17
the cat pointer, will be updated to point to the new commit
Lecture 6: Version Control (git) (2020) · ▶ 51:27–51:32

备份了五份,猜密码的机会也增加五倍吗?

历史记录可以复制,允许失败几次的额度却不能随副本数量任意增加。Krstić 解释,若一个托管记录在五个 HSM 上各有十次独立尝试机会,冗余就把总机会放大了。他描述的设计让各成员保存失败计数,但恢复流程必须经过多数派提交;被单独隔离的副本不能继续提供一份全新的猜测预算。这里要协调的不是仅供事后查看的日志,而是决定下一次请求是否还能被允许的状态。读这个例子时,可以把「保存了几份记录」和「谁有权消耗额度」分别画出来。它说明冗余与授权需要一起设计,不能只从备份数量推断可用性或安全性;具体保证仍限于演讲所描述的协议与信任假设。

原文与时间戳 · 2
every new unit you escrow to increases that maximum failure count
Behind the Scenes of iOS Security · ▶ 30:10–30:21
a majority quorum is required to proceed
Behind the Scenes of iOS Security · ▶ 31:22–31:27

重现昨天的结果,还需要哪一版规则?

Michael Schwern 用标签指向提交来讲 Git 分支。标签可以移到另一份提交,在他的示例中,先前提交仍可从历史中指认。Tom Scott 用时区说明另一类会变化的资料。他提醒读者要更新保存规则的文件,因为单靠固定偏移量不能涵盖不同地方和日期的规定。

要解释昨天的结果,保存当时的输入只是第一步。还要能找回当时使用的程序或规则。如果系统只记下一个总是指向当前版本的名称,旧输入仍在,也可能重现不出当时的结果。

原文与时间戳 · 2
just adding a label
[Linux.conf.au 2013] - Git For Ages 4 And Up · ▶ 23:25–23:29
as long as you keep that file updated
The Problem with Time & Timezones - Computerphile · ▶ 3:38–3:41

读完再想一步

如果两个请求同时更新同一账户,读者看到什么?事后还找得到旧值吗?