主讲人直言,很多技术大厂在线上实际运行的系统设计远非完美,即便身为分布式系统鼻祖的 Google 也不例外。例如早期 Google 的 HBase 实现中由于缺乏防护令牌(Fencing Token),导致两个节点同时认为自己拥有写权限,疯狂写入后直接把数据彻底写坏(Data Corrupted)。主讲人在早期使用 Google Hangouts 时,也频繁遭遇过极其严重的丢消息和延迟投递故障——自己发出的消息或是好友发送的内容,动辄在数小时之后才突然送达。哪怕是巨头打造的系统,在面对极端网络延迟与并发场景时,边界处理也经常翻车。
此时与会者 Lu Sun 在讨论区提及了“事件溯源(Event Sourcing)”。有听众联想到比特币(Bitcoin)的设计原理,即把所有交易记录在区块链这个公开账本中,计算当前余额时需把账户所有的历史交易打包对账累加。讲者澄清,Event Sourcing(约 2005 年提出)与比特币(2009 年出现)在概念上虽有时间跨度与本质区别,但在“保留不可变完整历史(Full History)而非仅存快照”的思路上是相通的。这与 Git 的版本控制思想也很相似:Git 记录 Commit 历史,并允许通过提交、合并与 Squash 打出版本树。然而,纯粹依赖全量历史进行计算在工业界也有现实短板:当数据量达到一定规模时,若应用每次都要把一整年的历史事件重新推演一遍,性能将极其低下。因此,系统必须在项目运行中引入定期快照(Snapshot),通过“快照 + 增量事件”来实现高效状态复原。
- **写时解决(Resolve on Write)**:在数据实际写入持久化存储之前拦截并解决冲突,若检测到冲突则执行特定的合并函数或直接抛出异常。
- **读时解决(Resolve on Read)**:写入时无脑追加或记录所有版本(如多版本有序映射),等到客户端读取数据时再交由应用逻辑完成冲突仲裁(关系型数据库多要求写时即确定具体值)。
```mermaid
flowchart LR
accTitle: 三种常见多主拓扑结构
accDescr: 环形拓扑为单向成环流动,星形拓扑以中央节点为枢纽,全互联拓扑各节点两两互联。
subgraph Circular["环形拓扑 (Circular)"]
direction LR
C1["Node 1"] --> C2["Node 2"]
C2 --> C3["Node 3"]
C3 --> C1
end
subgraph Star["星形拓扑 (Star)"]
direction TB
S_CTR["Center Node"]
S1["Node A"] --- S_CTR
S2["Node B"] --- S_CTR
S3["Node C"] --- S_CTR
end
subgraph AllToAll["全互联拓扑 (All-to-All)"]
direction TB
A1["Node X"] <--> A2["Node Y"]
A2 <--> A3["Node Z"]
A3 <--> A1
end
```
在全互联等多主架构中,另一个典型的隐患是因网络传输延迟不一导致“因果依赖倒置(Causality Violation)”。例如,主节点 1 写入数据 A 并向外复制,随后主节点 2 基于 A 写入了后续操作 B;但由于网络链路波动,第三个主节点可能先收到了 B 后收到了 A,导致本地回放顺序彻底错乱。针对这种并发与因果顺序冲突,理论上可以通过“版本向量(Version Vectors)”进行检测与追踪,但其实现逻辑极其繁杂,在实际工程应用中极具挑战。
---
[55:00](https://www.youtube.com/watch?v=vGb7JfpKFro&t=3300s) 无主复制(Leaderless Replication)与 Dynamo 架构哲学
[01:00:00](https://www.youtube.com/watch?v=vGb7JfpKFro&t=3600s) 副本修复机制:Read Repair 与 Anti-Entropy Process
在无主复制(Leaderless Replication)架构中,客户端并发读取多个副本时可能会发现版本不一致。例如读到两个 version 7 和一个 version 6,客户端就能明确知道 version 6 已经过时(outdated),随即主动通知该节点将其更新至 version 7,这种在读取路径上触发的纠错机制称为“读修复”(Read Repair)。除了 Read Repair,系统通常还会运行一个后台机制——“反熵过程”(Anti-Entropy Process)。该机制会在后台持续比对数据库不同副本之间的数值,一旦发现副本间存在不一致,便定位差异并纠正。
```mermaid
flowchart TD
accTitle: Replica Inconsistency Resolution
accDescr: Dynamo-style systems resolve inconsistent data via Read Repair on read paths and background Anti-Entropy using Merkle Trees.
subgraph ForeGround["前台读取路径 (Read Repair)"]
C["客户端读取多个 Replica"] -->|检测到 v6 与 v7| C
C -->|写入最新 v7 数据| R6["过期的 Replica (v6 -> v7)"]
end
```mermaid
flowchart LR
accTitle: Sloppy Quorum and Hinted Handoff
accDescr: Illustration of Sloppy Quorum using a neighbor node when designated nodes are unavailable, followed by Hinted Handoff.
在分布式系统的冲突解决(Conflict Resolution)中,业务场景往往决定了具体的技术选型。以购物车添加商品为例,如果系统在并发更新时无法判断谁先谁后,往往会默认把新增的 item 追加在最后——这种设计说白了就是为了促进用户消费,完全是由实际的业务用例(business use case)倒逼数据库设计的体现。
提到并发冲突处理,幻灯片上展示的 Version Vector(版本向量)复杂度极高。讲师直言今天不打算深入展开这个单节点因果依赖的 Version Vector,因为这种机制极其烧脑,讲起来"首先要把我自己绕进去,然后其次的话大家可能会被绕进去"。如果再将其扩展复制到 $N$ 个节点上,整体系统的状态与因果关系复杂度会呈爆炸式上升,建议感兴趣的同学课后自行阅读。
```mermaid
flowchart TD
accTitle: Version Vector vs Lamport Timestamp
accDescr: 对比版本向量与兰伯特时间戳在并发检测与全序生成上的不同定位
subgraph VV["Version Vector"]
V1["捕获并发写与因果依赖 (Causal Dependency)"]
V2["用于并发冲突检测与解决 (Conflict Resolution)"]
end
subgraph LT["Lamport Timestamp"]
L1["生成事件逻辑全序 (Total Order)"]
L2["无法区分两事件是因果相关还是真正并发"]
end
```
## Notable quotes
> [00:00](https://www.youtube.com/watch?v=vGb7JfpKFro&t=0s) 它的读写效率高很多,支持存储较复杂的数据结构,且当前业务数据不需要强持久性(durability)保证 — Scott Shi
> [35:00](https://www.youtube.com/watch?v=vGb7JfpKFro&t=2100s) 当你有很多 transaction 的时候不是问题,当你有很多 transaction compete 同一个 object 的时候也不是问题。一定会有一个 winner,winner will take everything,剩下的人多半都是 loser,loser 就得 stand back / stay back,等下一次 retry。 — Scott Shi
> [45:00](https://www.youtube.com/watch?v=vGb7JfpKFro&t=2700s) 解决冲突的责任到底在数据库,还是在应用层客户端? — Scott Shi
> [01:20:00](https://www.youtube.com/watch?v=vGb7JfpKFro&t=4800s) 首先要把我自己绕进去,然后其次的话大家可能会被绕进去 — Scott Shi
> [01:22:42](https://www.youtube.com/watch?v=vGb7JfpKFro&t=4962s) 那都是勇士啊,基本上都死得很惨 — Scott Shi
> [01:26:45](https://www.youtube.com/watch?v=vGb7JfpKFro&t=5205s) 2PC 和 Consensus(共识)不是替代关系,两者解决的问题不同,概念上有交集但本质偏正交(Orthogonal) — Scott Shi
> [01:30:18](https://www.youtube.com/watch?v=vGb7JfpKFro&t=5418s) Last-Write-Wins(LWW,最后写入者胜)机制绝对无法保证数据零丢失(Zero Data Loss) — Scott Shi
> [01:30:18](https://www.youtube.com/watch?v=vGb7JfpKFro&t=5418s) 你不理解也没事儿,但是你理解了肯定是对你有好处的——至少你不会在系统里给队友埋下一个巨大的坑 — Scott Shi
## Video description
In this view, we continue the discussion of replication, the slide could be found here: https://docs.google.com/presentation/d/1XfbqOmNh-yRqsVnznYFBd6hdjrreaef43TP9rcb2TXQ/edit
讲师 Scott Shi 在本讲中系统剖析了多主复制与无主复制的核心机制与工程权衡,强调分布式系统选型必须基于底层一致性语义与边界风险,切忌盲目依赖尽力而为架构承载强事务业务。
复制延迟引发的一致性破缺与工程底线 (5:14)
网络延迟的无界性使得跨副本同步可能出现长达数分钟乃至数小时的极端抖动,直接破坏单调读与因果一致性。在主从复制中,读请求分散到存在延迟的副本会导致读操作发生“时间倒流”;而跨分区延迟更可能导致“答复先于提问”的时序错乱。保障单调读的最简方案是按用户 ID 将读操作绑定至同一副本,而守护因果性仅需维护偏序(Partial Order),无需付出全序共识的高昂代价。
面对极端延迟与故障,系统设计必须推演最坏情况。讲师列举工业界教训指出,早期 Google HBase 因缺少防护令牌(Fencing Token)引发脑裂损坏数据,Google Hangouts 也曾发生数小时的消息延迟投递;Uber 曾尝试用 Kafka 支撑支付系统,但即便消息丢失率降至十亿分之一,在核心资金链路中仍属不可接受的架构风险。
多主架构的双花死局与冲突解决策略 (25:00)
跨数据中心部署的多主复制虽能降低地理延迟并提供容灾,但其核心痛点是并发异步写入导致的冲突。若在两地数据中心同时扣减同一账户余额,异步复制会导致双方在基于旧余额的前提下分别返回成功,最终引发灾难性的“双花”超付且无法轻易回滚。
彻底规避冲突的方案是将特定资源的写操作通过路由层强制收敛至单点 Leader,或承受吞吐极低、跨洲际延迟巨大的两阶段提交(2PC)。对于允许暂态不一致的业务,采用最后写入者胜(LWW)会因物理时钟偏移(Clock Drift)造成静默数据覆盖。更优路径是借助 CRDT 思想或读时解决,例如 Uber Blitz 客服平台将交互事件作为带 UUID 的记录追加至无序哈希表,写入完全免锁无冲突,再将数据还原与展示排序交由客户端业务逻辑处理。
无主复制的 Quorum 机制与脏读修复陷阱 (55:00)
源自 Amazon Dynamo 的无主复制彻底去除了中心主节点,依靠多数派投票($W + R > N$)换取极致的高可用性与无单点故障。系统依赖前台读修复(Read Repair)与基于 Merkle Tree 的后台反熵(Anti-Entropy)实现最终一致性,但后台修复进程会与在线事务竞争 CPU 和 I/O 资源,且 Voldemort 等未实现反熵的系统数据持久性会大打折扣。
在异常写入场景下,Quorum 会暴露严重的边界漏洞。若一次写入在 5 副本中仅落盘 1 个节点即报错中断,后续读操作凑巧读到该节点与 2 个旧节点时,若读修复按大版本号覆盖,反会将未达 Quorum 的失败写入“转正提交”,引发脏读。此外,Sloppy Quorum 与 Hinted Handoff 虽能在主副本不可用时借用邻居节点维持可用,但在网络分区下会导致读写集合完全无交集,造成暂态数据完全不可见。
复制模型定位与分布式事务辨析 (82:42)
三种复制模型各有适用边界:单主复制适合中小规模与强事务,但主节点故障转移有秒级不可用抖动;多主复制专注跨数据中心协同,写冲突治理是核心;无主复制属于“尽力而为”的高可用架构,适合购物车追加等宁增不减的场景,拿来强撑工作流或支付事务极易导致架构崩溃,如 Uber Cadence 强行搭载弱一致的 Cassandra 引发大量难以收敛的角标异常。
针对常见概念混淆,讲师澄清两阶段提交(2PC)与共识算法(Consensus)本质正交:2PC 解决跨分片、跨节点的原子提交,但协调者单点易引发阻塞;共识算法(如 Raft/Paxos)则是在不可靠网络中对状态达成全序一致。此外,线性一致性强调单对象的全局实时最新,事务强调跨多操作的 ACID 隔离,二者互不包含,唯有付出高昂延迟代价才能强行兼得。
分布式架构不存在万能模型,架构师必须清晰辨析系统一致性边界与业务长短事务的区别;在设计审查中警惕 LWW 丢数据、无主库造事务等认知盲区,守住数据持久化底线。
Source quotes
[0:00] Scott Shi: 它的读写效率高很多,支持存储较复杂的数据结构,且当前业务数据不需要强持久性(durability)保证
[35:00] Scott Shi: 当你有很多 transaction 的时候不是问题,当你有很多 transaction compete 同一个 object 的时候也不是问题。一定会有一个 winner,winner will take everything,剩下的人多半都是 loser,loser 就得 stand back / stay back,等下一次 retry。
[45:00] Scott Shi: 解决冲突的责任到底在数据库,还是在应用层客户端?
[80:00] Scott Shi: 首先要把我自己绕进去,然后其次的话大家可能会被绕进去
[82:42] Scott Shi: 那都是勇士啊,基本上都死得很惨
[86:45] Scott Shi: 2PC 和 Consensus(共识)不是替代关系,两者解决的问题不同,概念上有交集但本质偏正交(Orthogonal)
[90:18] Scott Shi: Last-Write-Wins(LWW,最后写入者胜)机制绝对无法保证数据零丢失(Zero Data Loss)
[90:18] Scott Shi: 你不理解也没事儿,但是你理解了肯定是对你有好处的——至少你不会在系统里给队友埋下一个巨大的坑
Original transcript
[0:00] 而且我这边有点心得就是说我感觉实际上很多时候你面这个System Design的时候它很难就是说你在45分钟大部分是45分钟到一个小时之内把这整个的流程就是从一开始collect requirements一直到最后的data schema那边全部走完很多时候我感觉可能就是一般你就看面试官会挑哪一块儿而他会让你具体讲讲我感觉很多面试官其实很关心你怎么样能够给一个例子把这整个系统end to end 跑一遍跑通然后如果这一步如果你能够把它说清楚的话,我感觉基本上这个面试就没什么问题,然后之后再来说,反正就是我的意思是说,如果时间很紧的话,确保就是能够,你设计了这个系统,按-to-end 跑一遍,就是给它展示一遍,就像你写完程序之后给它演示一遍,你test case一样,然后这样子之后有多余的时间你再来做其他的API,或者是database,或dataschema,因为很难,45分钟,之内基本上是不可能把所有东西都cover到否则你也cover就是不会很detail所以说但是我感觉我个人经验是这个Antoine的这个过程是很多面试官是非常care的对的,其实也看面试官,一般来说安团案的话,其实System Design,我觉得如果是两个人在一个频道上聊得可以很快的,System Design两个人在一个频道上,比如说为什么要Redis,然后简单聊一句,这个Redis效率高很多,你可以存一些比较复杂的Data Structure,然后你这个Data不需要Durability,很快就聊完了,其实System Design我觉得很重要的一点是,你聊的一定要在一个频道上,是吧,有点入门的理解对于这个System Design然后你要是和面试官聊的不是一个频道上的话这个System Design多半就怪了然后其次的话也要看面试官想考什么有的时候面试官想考的是比如说你对Database的理解,有的时候就是更多想考察的是不一样的地方是吧?但我觉得这点其实挺好的,你碰上这点说的挺好的,就是说应该有一个Antoine的例子是吧?就是很多时候有一个Antoine例子,甚至面试官没有主动提的话,你也可以把一个Antoine例子举出来是吧,一开始就举个安图案例子,然后再讨论每一部分的时候,把这个安图案的例子然后再写进去写一个example然后这样讨论过来的话我觉得多半就没什么问题了是好的,然后这块我们接着聊,我还是想在这个之前说一下,我现在大概估计还是到8月底之前结束这个System Design所有的讨论,之后的话我们可能有一些AdHoc的这种,或者是在群里面有些问题的话,我们可以一个问题讨论,但是我还是想在8月底之前结束,然后现在的话我觉得结束的话,这个System Design这块的话,我可能加一些跟之前不一样的System Design,就比如说,比如说Design a parking lot 这种有点像OO Design那种 Design Parking Lot这种因为这个其实有的公司也面Design Parking Lot也面它和我们之前学的System Design的风格不一样然后但是挺重要的一方面我知道Amazon喜欢面这个Design Parking Lot其他地方也喜欢面Design Parking Lot这个的话我们到时候加一两节我希望就是一到两节吧然后这样的话我们可以思考一下这个Parking Lot这种东西的DesignOO的Design对,然后这是一点,然后其次的话就是我尽量把这本书走完,就是这个Design Data Intensive Application这本书走完嗯后面的话这几张都比较难,我尽量还是讲的稍微慢一点,要么就多的时间长一点,要么把它break成两张。但是后面这几张都比较难的,所以这个还是尽量把这本书做完,所以大概还有大概还有五周左右,然后五周的话,加上这次可能有11次左右,我尽量把这个都搅完好好,我们接着讲这个replication,我们上次是讲了一个single leader replication。然后是一个Primary到两个SecondaryCopy,是吧?可能今天就是从这开始讲然后今天任务是把剩下的讲完就是Multi-Leader Replication 和 Leaderless Replication然后 again就是这个replication这张真的非常复杂,相对来说是比较复杂的
[5:00] 也就是这个system,就CPU system 里面相对来说比较核心的一部分了所以大家的话还是就是花点时间再额外看一看这个slides然后再思考一下这个slides是吧然后我们接着看这个 monotonic rateMonotonic read 是什么呢?保证什么呢?就是你从一个SIM Replica读的时候,你读的时候都从SIM Replica读,那你就可以保证Monotonic Grid。但什么时候不能保证Monotonic Grid呢?就是你读同一个Data,你比如说这种情况下,这个User一二三次,insert了一个comments,说这个sounds good,然后这个comments呢在replicate两个followers的时候,它时间是不一样的,比如说在时间1的时候,它就replicate到followers1,所以你在时间1之后,如果从followers1读的话,你就读到这个comments,但你从followers2读的时候,你就读不到这个comments了。这种情况下的话,我们看到从follow 1读的时候,我们是看到这个comments,然后你再读的时候,这个request 又到follow 2了,然后就读不到这个comments了。所以你看到这个data,实际是travel back to time,就是说,你看到这个data,实际上是revoke了,revert到之前的一个version了。有点像这个时间回溯了,time goes backwards,这个anomaly有些情况下是影响比较大的,其实任何情况下都影响比较大,比如说你读了一个Facebook feeds,你看到一个,比如说川普在Facebook上发了一篇文章,然后你一秒钟前看了,refresh又看不到了,然后你这时候可能就以为是不是这个文章也剔除掉了,假设你没有refresh的话,其实对user是造成了很多confusion的,那到底是在refresh的时候这文章出现了,到底是Trump在自己之间把这篇文章删掉了呢?还是他这个设计的是你读到不同的replica,然后你就是go back to time, go back, backward to time 了?这个其实是区分不出来的,从user 角度是区分不出来的,这些user experience 会很糟糕。所以我们怎么样能保证没有这个monotonic read呢?就是怎么样能保证有monotonic read呢?其实最简单的方式就是你每个read都去same replica就可以了,这个monotonic read的话,它是这会出现这个go backwards to time的,实际上是你去不同的replica读这个data的缘故,然后才go back towards time所以这个的话是这个可以保证你没有monotonic read但是这有同样的问题这个同样的问题是什么呢?这个同样的问题是什么呢?就是你这个user呢其实是你的request wrote到一个server了但是如果这个server fill掉怎么办?是吧?你如果这个server fill掉的话你还是需要去另一个replica读那你去另一个replica读的时候你可能就同样的问题就会出现如果timing不好的话你就会确实看到这个时间回溯了但是我们说server down这个概率是几千万分之一我觉得Sumle rule的话就在System Design中除非是这种前的transaction这种是吧否则的话如果它出现的概率是几千万分之一或上亿分之一的话很多时候你就不考虑了,不需要考虑那么多细节了那就像这种情况下,我们server的request,就是user的request是总是 rode 到其中一个database server假设Database server done的话,我们去另一个follow,这种情况下可能会broke monotonic read 的 assumption,但是如果是这种 comments read,我们就不考虑了,只要不是这种 transfer money 这种事情非常严肃的问题的话,你是不考虑这个问题的,或者是除非面试官强烈要求你要做这个事情,否则你是不考虑这种非常小概率的事件。进行优化是吧,然后其次的话在这个Data Center里面,所有的这个拜暂停 failure,拜暂停 failure,都是不被考虑的,就是你假设你这个Data Center里面所有的 nodes都是 friendly,都是 auto good face,就是出于好心的,不是这个 malicious nodes,这个是不考虑的,因为你这个考虑的话,这个就是 cost efficiency,是完全就是这个 cost 是完全不能 cover the efficiency 的。好,然后,所以我们在讨论这个 monotonic rate 为什么很重要的时候,是因为它会broke 一个Assumption,broke一个是什么Assumption呢?就是casualty assumption,就是因果效应,casualty就是因果效应。比如说CakePulse问Cake你能看到未来多久之后是吧然后Cake在听到这个Pulse的问题以后说我大概能看到未来10秒钟之后它这个呢,在这个数据呢,这两个数据呢,它写进去的时候,可能就写到不同的地儿了,所以这个从某个user来看的话,从这个observer的角度来看的话,因为这个cake的回画,是先写到这个partition2的leader上,然后先replicate到partition2的leader上,
[10:00] 然后这个问话就是这个这个问话呢实际上它这个就是copy 的时候它时间要久一点,它这个在partition 1 的时候,因为它这两个在不同的partition上在partition 1 的时候它这个时间copy 要久一点,所以就导致了好像这个答在问之前对,这个打在问之前,所以这个的话是casualty呢,guarantee是比较复杂的一点比较复杂一点,就是我们在这张之后也会有额外的讨论是吧,怎么样guarantee这个casualty,然后在这个consensus这张也会有额外的考虑是吧,怎么样guarantee这个casualty,这个casualty的话,你可以认为这样子,如果你在consensus的角度来讲的话,你如果guarantee这个casualty的话,你可以是个partial order你只要有 partial order 就可以 guarantee 这个 casualty 了但如果你想保证所有的这个对话全部是 order 的话 你要 total order在Total Order的话就需要全部的consensus了,这个时间效率就很低,但你只想保留这个casualty的话,这个关系的话,就是你允许concurrent这个data出现的话,你只要reserve这个partial order就可以了。这个partial order和这个total order这个感觉和这个coding不是有一个题吗?就是partial order的话,我记得我很久之前面那个Twitter的时候,他给我出了一个partial order的题,然后这个题我当时没有答出来,2014年,2013年的时候,我当时没有答出来。然后我过了好几个月后我都没想到怎么做这个patch order的题反正这个pass order就是你用pass order的话可以guarantee这个casual date然后其次的话就是大家反正遇到什么想不通的题的话就是也可以讨论一下然后也可以思考一下就是我觉得很多时候我之前面试过的题就是过了好几年后来想通了怎么回事他想考虽了什么点但是我觉得也不迟吧反正只要能想通就可以并且如果你面试的足够多的话,其实说的题都是那些套路,如果面试足够多的话,大概都知道什么套路了。然后这个基本上能保证你之后的面试基本上都能过,稍微准备一下的话,然后再加一些经验的话,基本上这个面试其实是和这个工作是不直接相关的,和这个是不直接相关的,是对。好我们接着谈剩下的所以我们讨论的话就是这几个问题,这几个consensus break,这几个这几个guarantee break 都是根据 replication lags 相关的好所以说我们要怎么样解决这个replication lag呢?所以我们可以这么讲,如果我们是在一个eventually consistent的这个system里面,我们在最早的时候也讲过,所有的replication都是通过networking的,然后networking是unbounded的。所以假设你对这个replication的时候,你要思考一下,就是做entrl要做最坏的情况的考虑最坏的情况考虑就是如果这个情况是最糟的情况下的话会发生什么比如说我们的replication大部分时候都在99%、p99.9%都是一秒钟以下是吧,一秒钟以下,一秒钟已经很长了。但是假设这个replication在这1/1000%的概率的时候,它是几分钟甚至几个小时那会发生什么如果你说没有问题那我们这个系统就非常好了就是这个guarantee是非常好的就是这个guarantee就非常好的就没有什么问题了但是你说这个如果这个delay就是potential的这个replication的delay呢几个小时会有disastrous result那这个系统其实设计的就我们可能考虑一下是不是这个System Design要额外思考一下很多时候大公司现在已有用的这个system design不一定是很好的system design,我们看到很多这个Google的例子,我看到很多Google例子,比如说这个HBase写的时候没有fancing token,然后就导致这个HBase自己写的写的就挂掉了,就它自己的data就crofted了,Google是自己就干过这种事情,就是HBase写的时候,然后其次的话,我记得我早些时候用Google hunt的时候,Google hunt自己动不动,就开始丢message了就比如说我发了一个message然后几小时后才deliver了或者别人发过Message几小时后才deliver了,这是Google之前常干的事。Google相当于是distribute system的鼻祖了,经常干这种事情。没有想法,这个千分之一的case如果出现的话怎么处理。Message Deliver,这个Delay几个小时事情我见过不止一次,我觉得这个做的就比较糟糕。Uber也干过很多很扯淡的事情,比如说Payment走Cafka,是吧?我觉得我当时还是比较惊呆的后来虽然有Lossless Kafka 但Lossless Kafka也有Loss因为这个只要是这个Caseless Kafka,我记得之前也有Loss,它的Loss的概率其实很低而已
[15:00] 普通的 Kafka 落实概率可能是一万百万分之一啊,但是Lossless Kephala可能在这上面再加个千万分之一或者是什么,就是十亿分之一是吧,但是它还是有Loss的,还是有Loss的所以这个就不应该拿 Kafka 作为 kill 是吧? 你还是应该拿 database 作为 kill 再加上 replicate 几次,这个 guarantee 是远远比 Kafka 强的当时就是你 deliver feature 的时候,你一个小组里面可能就一两个人说话算,然后 deliver 做完了以后就发现各种扯淡的事情。还有另一个讨论也是很有趣的,就是说我们Uber不是有一个叫Cadence的那个Flow吗?Cadence的这个Workflow,然后Cadence workflow是用什么实验呢?它的database是用这个Cassandra实验的。所以你 Cadence 是 Guarantee Durability 的, Guarantee Durability, Guarantee State Fold然后你最后你的这个backend用了一个best effort 的一个database你可以想想看这个Cadence的Engineer遇见这种Counter Case是很头疼的,非常头疼,非常头疼。所以他们就是,当时选的时候就说这个为什么选Cadence用这个Cassandra呢?是当时Cadence的设计人叫Maxim,现在他已经跳出去专门做Cadence的startup了。他当时也是Amazon Simple Workflow的Founding Engineer,他在Amazon先设计了Simple Workflow,然后被Uber挖过来做Cadence,现在做开源版的Amazon Simple Workflow。也没有反对嘛,因为他,你想他这个30年经验是吧,然后又是Single workflow 的这个创始人是吧,也是放电池尼尔,他说用 Cassandra 就行,那就是用 Cassandra 结果发现之后的话,好,这个 Connor case 完全没法处理导致现在的话,maintain起来,就出各种各样的问题,然后中间也造成了好几个project rollout的时候 failure,是吧?就是这个counter case完全没法处理。所以我说这个point就是,作为一个Engineer来说,始终要考虑Worth Case的,你百万分之一的这个概率发生,如果这个发生了以后是Dizastrous,那你就是要考虑一下是不是我们要换一个东西,然后其次的话,你其实作为一个Engineer来讲,90%的时间,特别是back-end的时间,90%的时间都在和database打交道,是吧?你这个database选的什么,如果出问题的话,你就不是伤筋动骨的事了,就是整个人要重新写一遍了,整个人要重新换一遍的事。你如果是这个data model换了,就是要做data migration,伤筋动骨的事。你要做database换了,这个整个人都感觉要换一遍的感觉。就比伤筋动股还要严重一下所以这个设计的时候要多考虑一下然后特别是我觉得这个基础的这块基础的东西还是要非常扎实的就是要考虑到可能潜在的情况然后这个是很重要的特别是你的use case比较广的话作为一个好的entity的话往往是批判性是比他这个赞同性要强的就是你批判批判性是永远是比赞同性强的这是我直观的几个想法吧大家这块有什么好的例子也分享一下的话有没有什么更好的例子可以分享一下谢谢大家我看就还有个chat我看一下Amino Simple Workflow是啥啊?Amino Simple Workflow是,你可以搜一下就叫Amino Simple Workflow吧它是就是说本来是一个执行一大段,就是你把所有的那个task,你说先define一个task,一堆task,然后把这个task定义成一个DAJ的graph,然后这Emerald Simple Workflow就开始执行这个task的graph了。它比较适合什么呢?比如说,有些business use case,比如说你发生了一个transaction,你发生了一个 transaction 以后你要 generate invoice 是吧?然后你 generate invoice 以后你还需要去 credit card, swap credit card 是吧?然后你比如说这个,比如说之前讨论的这个怎么样,就是 periodically 每个月的时候你swap the credit card,你就可以用这个 workflow 来做。然后你像整个 Uber Eats 是可以在这个用这个 simple workflow 来做的,可以用 Amazon simple workflow 做的,它实际上也是用 Cadence 做的。这个Durability 还有这个Data Consistency 有时候没法Guarantee的话有各种各样的问题是这么一个东西就说白了是你define task然后每个task是executable不管是做计算还是做存储还是做任何具体的东西然后你再define一个graph然后这个graph是个DAJ然后DAJgraph然后你把这个task的连接
[20:00] 就变成一个 workflow了然后它这个 framework 呢它这个 cadency framework 呢能 guarantee 你这个 workflow 从头执行到尾从这个起点执行到终点有点像一个有线状态机,然后它帮你guarantee这个执行碗建盈说不是Paper吗?不是Paper啊Piper 你可以这么认为,你可以用Cadence写一个Piper因为这个Piper其实是这个Open Source的AirflowPiper是我们copy Airflow 的但是我们copy了一个版本以后,我们就自己做这个版本的维护了你可以认为这个Airflow或这个Piper呢,是可以用这个Cadence写一遍的,就是你在Cadence的基础上写一个Piper并不复杂你知道吧 就在Cadence的基础上写一个Piper并不复杂 是这样子的所以它跟Piper是不一样的Piper的话它现在设计基本上就是执行一些这个batch job什么batch job 我给你举简单几个例子就比如说你现在要sign promotion email 是吧你就是一个batch job 然后就是每天执行下sign promotion email或者是说我看一下哪些user还有欠款没有还给Uber 是吧有欠款没有还 那我就到时候就是每天的时候看到这个欠款没有还进行怎么样处理啊,这种 batch job,它不跟 request 相关嘛,一般的时候我们都说 request response 嘛,就是 transaction request response 嘛,这个是跟 request 不相关的 batch processing,还有一些的话,analytical 这块有很多 paper job他很多时候是把这个data从这个transaction database转到analytic database 然后进行额外处理这个Cadence和Piper的关系是先有Cadence和有Pepper 是吧?你可以认为这个Cadence是Pepper的这个 backbone framework两个是不一样的谢谢大家好,我们接着讨论剩下的这款的话,然后我看一下这款谢谢大家我们讨论哪了,对我们讨论了说这个,对我们要考虑的时候很多时候是worst case,就是如果最坏的情况下发生的话会有什么样的结果,所以说如果是这种情况下有最坏的情况下发生的话,那你不会有很坏的结果的话,那么就没事了是吧?所以最好的情况是什么呢最好的情况是你的application developer就是作为一个application developer你不是infra developer或者不是system developer你不需要关注一些replication issues,就是对你来说,你的replication不存在,对你来说你只有single copy of data,对于developer的角度来讲的话是最好的。我面对的database,我不知道它怎么实践的,我不知道这个底层database怎么实践,但对我来说,这个database做了一个存和一个去一个存一个取 是吧 一个write 一个write 然后我期待于我刚存的data我读出来以后就是我刚存的data 是吧不是一些非常 weird 的 result,这种情况下的话,这个 abstraction 做最好的。所以这就是为什么有 transaction 的存在,是吧?Transaction 这个存在的原因就是,他希望把这个系统中特别 messy 的那部分,特别复杂的那部分,包括 durability,包括主要的 concurrency control,怎么办我这个conference control从database角度就帮你处理掉了所以是希望这样子的但是呢,这个Transaction,其实我看到群里面有讨论说这个Business Transaction 和这个Database Transaction 不一样的,我记得上周也有讨论了,Business Transaction 就是整个订票是一个Transaction,但你这个Database Transaction 是你任何一个Commit,是吧?有很多时候Developer 决定的,任何时候一个Commit是一个Transaction,更多讲究的是一个非常就是任何一个Request 希望就contain了任何东西,你尽量不要有这个Interactive Transaction,尽量是你一个request过来以后就是一个transaction我把你的request全部执行完以后就给你返回你不要这种open的transaction,不要interactive transaction这也是近几十年的一个系统设计的改变吧之前的话,一个大的transaction,就是business transaction,就是database transaction后来整个系统的设计这个观念就改变了好,所以说这个database这块transaction和这个distributed transaction是有额外的讨论的,我们之后的话会讨论一下。现在的话有两个观点,就是有的人就说在这个distributed system里面这个single node transaction不应该存在因为他这个cost太高了但有的人说
[25:00] Single node transaction还是应该存在的,因为它难以避免的会很重要。在distribute system里面,我们还是应该满足这个transaction,但是cross node transaction还是应该满足的。但是这两个观点各有各的好处吧我们在之后的这个Transaction那张也会仔细的讨论一下不同的Transaction我们这个Single node replication讲完了我们现在开始讨论Multi node replication嗯我们说这个Single Node replication呢,就相对比较简单吧,就是一个Node是吧,你所有的写都是写到一个Leader上,然后replicate到不同的Follower上MultiNode replication相对来说是更实用的一个replication现在的话不管是这个Facebook 还是Uber 都是用的MarketNode replicationMulti-leader replication 什么原因呢?就是说你的这个read和read是找你你Lentancy最近的Data Center就是说你的Write和Write同一个用户,同一个User你的Write和Write可能不是在同一个Data Center上有多种原因,一个的话最重要的原因就是它的performance会更好一点,是吧?你可以找离自己更近的这个Data Center你比如说你在 China 的话,你可能在这个 China 的 data center 是吧,你在 US 的话,可能在 US 的 data center。而不需要说,哎,我这个 user wrote 到这个 US 的,但我实际上在 China,那我整个这个 run trip 的话就加200毫秒。the performance就很糟糕了所以更多时候为了performance原因然后其次的话在你Datacenter有outage的话你也可以从另一个Datacenter 说你PrimaryDatacenter Outage的话你就去另一个Datacenter把说的request wrote到另一个Data Center然后再其次的话,这个你有Network的话,比如说你连不到你这个最近的Data Center的话,你可以把你的request wrote到远一点的Data Center并且这个Network,Network是可能trigger一些非常非常weird的issueNetwork 可以吹发出很多VR的意料不管是在这个Rraft,还是在这个Paxos,在Consensus algorithm里面,有一些非常非常worst-case scenario都是由Network来造成的,并且这个Network可以有一个非常简单的Network failure,然后就造成了一个非常非常复杂的一个这个issue,就是这个就不能reach consensus,或者reach consensus的这个收敛速度就很慢了。所以这个Data Center Outage和Network是一定会发生的,所以我们这个Mari Data Center这个Trade-Off呢基本上是业界达成共识的,就是production里面,基本上还是以Mari Data Center比较特别到你到一定规模的时候,这个Mari Data Center是难免的一个一个进层 蓝面的一个里层就是你变成一个market data center就是你的reader和reader可能到roll到不同的data center上那Mati Data Center呢我们可以看一下之前的这个这个是什么呢?就是什么意思呢?就是说你这个rate和rate呢,是写到,比如说我们这个rate和rate是写到这个theta center 1的,你的锐利和Ride都写到DL11特别是Ride写到DL11它这个change 是会Copy到Data Center 1 的Follower 同时在 Cross Data Center copy到Data Center 2 的Leader然后再把这个Change呢和这个Data Center 2的Leader进行就是"Resolve"这些Conflictresolve conflict,我们之后会讲这个conflict这两个conflict resolve 了以后,然后再push到datacenter2的这个follower上所以它是三层的结构其实是四层的结构第一层就是你这个Primary Data Center Leader 是Source of TruthPrimary data center leader 是 source of truth,它是包含了你这个 record,你这个 transaction, source of truth,然后这个 follower 是 copy of source of truth,所以这个多半也是没有问题的,如果这个 data center leader 当掉的话,这个 follower 多半是有最新的数据的,可能会有一些,如果是 asynchronous 的 replica 的话,可能会有一些丢失数据,但是它基本上是拿到最新数据的,因为这个就是in data center replication是时间相对来说是比较稳定一些可控的但是这个cross data center replication呢这个时间是很长的因为你很多时候这个travels的地点也极其远是吧你可能整个要横跨美国大陆啊横跨个几千个mile这个时间本身就很长可能要加个几十毫秒到一百毫秒甚至两百毫秒都可能并且你过来的时候你这个可能就和这个leader呢是有conflict的你需要resolve conflict然后这个Resolve Conflict的以后,然后你再把它写到这个Follower上,所以这个其实是四层吧,就是这是一层,这是一层,这是第二层,这是第三层,这是第四层,其实是四层的这个Data,其实是有四个,其实是有两个Copy的Data两种版本的data 然后再加上两个版本的这个啊就是delayed replica,所以实际上是四个copied data四个甚至更多
[30:00] 就是你有可能这个Leader replicate两份到Followerreplicate到Follower1和Follower2然后Follower1和Follower2的Data不一样所以你在这个实际生活中Practical Speaking你在Facebook的Data你可能有六个Copy是吧你Primary Leader一份然后你Follower1一份Follower2一份然后Secondary Leader一份然后Secondary Follower1一份Follower2一份这六份data可能在某个时间节点上是都不一样的那你如果这个leader挂掉了或者这个leader有conflict怎么resolve conflict的话这个是比较复杂的一个问题也是这个multi data center最核心的问题相对于这个singling data center最核心的问题怎么样resolve conflict好 这块的话就是讲了这个multi leader这个MultiLeader的很多时候这个EU的这个Transactional Database已经支持了像比如说MySQL的话MySQL的话这个有一个External Tool叫Townson Replica是支持这个MySQL的这个MultiLeader的Configuration然后BDR也是支持这个Configuration然后Goldengate的话也是支持这个对Oracle来说是支持这个multi-leader replication所以这个multi-leader replication就是我们怎么样解决conflict是比较复杂的我们之后也会讨论一下怎么它这个conflict可能发生的格式这款是一个具体的use case我就不讨论了大家有兴趣的话可以读一下就是offline-ended的use case就是一个用的 case 具体的 use case另一个 use case 就是比如说 Google Docs 的 edit也是多种人在同时 edit 的同一个 document这个也是一个 use case 我在这块也不考虑了就是不讨论了 我们只讨论这块最核心的问题就是 conflict这块 conflict 就比如说举了一个这个例子User 1 和 user 2 同时在 modify 一个 page这个 page 呢 title 是 A就是User1和User2同时Modify这个Page,Title是A然后User1把这个Title改成B了然后User2把这个Title改成C了然后他们写在自己的PrimaryData Center的时候都没有问题就是在Data Center Leader1这块这个Title就变成B了,在Leader2这块这个Title就变成C了,就写进去的时候没有问题因为你没有任何跟你competing没有concurrent run,没有人跟你competing之后也没有问题的但是它replicate到另一个data center的时候就发现有conflict了因为为什么呢因为它这个old value是从A到C的但是它到这个data center的时候到data center这个到leader 1的时候它这个值已经不是A了已经变成B了那所以就conflict了然后其次一样的这个leader 1的change到leader 2的时候它是从A改成B的但是现在这个Leader2的这个值不是A这Leader2的值是C那改成B的话是不是会有问题是吧这个可以想象一个Account的Transaction就是User1和User2同时对这个Company的Account进行TransactionUser1从这个CompanyAccount滑走了10个MillionCompanyAccount只有15个Million滑走了10个Million然后在这写说没问题我滑走10个Million然后User2又从这个CompanyAccount滑走了另10个Million另外10个million然后一对比说我滑走10个million的assumption是你这个account里面有15个million所以我滑走了10个million但是到这个当你cross data center replicated 过程的时候观点不是这个assumption15个million就不是了因为已经滑走10个million已经变成5个million了这种情况下的话这个就有conflict 是吧你不能这块滑走10个million然后另一个又滑走10个million已经不是了,因为已经滑走10个million,变成5个million了这种情况下的话,这个就有conflict,是吧你不能这块滑走10个million然后另一个又滑走10个million你没有20个million了,去滑,是吧所以就是account的原因这个问题会变得极其复杂为什么复杂呢这个为什么说,我们说为什么说这个和这个single node的concurrency,这个conflict不一样呢是因为很多时候你为了performance你只要在这个primary data center上只要满足你没有任何conflict你就返回给user ok了所以这种情况下的话我们不管对user 1 说你拿到10个million了跟user 2 说你拿到10个million都返回的是 ok我们这时候如果在revoke的话他们可能有其他的promise了是吧比如说他拿了10个million以后他可能已经答应下游的公司说我已经要买你的设备了是吧这种情况下的话你就会有其他问题你这个assumption就被打断了所以这个conflict就必须被resolve这种情况下的话就变成一个死局了你假设自己有20个命令但实际上你只有15个命令但是连续划走两个10个命令并且都返回的是OK好所以说我们在这个market data center的时候
[35:00] 你实际上是Asynchronized Conflict Detection, 不像是一个Single Node, 你是Synchronized Conflict Detection,在Mari-Diesel Center是Asynchronized Conflict Detection所以你这个要想办法解决这个问题是吧你不能两个人request到不同datacenter同时滑走10个million这个问题是不能出现的是吧这种情况下是不能出现的所以说我们怎么样解决这个问题呢最简单的解决方式是减少conflict发生的可能就说我们所有的这个right啊走同样的leader,那这个conflict就不会发生了,是吧?你要划走company A 的钱,那你所有的request都去leader1里面去划,那你这个conflict是没有发生的那你就不可能出现了,因为毕竟Leader1的话,它这个Data是consistent的是吧,最多是concurrency control的问题,两个人要同时滑的话,你做这个transaction的时候,一定有一个人先执行是吧,我之前那个Lead mentor经常跟我说,啊当你有很多transaction不是问题,当你有很多transaction的时候不是问题。但是你有transaction complete同一个object的时候也不是问题。当你有很多transaction complete同一个object的时候,一定会有一个winner。那 winner 会 take everything 剩下的人多半都是 loser 那 loser 的话就得 stand back, stay back, 等下一次再 retry是吧 当你所有request都到同一个datacenter的时候不是问题你competing同一个resource不是问题 但你一定会有一个winner甚至可能没有winner,但最多只有一个winner最多只有一个 Winner, concurrently request,最多只有一个 Winner, Winner will take everything, and then leader will retry, will be a bot.是这样子的结果嗯所以这种情况下的话,如果这个request,就是所有的划钱的request都到同一个leader的话,这个事情是不会出现的。然后如果不是这个样子的话,就是说如果不是这种像划钱的case的话,我这块说,如果是这种strong transaction的例子的话,你基本上只有一种选择,就是说你只有一种选择,就是你说的request要到同一个leader上。基本上只有这一种选择有另一种选择什么是Synchronize Configure Conflict Resolving 什么意思呢?你在Leader1写Transaction的时候,同时在Leader2上也同时开一个Transaction就是这两个相当于是就相当于做 two-phase commit 了2-phase commit了,这个效率是非常低的在Leader1和Leader2同时开一个transaction这个效率是非常低的,所以系统一般是不被考虑2-phase commit一般是不被考虑的所以做transaction的角度来讲的话Multi-leaders setup是非常dangerous的你一定要保证你尤其只有一个datacenter在处理你的transaction当你进行这个Data Center fill over 的时候,你必须保证之前的这个Data Center,所有的这个Change已经 committed了,然后才能开始另一个Data Center的 survey。是吧,这个是有一些timing,如果设计的话要仔细考虑的,要仔细考虑的,你总是有一些engineering solution 能解决的,但是核心的观点就是,你只有在任何一段时间,你只有一个data center在SERV,只有一个Data Center里面的一个Leader在SERV的Transaction,那就不会出现这个Double Spending的情况,这个情况有个专用的名字叫Double Spending,包括比特币设计的时候也提到很多次的Double Spending的情况。好 然后然后其次如果不是这种transaction情况的话,就是你允许这种,就是不是这种transaction,这种非常strong的这个要求的情况下的话你允许有一些不一样的state 是吧你最后只要convert到一个consistent state 去啊eventually consistent 就可以了 是吧只要 eventually consist of a state 就可以的话那这种情况下 我们有多种方式可以解决 是吧比如说这个比如说这个常见的方式的话就是因为你都是两个都是concurrent嘛,我们比如说可以用last right win这个方式Not the right wing,就是说当你有 concurrent right 的时候last write 就是overwrite 之前的write但是这个last right fin是有一个covid,是有一个陷阱的,我们之前最早的一期的时候,就是5月份的时候讲过一期的时候,这个data node,就是这个node的时间是不一样的,所以你很有可能发现这种情况,就是你在nodeA上和nodeB上,Node A的时间,这个 timer,这个clock是比Node B慢两分钟的,有可能。就是Node A的时间是比Node B慢两分钟的。然后你新来了一个request实际上是先写到B上,后写到A上。就是说你新来一个request先写到B上后写到A上从绝对的时间来讲那这种情况下的话那你是不是A的时间应该是最后的结果但是因为A的时间慢了两分钟
[40:00] 所以最后跟B compare,然后又被revoque了,是吧?B的结果变成最后结果,因为A的时间慢了,所以这话其实会有data loss,从你的customer角度来讲的话,从你customer角度来讲,observer的角度来讲的话,我先写了一个1,再写了一个2,最后返回我的是1。就从customer角度来讲,我先写了一个1,再写了一个2,如果用last right win 的话,有非常小的概率,最后返回我的是1,你知道吧?就是你实际上是broke了这个guarantee 的所以任何用Lacelet-Vin的这个mechanism都有这种问题啊,都有这种问题,就是说你实际上是可能是有 data loss 的,并且是非常 subtle 的 data loss 的,你不可能,你很多时候 detect 不出来你有 data loss,这个就是根据这个 clock,就是根据这个时钟有这个,在不同机器上有这个 screw 的原因,就是它就时钟有 drift 的原因,clock drift 的原因,任何用 last right thing,就是当你读这个 database 的时候,比如说Cassandra是用Lasthreat Fin的你知道Cassandra是用Lasthreat Fin的话你本能的想法就是它不guarantee你的data是最新的data也有可能被旧的data覆盖新的data是可能的因为他用 last thread finish 是吧然后其次的话是另一种就是你可以做这个怎么样去detect Winner呢?是你可以给每个 Replica 一个 Unique ID 然后这个 Replica ID 高一点的那就把 Replica ID 低一点的这个 Write 就 overwrite 掉了这个也是有Data Loss,这个Data Loss的可能性更高,是吧?你user给A写了一个值,然后给B写了一个值,然后先写的1再写的2,然后因为这个写1的这个Data ID更高一点,然后就把这个2给overwrite的话,这个Data Loss更明显一点。这个last write win这个Data Loss,比较不容易发现,但是就是你有一个这个概念以后,你一查这个可能性,counter case是有可能用的话,这个是很明显的。就是还是比较致命的一件事然后再其次的话就是最新的话就是有一些近几年我记得可能是14年以后吧有一个叫CRBT的一个model CRDT的一个modelCRDT的一个model,我忘了全称是什么了,后面也有,CRDT的一个model,这个model很多时候也比较直观,有点像这个unordered set,是说你在这个unordered set里面加值的时候,你不管是+1和+2都无所谓是吧,你+1加进去,+2加进去的话,反正这两个共存,就是1和2都是存在里面,那你最后怎么解读是你的问题,这个Uber的Blitz Platform是这么实践的,这个database就很有趣,这个database实践是很有趣的就是说,你现在有个database,你有个resource,比如说这个ID是1,从这个1的object里面写东西你往这里面写东西我接受你写的任何东西你不管这个写是从node1写的还是从node2写的,我都不看,我接受你写的任何东西。就是你写我任何东西我都保留下来然后当你读这个东西的时候,我把你所有的写的record返回给你我们就拿Blitz作为例子,我们就举了Uber的一个例子。Blitz是一个Customer Serving的一个platform,他这个里面呢,可能就是他可能会比如说我要返回这个,我要说这个Uber有一单东西有问题是吧,我要向Uber客服说一件事,我就给他说,我就进建了一个Biz Tickets,我对Uber客服说一件事。然后我们这中间可能有很多交流,不是交流,有很多交流,是吧?比如说我写了一点话给客服,客服写了点话给我,是吧?然后包含有其他user,看了一下这个ticket,是吧,我比如说,我写了一个ticket,然后,然后,比如说Mike看了眼这个ticket,是吧?然后这也是一个action他所有的action,他这个ticket是一个大的hashmap你可以认为这个ticket是一个非常大的hashmap,on order的hashmap然后他这个key是random generated的key,就是hashmap的key是random generated的key然后他把所有的action写到这个HashMap里面所以这个写是很好写的,不管是来自于Datacenter1,Datacenter2,无所谓,我就把你放在HashMap里面,也不可能有conflict,因为这个CaseUID嘛,就是conflict的可能性基本的原因,是吧,我所有的写都写进来。但我进行读的时候,那我就把所有的action读了,这个action包含我所有的交互是吧,我读。我给客服发信,客服给我发信,然后其他用户看这个message,所有这个交互读下来,然后是client responsibility去怎么样显示这个object
[45:00] should claim the responsibility. I'm a reader, I'm a client. I read this database. That the database in there is a large number of the pages. What are the actions that we have? It's my responsibility to how to visualize the pages. I want to show that first happened A, then happened B, then happened C. This is my responsibility. It's not the database responsibility. This is a very interesting time. How to say this? The problem is that you have a good place and a bad place. The good point is This is not a source of evidence, this is not the same. You've been starting Let's talk about the good and good and good and good. I forgot about sourcing. What is the good and good? What is the good and good? You don't have data loss. You should write a transaction, it won't conflict. So you don't have to write in the primary data center, primary data center is 1, primary data center is 2, you don't have data loss. um, What is the case? The application developer's all of the application is very complicated. For example, there are application developers who want to visualize the tickets. You need to write a lot of logic, how to visualize it, how to solve it. For example, there are application developers who want to look at the tickets. For example, I want to see who saw the tickets. You want to write a lot of logic, who saw the tickets. Database is a little like a "fuck" feeling. Database infrastructure developer's job is very simple. Just write a hash map on order. But your application developer use it very complicated. You just need to put the hash map on order. And see how to pass the data. Lu Sun, you said event sourcing. You said event sourcing is what? Thank you. Okay. Bye. You follow me on the event trusting link. Thank you. All right. Thank you. Thank you. Hello, I'm going to say that. Event sourcing is the Bitterbit design principle. It is to put all transactions in blockchain. And if you need to balance the current balance he put all the money in the bag of all the transactions in the bag and reconcile to the current balance. Is this one? I don't remember that Sucing and Bitcoin is not related to the same concept. It's a unique concept. Okay. You can see the event solution it was 2005, and the Bitcoin was 2009. It was 2009. It's a different concept, but I forgot what I was going to do. Yes, it has a lot of different concepts. CRDT is a concept. And GitHub is a bit similar. GitHub is a snapshot and a new commit. It is a bit similar. You can have a snapshot and commit a lot, and smash it, and smash it, and then create a new snapshot. There are many places. Yes, but the idea of it is that it is not to have snapshot. It is not a snapshot. It is a full history. And if you need to have snapshot, it is from full history. Yes, it's like this. You're just going to use calculus matchup. This is the point of view. But when you have data to be big enough, Basically, in addition to the project, the project will be able to produce snapshots. Many times, you have to use data for a year, you can't be calculated once again. This is a very low effect. If you have data for a year, you can't be calculated once again. The result is a very low effect. So you can use snapshots. I'll just read this event sourcing. I think it's hard to read after this. That's the... in the chat. Yes, and when we say this config, we have a result of a non-resolve method. Resolve the function, one of the result is you write the result. If you have a conflict, you write the result.
[50:00] resolve conflict,就是你在写进去之前然后另一种Resolve的话就在锐的时候ResolveRed的时候 Resolve,比如说我刚才说这个就是写的Ordred HashMaps相当于是在Red的时候进行Resolve Conflict,然后Red的时候 Resolve的话很多时候就是比如说Relational Database,很多时候就是在Red的时候就必须得写一个具体的值了,Resolve。然后有一些自动的这个conflict result方式,比如说这个CRDT就是这个 Conflict-Free Replicated Data Types就是我们之前说的这个,有点像我们之前说的这个,就是这个,就是这个, directory 是吧,叫,on order list 或者 order list,它这块这个 CRDT 呢,它这个支持更多的这个 data type 是吧,比如说这个,这个 order list 啊,这种,啊,支持更多这种的额外的这个 data typeOK然后还有一些其他的automatic result的方式但是基本上所有的这些algorithm都非常年轻非常非常年轻很多时候都在学术阶段的我觉得现在最火的可能就是CRDT的吧这个CRDT在Reddit上用的比较多然后React上用的比较多在 Rack 用比较多有没有在Redis上用? 应该是没有在Redis上用,因为Redis是这个Single Thread的这个Serialization,所以应该是没有在Redis上用,所以在RAC用的比较多。我不记得这块有没有在这个Reddit上运用了然后其次的话像GitVersion的Control啊也是也是用一个相似的这个CVMerge function也是这个Automatic Resolve Conflict的一个方式嗯我们就是讲这个topology, multi-leader topology,这个multi-leader topology也有多种topology,就是什么circular,star topology,outward topology,这个也可以作为一个不同的理解,就是有一个观点,不同的topology也是其中一个比较复杂的一方面,像Uber的topology比较简单,因为Uber就两个data center,所以就是一条直杠线,是吧,就是就没有这个,像这个topology都比较简单,三到四个以上才有这种环形的还是这个start型的还是out to out的Uber的话你可以认为它是out to out的也可以认为是start的也可以circular是吧因为两个server的话这个topology就比较简单了但是有的这个topology会比较复杂的像这个Amazon的topology就相当复杂了这么多datacenter的话我记得Amazon可能有几十个datacenter啊在大陆就整个几个大陆都有是吧然后有几十个datacenter的话这个topology怎么样设计还是很复杂的一件事情嗯你除非做这个相关的一般来说是不会有这个问题的,但是这块可以看到一些这个topology,每个topology不同的地方嘛,比如说你要是这个circular topology的话,你这个data flow方向是一个方向找另一个方向的是吧,就是你这个data replicate的方向是一定是这个每个node的这个replicate的这个方向是,就是最后面的node这个data呢假设你写了data写到这个node的话这个node是最后被reapplicated的然后如果是start topology的话那你这个一般来说这个中心的这个server呢,它这个data是最更新的,或者最up to date,是吧,或close to update。如果是out to out topology的话,你的这个traffic会更heavy一点,是吧,你说的这个request,你要同时replicate,就是同时写到三次,你进out to going的这个traffic,outgoing traffic 会更 heavy 一点但是你这个 replicate 的时间会更快一点 是吧嗯对吧 这是各个的好处好谢谢大家然后计划有一个说是一个multi leader replicationRite to me a RAM at a strong order at the same replica.这块是给另一个例子是吧就是说当你写这个Multi Leader的时候你在这个叫你是multi leader的时候,你当有第三个leader的时候当你有mart leader 的时候 当你有第三个leader 的时候 你这个第三个leader 可能先收到这块的话,这Lead2可能先收到你的顺序是错的,就是和刚才那个casualty violation是类似的例子,跟casualty violation是类似的例子。这也是conflict的一种吧,就是和这个一种,然后他这块的话说这个resolve用version vector这个version vector也是非常复杂的,我觉得这个可能我可能今天还是会跳过,我觉得作为如果感兴趣的话,你可以仔细读下这个version vector,我觉得还是比较复杂的谢谢大家好,我们讲完MultiLeader了以后,讲这个Leaderless Replication我们之前讲的这个不管是single leader 和 multi leader 的 replication 他有个基本的 assumption 基本都是用SYCLE database我突然想要自己的
[55:00] Bis. Leaderless Replication, die ich oft als DynamoDB fühle mich an. Also, wir haben viele Sachen, vor allem, ich persönlich, ich persönlich, auch mit dem eigenen Preferen, ich persönlich habe, ich persönlich nur考虑 die Datenbasis. In-memory databases, Redis, Memcache, leaderless replication, Dynamo-like database, SQL-like database, sharded SQL, escherned SQL. Das ist die 4 verschiedene Database. Und dann, nachdem man die verschiedenen Analyse anwerteile. Wenn man die Analyse anwerteile, kann man sich auch eine Redshift oder Redshift, eine Column-Based Database anwerteile. Aber in den Grundsatz, wir müssen diese 4-5种 Database ausfragen. Es gibt viele verschiedene Database, die sich in den Zusammenarbeit mit einer Use Case zu erzeugen. Die Möglichkeit, die diese Systeme zu erzeugen, die sich in den Zusammenarbeit mit einer Umgebung zusammenfragen. Und die viele verschiedene Gebäude, die sich in den Zusammenarbeit mit einer Umgebung zu erzeugen. Kaffee und Flink, die auch in einem bestimmten Schleuchten zu nutzen. Das ist sehr gut. Kaffee und Flink. Wir sehen uns die Designs, die 5-6 Punkte zu lösen. 5-6个节目解决 Ich habe jetzt noch nicht gesehen, dass eine Design-Bestin-Bestin ist. Das ist nicht die 5-6-jährige Geist. Es ist nicht die optimal Lösung, das ist nicht die optimal Lösung. Das ist nicht die optimal Lösung. Aber in der System Designs, oder in der Arbeit oder in der Arbeit, kann man diese 5-5-5-Database plus die Tools, Kafka und Flink, das kann man sich zu lösen. Das ist alles möglich. Wir haben hier die Leiter-Leist-Database gesprochen. Das ist DynamoDB. Ich wünsche euch, wenn ihr es habt, den DynamoDB zu machen. Das ist ein sehr guter Wissen. und auch eine Leader-Less Replication-Klip. Das Buch ist sehr gut. Wenn die User ein, zwei, drei Mal in den drei Replicaten schreiben, dann ist das Leader-Less Replication nicht ein Leader. Ihr ist die Wahrheit von den Majority. Wenn man die Majority verhältst du das ist, dann sollte man das ist. Wenn man die User-Replica 1,2,3 schiebt, dann die 1 und 2 schiebt. Und zwar ist es Offline, sollte es auch zurückkehren. Das ist schon geschrieben. Wenn es aus dem Linken aus 2345 aus dem Linken zu den Daten. Wenn man diese Daten aus dem Video dann kann, dass man diese Daten aus dem Video dann kann, dass man diese Daten aus dem Video dann kann. Das ist eine Determine Factor. Das ist eine Determine Factor. Das ist eine Version. Das ist eine Last Ride Timestamp. Das kann man sich mit dem Timestamp anwenden. Wenn man die Timestamp anwenden kann, dann kann man die Timestamp anwenden. Das ist eine Clock Drift. So, wenn wir den Leaderless Replication sehen, ist es ein Vorteil. Vorteil ist, dass es Du bist ein Leader. Wenn man einen Server auf der Anwendung hat, kann man auch die Reader und Write Request zu erweitern. Wenn wir eine Replication haben, wenn wir eine Replication haben, dass Replication 3 ist, dass Reader ist, dann wird es nicht mehr Reader. Wir müssen die Replication 1 und die Replication 2 sein. und durch den Consensus Aquarium herausfinden, eine neue Leader zu finden. Wenn man die Replica 3 ist der Leader, dann ist die Service unavailable. Aber mit Leaderless Replication kann man einen bestimmten Replica unavailable. Es gibt keine Single Point Feature, keine Single Point Determiner. Wenn man eine Single Server unavailable hat, dann ist es nicht der Service. Also, das ist das. Leaderless Replication ist eine sehr wichtige Meinung, dass wir diese Daten in der Zeit, in der Zeit, in der Zeit, in der Zeit, in der Zeit, in der Zeit, in der Zeit, in der Zeit, die Daten sind nicht gleich. Es gibt einen Moment, die Daten sind noch mehr als die Daten. Das ist nicht so ein bisschen. Nama. Wir wollen wie die Daten eventuell verifizieren? Das ist eine eventuell consistent. Das ist eine eventuell consistent. Wie soll man eventuell verifizieren? Wie kann man eventuell verifizieren? Wir können eine eventuell verifizieren. Beispielsweise in der Übersetzung, User 2345 Client,
[60:00] 两个七的version,一个六的version那他就知道这个6的version是autodate的那他就可以说让6的这个version更新成7的version就这个Client告诉这个Server说你应该更新成最新的version了然后这个就叫Read-Repair嗯然后它不仅可以做ReadyPart,它还可以做什么呢?它可以做一个叫Antitrophy Process.Antitrophy Process 什么呢?就是说它不停地 compare 这个Database 不同的几个 replica 之间的值。它如果发现几个 replica 之间有一个值,不一致的话,它就找见那个不一样的值,然后把它crack掉。这块有个小的trick叫mercure trick叫merc tree,这个merc tree是一个非常高效的能compare出两个replicate哪一块值不一样的一个algorithm, data structure,这个data structure,叫merc tree,然后可以非常高效的compare出,比如说给任何两个replicate,它具体哪一个data不一样,可以通过这个来compare出,非常高效的就compare出了应该是log n就compare出这哪个data不一样然后再根据这两个data不一样的对比一下哪个version更前面那就可以repart这个data了不是所有的data center这两个都有的,不是所有的这个,不是所有的database这两个都实践的。你比如说这个Voltemont的话是不做这个anti-trophied process的,它是没有这个background process的。那因为它没有这个 background process 所以它影响了它的 durability 并且你读到 data 非常有可能是 still 的 data 是吧你就是steal的可能性会增加但是Denimal 是一般这两个周时间就是你rider repair 和这个antitrophic processor 都有的这两个各有各的好处吧这两个结合起来才能guaranteeeventually consistent像Voldemore的话,其实我觉得很难定义成 eventual consistent 的,因为它没有这个 anti-trophied process。但是另一方面来讲,有 anti-trophied process 的话,你实际上这个 anti-trophied process 是个 background process当你这个Background Process 进行 Run 的时候,你多半是要和你这个 ongoing 的 transactions 进行 resource 的 complete 的了。你可能会影响一些 ongoing 的这个 transaction 的 performance 是吧。所以这个到时候 optimize 的时候也会比较复杂。然后这块有个问题啊说如果有一些write field 了五个node只写到了一个那read repair 会不会make mistake 啊这块的话这个就是没有就是这个没有达到 quorum我们说这块这个所有的这个Leaderless Replication是要讲究一个chorum的概念,什么意思呢?这个chorum一般是用户define的,像这个DenimalDB这个设计的时候非常有先见但我毕竟设计设计的时候很多想法是很很有先见的也就是说大部分情况下我们在讨论的例子都是说你要达到这个你Red和Red要达到绝大多数,什么意思呢?就是你要大于N,比如说你RAID和RAID的数量是大于N的像你提的这种例子就是五个node只有一个写成功的话,那么你这个其实除非你这个read呢,除非你这个设计是write=1就可以,read=n。就假设五个node的,你read只要写到其中一个就可以,但是你read要五个都读。嗯你知道吧,就是我们可以假想一下有5个node,下面这个例子有5个node你怎么样能guarantee这个eventual consistent呢?eventual consistent就是怎么样能guarantee quorum呢?就是这个投票的大多数呢你一定要是Red和Red加起来是要大于5当你Raid和Raid加起来大于我的时候你就一定最新的data一定会被读到就是你写进去以后当你读的时候一定会被读到是这样子的,我知道是需要read,read需要corum,但我这里的意思是,就是你第一次read,它有五个notes,然后你只写到了一个,这个read fail了,好像就只写到replica1,那你接下来有另外一个read,然后你read的时候呢,读replica1是读到一个最新,但是并没有write,最新,但是不算是成功write到的一个数据。那这个时候,它会read repair吗?好问题,这个其实是一个很trick的问题,这个其实也是Denemo里面没有回答的一个问题。这个的话这个的话这个问题呢是是这是存在问题有可能是有可能不是因为Denible那篇配合里面写的时候是他是没有就是没有解决这个问题他只是说当你data不一致的时候你应该有个mechanism去解决这个inconsistent data但这个mechanism是只要你有一个人是最新data就应该是把剩下的都否决了还是你应该按majority来吧
[65:00] Hold. He actually didn't talk about this problem. If you can just use that paper to understand 你这个呢是这个data呢 you do a red repairer, it will make mistakes But from the paper that I wrote about the whole thing, you can make mistakes. Let's give a example. You have five nodes, and the four fields are filled. And you this red actually think be about it right but you have a note written in the other words in the animal when you have a note written in the other words you will not be revoked You write it out after you read it, you write it. Actually, transaction from DynamoDB's perspective, it's not a problem. It's an uncommitted transaction. But you read it. If you read it, you read it. If you read the three and read the four and read the five, it would be better to divide. Because if you read the four, you will find the majority is not the version. You can also repair it. 但是最worst case 是读了三 就是你的read和read 都写的是三 结果你读了三 读了三的话 你有一个新的version 两个旧的version 你这种情况下 是区分不出来 这个新的version 是不是真的新的version 它有可能是 about it, commission, but there's a lot of other three nodes that are written in the version. But the two nodes are filled. I just read the version from this node. I read the version from the two nodes. I read the version from the two nodes. In this case, you can do read and repair and then cover it into the version. - Actually, I saw the Nino-Risability that was mentioned in the beginning. It was actually related to the meaning of this. But I probably didn't express it. - Yes, this is a very valid question. This is a very countered case. You actually from Dynamo, when you write it, you have no reach out. It's just five nodes. We'll talk about this one. If we have 5 nodes, 5 replicas You write to 3 to successfully write You write to 3 points to success for the rate. When you write to write, you write to the replica 3 points. The other write to fill all the points. From the right perspective, it actually is filled out of From right perspective, it's fill-in. If you write version 7, and you write version 6, you think 7 is fill-in. You can read the database, it is 6 or 7. In DynamoDB, the leaderless replication is not reversed. So you read the reader, you read the 3, 4, 5, right? So you read the 3, 4, 5, right? So you read the 3, 7, and the 4, 5, 6. In this situation, the reader is not sure 1 and 2 are 7 or 6. If it is 1 and 2 are 6, it would be better because majority will decide it is 6. But he doesn't know that 1 and 2 is 7 and 6, he can only imagine that 1 and 2 is If you have 7, you can probably put 7 in the middle. It's a 6.0.0. The about it write, you return to the user, I said I wrote about it. But the fact that the write is successful. It's successful in this particular situation. So this is a very counter case, but you can see Denimal DB or Leaderless DB, we can't guarantee any transaction. We just want to talk about transaction guarantee. It's actually very difficult to guarantee any transaction. I hope that this time we can understand the question and the more complex. Thank you. Let's look at DenimalDB. The red and red corner is very interesting. If the red is in the underlying state, it will be in the underlying state. You can tolerate available nodes and ensure that you can read the data. You can read the data from the last committed data. There are some more interesting things, right? For example, if you have three nodes, you can guarantee one node unavailable when you can do this transaction. If you have five nodes, you can guarantee that you can rate and write in two nodes unavailable when you can do this transaction. We can read and write. So this one gave a very good example. This is a simple example. You write to Replica 1, 2, 3, and you read to Replica 3, 4, 5. But because this one This is the same as the "Successful" version. So, at least there is a replica that you can see the latest "Successful" version. So this is what it is written in DynamoDB. And there is also a very interesting example.
[70:00] 在这看这一块,你其实这个W和这个就是Write和Rate是没必要一定大于N的如果你就是说我就破罐子破摔了是吧就是说,我不要求任何guarantee我不要求任何,有些时候是有可能有这种use case我不要求任何guarantee是吧那我W和R是可以小于N的其次的话,W和R有一种特殊的case比较有特殊的case,就是比如说你Write写的任何一个node就可以了但是你Rate要把所有的node全部读一遍然后找出最新的写的也就是说你比如说五个node你write是写到其中任何一个node就可以了那你这种就是当你write heavy的时候write非常heavywrite非常infrequent的时候你write任何写了一个node都可以但你write的时候你就把所有的node涂出来然后找出这个值到底应该是什么这个也是能guarantee这个corum的然后另一种情况下是反过来就是你write是要写到所有的里面就是你所有的write要写到五个里面必须有五个全部写到但你RAID是可以从任何里面读这个就比较适合RAIDHeavy的UseCase你RAID是可以从任何里面读的但是这两个Case我觉得只Case呢它其实只是一种我觉得只是一种这个这个这个Corum的这种这种这种就是玩数字这种游戏因为这个这个整个这个Leaderless这个Replication设计的最终最初目的是TolerantTolerate这个Unavailable node同时让整个ServiceStill Available如果你是单纯的说这个SkillsSkills和Skills那你其实有不同的方式来解决比这个Leaderless Replication更好解决所以它这个更多是感觉是一种玩数字的游戏就是把这个WR随便设置想一下极端Case但是真的是Read Heavy 和Read Heavy的话你可以有不同的方式来解决没必要用这个Leaderless Replication它更多时候是tolerate这个unavailable node的 performance更好一点好这个Leaderless Replication有很多问题比如说你这个sloppy column read的时候你可能会有问题什么叫sloppy column呢就是我们来再讨论一下再来看这个例子就是很多时候在想很多时候有人问这个Leaderless replication它scalability是多少其实它scalability应该是Infinite scale这个Leaderless replication应该是Infinite Skill为什么呢你这个机器呢你可以思考一下每个Data每个Data它到底是划分到哪个哪五个Replica上其实是可以由系统决定的你比如说你任何一个Data任何一个Rate和Read我可以给你生存一个YoyoID给你生存一个ID然后我根据你的ID来决定你到底是哪五个Replica来Serve你这个可以 further skill 是吧你没必要说你不需要说整个DynamoDB就五个replicaDynamoDB可以有infinite replica你可以有上万个replica实际上DynamoDB确实有上万个replica你可以有上十万的replica上百万的replica都有可能但你具体的哪一个data你来了一个data那我这个data面对的具体是哪个machine的话我可以有一个hash 是吧我可以根据一个hash来决定这个data是我hash了一下这个data然后根据它ID前几位我决定它具体是拿几个Machine来Serve它是吧然后可以通过这个来决定那么我们会意识到这个replica在整个DynamoDB里面的replica数量是完全自由的所以它的数量应该是远远大于你这个n的数量的就是对于particular data对于具体的一个data你的这个replica具体值的replica数量就是远远大于这个的那么当你就是当你比如说假设这个是n等于5的话假设你正好这三个replica全部down掉了就是345全部down掉了那Denimal呢它设计的最重要的原因就是guarantee availability所以它就采取了一个折衷采取了一个什么折衷呢就是说假设我现在数量是不到这个corum不到这个corum数量我可以借用其他的replica就像说我现在想回家但我家那个钥匙丢了我家钥匙丢了我先去我邻居家沙发上税然后等我家钥匙早见的时候再回自己家税这种感觉一样所以这种情况下假设这个replica345全部down掉的话DenomDB的client可能会借用replica6去replica6来写这个data这叫sloppycorum就是sloppy,就是没必要严格执行这个corum去其他家的沙发上借数一晚上的时候当你这个replica3又backup回来的时候当你replica3又恢复的时候再把这个replica6的data再copy给replica3所以这个叫sloppycorum所以这个sloppycorum当你有sloppycorum的时候你可能会发生一种
[75:00] 很奇怪的情况是吧你这块写的时候你写的data是写到1和2和6上的你注意到 写的电台写的1和2和6上的但你读data的时候读的是三四五的data所以你这个写是完全没有被涂到的因为你有 Slopey Corum,所以你从这个Ride的角度来看,Data是写到1,2,6上的你写的时候写到126,但是你读的时候从345上读的,这个chorum是没有达到的这个其实很常见你想一下你如果有个network partition把1 2和3 4 5分开了这个情况就发生了是吧,你有个Network Partition,把1,2和3,4,5分开了,那你写的时候只能,1,2不够了只能进入一个6,但你读的时候从3,4,5读,那这个Data就不一致了,所以这个Network Partition很容易使这个sloppy column发生嗯好,然后其次的话,这个DenableDB还有什么可能的情况呢?就是这个Data Loss,发生Data Loss,就是当你有同时的很多 concurrency right的时候,你实际上根本区分不出哪个right发生最先发生的。那你可能每个replica的话,每个replica它可能有clock school,然后就导致这个last right win就可能会loss。就是你如果你这个conflict resolution是last right thing的话你有可能loss我再强调一下,Tenemodb它设计中它这个Conflict Resolution是由用户自定义的,您可以是比如说Version是可以的,你可以LastThreadWin,甚至您可以写个Conflict Resolution的Logic你可以写的,在那个Cassandra中好像Default是LastThreadBin,在Cassandra的Default是LastThreadBin,所以这两个是不一样的好然后我们再读一下其他的几个Case,我看有什么其他有趣的Case,你没必要理解所有的有趣的Case,但是有些常见的Case,你可以理解这个,我们把DenemoDB或Leaderless Replication叫做Best Effort,就是你不能guarantee你读到最好的最新的。好所以像第三个例子就是刚才静怡说的例子就是当你写的时候你只写了其中一个但是当你读的时候呢,你实际上读的时候,你在测证情况下,你可能有Dirted Read的,甚至这次ReadedPier的话,就相当于是把一个Uncommitted的Change然后 committed 掉 这个是非常connor 的 case然后DinomDB即使任何事情都是 working correctly 的话还是有age cases,然后可能timing不好,然后就导致你这个data是crafted data,所以任何用Denimal DB或者是Cassandra这种leaderless database做这个transaction都是勇士啊,我们之前已经有Cadence这种各种头头的countercase作为先例了是吧,作为Cadence,我知道下图有些组这个engineers在这个Cadence组做工作已经是特别痛苦是吧,所以说这个任何敢用这个Leaderless Replication做Transaction, Business Transaction都是勇士啊。大家知道它是一个Best Effort的这个Database就可以了我看看这块 Sloppy Corum 和 Hinted Hand-off 我也讲过了就是当你不组 Corum 的时候 你要借用一个 Corum然后谢谢大家这个的话就是DenimalDB另一个例子了,就是当你写的时候,因为它是leaderless transaction,leaderless replication当你同时写的时候,比如说这个情况下,node1写了A,node2写了B,然后在Node1写了A,然后Node3写了B,在Node2上就发生冲突了那这种情况下的话,你其实是区分不出A和B,谁是应该是最后的这个的话是完全没有办法区分A和B谁是最后的你如果是按大多数的话可能是A,但是如果按timestamp的话有可能是B是吧嗯真的是看这个config resolution是怎么定义的所以这个DenimalDB为了甩锅呢就是叫你client自己来写config resolution所以它也是为了甩锅吧,这个database的话很多时候是不想承担这种特别大的风险的他当时举了好多例子呢,就是这个Shopping Card Checkout 的例子,就是在PayPal里面举了很多例子,Shopping Card Checkout 例子,就是比如说,你这个A的这个Transaction,A的这个Transaction可能是加一个Node,是吧?B的这个Transaction可能是从这个Shopping Card里面,就是 remove 一个 item当你进行conflict reserve的时候,你remove的item,如果发生conflict的话,是一定不被remove的。就是说,它是跟它business use case相关,就是说,如果我再加一个item同时,
[80:00] 就是捡了一个item,然后我系统没法判断出谁先谁后的话我就假设这个家的itom在最后了就是说白来是为了增加更多的消费嘛也跟business use case 相关所以这个所以这个Database设计,Config Resolution这款也是和你的Use Case相关的。好,这个就是对刚才的例子的更多的解释最后这个非常复杂的version vector这个是一个 single node version vector我今天不打算讲进来,因为我觉得讲这个的话,首先要把我自己绕进去,然后其次的话大家可能会被绕进去这个还是很复杂的。大家可以有空自己看一下吧,你可以想像说这是一个Single node Casualty Dependency 的这个Version Vector如果你把它copy到N个Node的话,就是这个Version Vector了,这个复杂度是非常非常高的。嗯我可以做的事吗?好我想说这个version vector和lan pod的timestamp是不是同一个东西啊,lan pod的timestamp是是另一个东西那个比较简单,这个的话,Virtual Vector的话,是Concurrent Red,就是这个Resolution的,这个是比较复杂的一个东西,如果感兴趣的话可以读一下,我觉得读一下也挺好的,可能帮你思考一下这个Multi Leader的这种各种conflict会出现各种什么样的奇葩的情况我可以再用一次的这也是最后一个slide了,然后大家有什么问题的话,我们讨论一下,没有的话,今天就到这为止好了。我这边的话还是跳了很多slides了,我觉得多种原因吧,我这块就是列出来的话还是给大家一个有机会的话可以读一下,特别你要是没有这个书的话或者是你感兴趣的话可以读一下,但是因为它复杂度太高,我觉得我自己读一遍有时候容易把自己也绕进去的时候可能就不讨论了,其次的话我觉得这块的话很多时候是对于这个high level的这个知识点讨论和这个普及,很多时候讲的是这种方向是吧,如果我走太多细节的话,太过于细节的话,很多时候就之前,如果你是没有学过这个概念的话,大的方向可能都会迷失掉。所以我们再到今天的这个agenda里面回顾一下好在最后的时候再回顾一下所以这个replication是有多种replication的,一个是最常见的sql是有single leader replication那就是有一个leader然后他的data是replica有几个followers上然后你可以 asynchronous replicate,也可以 synchronize replicate然后这时候有不同的这个fileure handle方式是吧并且你replicate的话不管是用statement log 做replicate还是用这个write hand log 做replicate都不太好所以他们因此发现了发明了一个就是发明了一个新的就是设计了一个新的replicate log就是专门是做replication log然后当你做replication的时候你就多copy of data所以你可能会有不同的consistency level是吧然后这块的话就简单介绍两个consistency level一个是radial rate还有一个monotonic rate然后Single Leader Replication,大部分小公司已经足够用了,就是你做个startup几千人,几百人就足够用了,但是对于这种特别大的公司,比如说Facebook和Uber的话,你这个Single Leader Replication也是不够用的,因为你的availability会很糟糕,当你这个Single Leaderfuel掉,single-party failure fuel掉的时候,你虽然能再选一个leader出来,但是你这个中间会有几百毫秒,甚至几秒的availability,所以你这个performance是很多时候不可以接受的。那这种情况下就需要Metiliter ReplicationMetiliter Replication呢基本上也是 SQL 它只不过是多了一层就是 cross data center 这个 replica 然后你会有 conflict 所以呢Multi-Leader Replication大部分时候都讲怎么样解决这个conflict的最好是没有就是最好最好的情况就是当你做transaction最好的是没有conflict就所有的写是固定的road到一个leader上的但是如果你能允许适当情况下的conflict error,是吧?就比如说不是这种payment transaction,是吧?你可以做成这种CRDT这种,或者我们之前讲的blitz这种,就是un ordered hash set你所有的写全部recorded 但你读的时候进行这个resolving, resolve conflict然后最后的话讲了这个Leaderless Replication 主要是Denimal,我是强烈建立大家去读下Denimal这个Paper,读前会很累,可能会如果之前没有读过Paper,像我第一次读,我读了大概十几个小时读了十几个小时放的感觉,但是读了以后会看到很多,很多,很多这个就是能学到很多东西啊,
[85:00] 设计理念,它整个设计就是围绕在怎么样提高这个database availability 上设计的所以它不管是choram,sloppychoram,还有包括这个read repair,antitrophia,设计非常轻盈的设计然后但是我们说这个leaderless replication database它是一个best effort database它和之前两种database是不一致的就是single leader 你可以认为是基本上可以guarantee任何 transaction就是你需要根据不同的这个Durability要求你可以需要Trick一下但是你可以Garantee任何Transaction但是任何讲把那个Business transaction特别关于Money相关的Transaction要做成用Leaderless Replication的Database来实践都是勇士啊基本上都死得很惨然后最后的话就是它这个Leaderless Replication有个Concept叫Eventually Consistent它通过Read-Repair或者Enteritrophied的Process然后导致这个SteelData被Repair掉然后它这个Leaderless Replication不管是TenableDB还有Consentral都有个Steel那种Monitoring它也可以看它这个data到底有多少的still,然后来决定是否是增加就是增加它这个conver的速度啊什么的,可以有一些fantune,就是可以更tune的更细一点是吧,可以tune的更细一点,使这个database的performance来说更好一点,特别是这个data的consistency更好一点。这个replication就讲完了,我还是建议大家再反复多读几遍,就是high level的话基本上cover了所有的replication但是可以做足几遍我觉得我今天要有个读的就是想读一下event-sourcing我忘了这个具体怎么回事了嗨,Scott,我这里有个问题你问好了是这样子的就不是那个replicationreplication那一张的问题是我看到后面consistency and consensus 那一张他让你有介绍distributed transactions and consensus他先是介绍tofaces commits然后是for tolerance consensus algorithm那我这里是想搞清楚一个概念是tofaces commits是可以保证在这些replicated system或者database里面它是一个能够保证一个比较strong的consistency而是它在没有2PC的情况下面用fault tolerance consensus algorithm来推而求其次2-face commit 是能保证 cross-shard就是cross nodes 的transaction它是一定能保证的但它经常不available然后它效率非常慢但是它能保证这个就是cross node的transaction那是不是在没有这个的情况下面才会有下面的consensus algorithm呢2-phase commit和consensus好像不是同一个概念consensus更多的是找一个total order它和linearity更相关还是这个概念还是有点有些相关但又有些 orthogonal就是那 consensus 在什么时候应用呢?consensus 更多时候就是比如说你有一大堆 replication你现在有一大堆 replication log就是比如说 single leader replication你有一大堆 replication log那怎么样决定这个 replication log谁在谁的顺序是怎么样的?就是 csensus这个是consensus或者是说你现在有一大比如说你single leader 的一个 database就是然后这个 leader 挂掉了你这么多 follower决定谁是新的 leader这也是 consensus对但是他们两个是不相关这个我很难用语言来形容出,就是说两个是有相关性的,不是Orthogonal的问题但是Linearability不guaranteeTransaction,Transaction不guaranteeLinearability我给你举个例子,Linearability和Transaction是不guarantee的,就是两个是不完全相互guarantee的有没有又Guarantee Linearability又Guarantee Transaction的呢那可能只有Two-Phase Commit了就是Guarantee这两个Two-Phase Commit可能是Linearability和Transaction都Guarantee的但是这个Performance是最糟糕的我给你举个例子就是Guarantee Linearability但不Guarantee这个Transaction比如说你当你有MarketNode的时候当你有多个Node的时候就是多个DataRecordUpdate的时候
[90:00] 那你很多时候你这个Linearability是可以guarantee的但是你这个Transaction可能没有guarantee 比如说嗯对这个可能是没有garantee然后在很多时候是transaction能garantee但linearity不能garantee比如说当你做这个snapshot isolationSerialized snapshot isolation database 时候是吧,你的Linear Abinitation 没法 加 产 提的对吧对的,谢谢好这个问题比较复杂,它这个细节也比较多哇并且加上terminology比较复杂的话,这个问题确实比较复杂但是我觉得好处是没有人会问你这么细的,我记得,其实我研究是比较细的,我当时做写一个前两个月写的一个这个Design,我这个Design写的特别写的,我大概写了50多页的一个Design,因为比较大的一个系统,然后我去那个就是我们这个Level 2的这个Community去,去这个review 这个 design 了,然后他们这块 Level 2 Committee 但不是都是 staff engineer 吧,都是二三十年工作经验的,这个非常 experience engineer然后我就说这个last right win这个algorithm是不能guarantee不能guarantee data cost,就是没有data loss的,我就解释,大家很感兴趣然后基本上所有的stuff都很感兴趣,然后就花点时间解释好就是为什么这个last right win 是不能guarantee这个没有data loss 是吧?就是解释了很多,然后其实看到这个做工程做多了以后这种非常细的东西理解是好的,但是它肯定大部分人是不理解的,大部分人是不理解的,你不理解也没事儿,但是你理解了肯定是对你有好处的,就是你至少不会给队友埋坑是吧,不会埋一个很大的坑在那里谢谢大家好 有没有什么其他问题好谢谢大家 谢谢大家好,那今天就到这里吧,谢谢大家,非常感谢。