## Detailed walkthrough
### [00:00](https://www.youtube.com/watch?v=SrnRA3JLjIA&t=0s) OpenAI API 与代码生成工具的初体验
在正式进入分布式系统的正题之前,讲师先向大家分享了一个最近正在探索的有趣工具——刚开放不久的 OpenAI API(当时处于早期测试阶段,仅向大约四五百名 Beta 用户开放)。讲师现场演示了它的能力,说明它本质上是一个基于深度学习的模式识别(Pattern Recognition)和“文本进、文本出”(text-in, text-out)系统。在补全测试中,输入 "I think",模型便顺理成章地补全出名言 "therefore I am";在输入 "iceberg" 后,模型也能返回类似 "what we know is a typical iceberg" 的连贯文本。用户还可以通过调节参数来控制输出结果,例如调整 Response Length,或是通过 Temperature 来控制输出的随机性(Randomness)。
除了简单的词句补全,讲师还演示了模型的文本分类(Classification)能力:输入 Facebook,它能打上 Media 和 Technology 的标签;输入 FedEx,它准确归类为 Logistic Transportation;讲师还随手测试了一家游戏公司 EA(Electronic Arts),模型也精准识别出这是一家 Video Game Company。此外,该 API 在文本摘要、命令行生成、问答系统(Q&A)以及聊天机器人(Chatbot)上的表现都相当惊艳。讲师提到社区里有人用它生成音乐、生成创意,甚至利用 React Component Generator 直接生成前端代码。针对弹幕中“程序员是不是快失业了”的调侃,讲师笑着安抚大家:“不会的,它只是 generate 已有的 code。”比如生成简单的 HTML 骨架和基础引用,但编程中最复杂的核心在于业务逻辑(Logic),这是目前模型无法轻易取代的。讲师表示如果听众有好的 idea 想做实验,他很乐意在群里分享自己的 API Token 供大家体验。随后,讲师对近期的课程进度作了简要同步:本期聚焦分布式系统中的 Replication(第 1 部分),而下周针对应届生 Leo 的模拟面试(Mock Interview)则可能会考察 TinyURL 或 Craigslist 这种相对基础的高频系统设计题。
为了强调分布式系统的严谨性,讲师引用了道格拉斯·亚当斯的名言:“事物可能会出错与绝对不可能出错之间的主要区别在于:当一个绝对不可能出错的事物出错时,它通常会变成彻底无法挽回的灾难。”在分布式系统中,必须清醒区分什么是“可能出错”,什么是“在物理法则下绝不可能出错”。著名的墨菲定律在分布式领域体现得淋漓尽致——"What could go wrong, eventually will go wrong"(只要存在出错的概率,给它足够长的时间,它就必然会发生)。因此,在设计保证数据绝对安全(Data Safeness)和绝对正确的系统时,任何边缘容错场景都必须预先考虑周全。回归本质,Replication 就是通过网络将同一份数据冗余存放到多台物理机器上,其核心驱动力之一就是缩短用户物理距离(Geographical Proximity)以降低网络延迟。以 AWS 为例,全球分布着几十个可用区(Availability Zones);反观早期 Uber 只有 Phoenix 和 DCA 两个主力数据中心,如果一名俄罗斯用户发起打车请求,网络数据包跨越太平洋传输,仅端到端网络延迟(P99)就会增加 100 毫秒以上。将数据通过副本部署在离用户更近的数据中心,可以直接削减数十至上百毫秒的物理延迟。
在分布式系统中,如果需要为一个现有的数据库集群配置一个新的从节点(Follower),最朴素的想法或许是直接把数据文件从一台机器拷贝到另一台机器。然而这种做法在实际运行中是行不通的。因为在数据持续写入的场景下,文件在拷贝过程中随时都在发生变动,直接拷贝会导致数据文件处于损坏或不一致的状态。在传统的企业 IT 运维中,常见的做法是申请一个停机维护窗口,比如业务停机维护六个小时,把数据库完全锁住或直接下线,再做全量数据备份(Dump)与拷贝。但对于现代互联网公司而言,这种需要长时间停机的维护方式是完全无法接受的。
```mermaid
flowchart TD
accTitle: Split-Brain Scenario in Distributed Systems
accDescr: Diagram illustrating how a network partition creates a split-brain condition with two conflicting leaders.
subgraph NormalCluster["正常集群状态"]
L1["旧主节点 (Leader 1)"]
F1["从节点 (Follower)"]
F2["从节点 (Follower)"]
L1 -->|"同步写操作"| F1
L1 -->|"同步写操作"| F2
end
subgraph PartitionEvent["发生网络分区 / 心跳超时"]
direction TB
L1_Isolated["旧主节点 (假死/网络隔离)<br/>仍自认为主节点"]
F1_Promoted["被选举出的新主节点 (Leader 2)"]
F2_Active["跟随新主的从节点"]
F1_Promoted -->|"同步新写入"| F2_Active
end
例如在银行转账场景中,用户从 A 账户向 B 账户转入 100 元,主节点写入成功后立即向用户返回“OK”。然而日志还没来得及同步给从节点,主节点便瞬间暴毙。这个主节点可谓带着秘密“含恨而终”。当从节点被提升为新主后,根本不知道这笔转账的存在。当用户再次查询余额时,发现钱凭空消失了,这便造成了严重的数据不一致事故。
更具破坏性的是异步复制丢失数据与主键自增(Auto-increment ID)结合引发的安全穿透,GitHub 历史上就曾发生过一次著名的真实重大安全事故。在 GitHub 的架构设计中,MySQL 数据库使用自增主键来标识 Pull Request(PR)等元数据,而代码库的具体内容和元数据映射则缓存在第三方的 Redis 存储中。当时旧主库在写入一条 Uber 的私有 PR 记录时,分配的自增 ID 为 1,但该记录还没同步到从库,旧主库就发生了宕机。从库被提升为新主库后,并不知道 ID 1 已经被使用过。随后,Lyft 的开发团队恰好提交了一个新的 PR,新主库再次分配了自增主键 ID 1。然而,底层 Redis 缓存中 ID 1 所指向的代码引用仍然是之前 Uber 的私有代码仓库!这直接导致 Lyft 的人员在打开自己的 PR 时,竟然可以读取到 Uber 的内部私有源码。这类事故一旦发生,除了系统崩溃,更会带来极其严重的跨企业机密泄露与法律诉讼风险。如果当时系统采用全局唯一标识符(UUID)而非递增自增 ID,即便发生数据不同步,最多也就是访问报错,而绝不会错位映射到其他公司的私有资产上。
```mermaid
flowchart LR
accTitle: GitHub Auto-Increment and Async Replication Bug Flow
accDescr: Shows how asynchronous replication and auto-increment ID reuse caused Lyft to access Uber's private code.
subgraph OldMaster["旧主库 (宕机前)"]
PR_Uber["写入 Uber PR<br/>自增 ID = 1"]
end
subgraph RedisStorage["外部缓存/引用存储 (Redis)"]
CacheRow["Key: ID 1<br/>映射目标: Uber 私有代码仓库"]
end
subgraph NewMaster["新主库 (故障转移后)"]
PR_Lyft["写入 Lyft PR<br/>复用 ID = 1 (无前序记录)"]
end
基于语句的复制(Statement-Based Replication)在面对复杂数据库特性时会迅速崩溃。除了常见的非确定性函数,数据库中的触发器(Triggers)和存储过程(Stored Procedures)也是重灾区。例如触发器逻辑为“当 Column A 发生更改时,自动将 Column B 的计数器加 1”;而存储过程则是一大段打包在一起执行的语句块,旨在减少客户端与数据库之间的网络交互。讲师指出,存储过程在早期的传统 IT 企业中非常流行,但现代互联网公司基本不再使用,因为它的副作用(side effects)实在太多,代码极其脆弱(fragile),极易产生难以排查的 Bug。此外,关系型数据库还支持用户自定义函数(UDF),开发者甚至能在 UDF 中发起外部 API 请求;一旦复制包含这类逻辑的语句,从节点执行时产生的副作用将完全不可控,导致主从节点数据严重分歧。虽然这些边缘情况(edge cases)理论上能打补丁解决,但维护成本过高,因此业内如今基本淘汰了语句复制。
为了彻底摆脱物理层束缚,业界演进出了专门为复制而设计的**逻辑日志复制(Logical Log / Row-Based Replication)**。逻辑日志与底层的具体存储引擎完全解耦,它采用一套与存储无关的描述语言来记录行级别的数据变更:
1. **插入(Insert)**:记录该行所有列的新值(new value of all columns)。
2. **删除(Delete)**:记录足以唯一标识该行的主键;若无主键,则记录所有列的旧值。
3. **更新(Update)**:记录主键信息以及发生变更后的列新值。
逻辑日志按事务提交的先后顺序记录严格的全局序列(Sequence),从库只要按序应用便能确保数据不会损坏。更关键的是,逻辑日志只关注数据逻辑本身,主节点使用 B-Tree 而从节点使用 LSM-Tree(Log-Structured Merge-Tree)完全可行,甚至允许主从节点运行不同的数据库版本,从而天然支持零停机滚动升级。此外,逻辑日志格式透明,易于被外部应用程序解析,催生了变更数据捕获(Change Data Capture, CDC)架构,使得像 Cassandra 或 MySQL 等数据库的行变更能以事件流形式输出,对接下游实时流计算。另一种演化方案是基于触发器的复制(Trigger-Based Replication,例如 Oracle GoldenGate),在行更新时触发应用层钩子逻辑来实现跨库同步,但由于在数据库层执行额外代码,其系统开销(overhead)明显高于其他机制。
针对课堂上关于“日志复制与事务强隔离级别关系”的提问,讲师特别强调:**复制(Replication)与隔离级别(Isolation)是完全正交的两个概念(orthogonal problems)**。隔离级别与并发控制属于事务范畴,通常在主节点(Master)处理,用于裁定多并发请求中“谁胜谁负”(who is winner, who is loser);而复制解决的是主节点确定好结果后,如何将数据可靠同步到从节点(Master to Slave)。这两者不应混为一谈。
当场景拓展至多端接入与跨地域部署时,写后读一致性会变得更加错综复杂。首先是**跨设备写后读一致性(Cross-Device Read-After-Write Consistency)**:用户在 PC 桌面端更新了个人资料或发布了内容,拿起手机端查看时,两台设备发起的网络连接可能由于会话或网络拓扑差异,被网关路由到了完全不同的节点甚至是不同的数据中心。如果用户在桌面端刚写完,手机端连上未同步的从库,依然会遭遇一致性破裂。
在现代高可用架构中,数据库通常要求跨多个数据中心(Cross-Datacenter)部署副本。假设系统在两个数据中心各自维护副本,以防止单机房故障(Complete Outage)。此时客户端路由面临两难抉择(Trade-off):
- **强制固定机房路由**:要求特定用户的所有请求必须钉选路由到指定数据中心(如旧金山 Data Center A)。这虽然容易保障写后读一致性,但性能隐患极大。一旦该机房出现网络抖动或性能劣化,用户体验将随之雪崩;而且一旦用户出差旅行(如从旧金山飞到北京),原本就近访问亚洲机房的请求依然被迫跨洋跨网绕路回旧金山,带来不可接受的网络高延迟(High Latency)。多用户共享账号(跨地域同时在线)更是会让固定机房策略彻底失效。
- **就近访问优先**:根据客户端地理位置路由到最近的数据中心,能获得极佳的响应延迟,但只要主从复制存在跨洋延迟,便几乎注定在某一时间窗口内牺牲写后读一致性。这完全取决于业务形态是优先追求一致性还是更看重低延迟性能。
关于“副本复制(Replication)是否必须基于事务(Transaction)完成”这一问题,主讲人指出,从理论概念上讲,事务与复制是两个完全独立的概念:事务关注并发控制与原子性,复制关注数据的多副本分发。即使一个事务同时修改了对象 A 和对象 B,理论上复制机制也可以单独同步对 A 或 B 的修改。然而,在实际的业务场景(尤其是关系型数据库)中,如果将事务拆开复制,就会导致严重的数据不一致——比如银行转账场景中,账户 A 扣减 100 元而账户 B 增加 100 元,如果只复制了一半,账目就会失衡。因此,工业界在关系型数据库中做单 Leader 复制时,通常都将事务作为复制的基本单元。
[0:00] Scott Shi: 不会的,它只是 generate 已有的 code。
[5:00] Scott Shi: 数据往往比代码活得更久
[5:00] 道格拉斯·亚当斯: 事物可能会出错与绝对不可能出错之间的主要区别在于:当一个绝对不可能出错的事物出错时,它通常会变成彻底无法挽回的灾难。
[5:00] Scott Shi: What could go wrong, eventually will go wrong
[14:48] Scott Shi: Kafka 本质上就是一个简化版的 Database
[25:00] Scott Shi: 黑社会的旧老大突然死而复生
[55:00] Scott Shi: data structure 直接 mess up
[60:00] Scott Shi: 复制(Replication)与隔离级别(Isolation)是完全正交的两个概念
[60:00] Scott Shi: who is winner, who is loser
[70:00] Scott Shi: 能看到未来 10 秒
Original transcript
[0:00] 在开始前,我先给大家看一个很有趣的tool,就是我这两天在Xplot的东西,就是OpenAI的这个API。这个OpenAI这个是最近开放一个API,然后它现在的话其实BetaUser只Release了大概四五百人,然后可以做很多东西,我觉得还挺有趣的,比如说比如说 I think 是吧,就是它正常的就是一个填词,但是你可以比如说你说我输点东西然后它给你填然后就是 I think therefore I am 是吧然后他给你填这个词,然后就是他能做的一件事情。比如说,然后他这块可以填一些configuration,比如说他response length,temperature是randomness,然后还有一些NLP的东西是吧。然后我还尝试了一下其他的,比如说,我推呢。是倚谢谢大家谢谢大家谢谢大家我想的是iceberg是吧,然后他就告诉我说,what we know is a typical iceberg然后这种,它可以填词,然后它其实是一种 pattern recognition,它还可以做以下的东西,比如说可以做 classification就是他给的一个例子,比如说他Facebook的话是media和这个technology比如说 FedEx的话他就给你填 FedEx 是什么公司你run的话就告诉你FedEx是什么公司,他告诉你是logistic transportation是吧我们这块可以输一些比较冷门的工资反正我试了一下比如说EAA出过去的话它还是能Pause-ride的就是个 video company 是吧然后好然后就是这个classification,然后它还可以做一些summarization和这个text command 和这个Q&A和chatbot我觉得还是做的比较好的,我仔细去试验了几下,我觉得试的还是比较好的。嗯谢谢大家好对就是这样子的,它反正是个taxing,taxout的一个程序。我现在的话有几个想法想做,但是管理时间比较缺,不知道这个能不能有空做出来。OpenAI有很多例子,我可以把这个放到这块,感兴趣的话可以读下Document,我放到这个chats里面,可以读下Document和已有的例子,我觉得有些例子还是挺有趣的,比如说他可以,他最多用的最多是 generating 嘛他比如说可以 generate music 啊然后可以 generateLabel 可以 generate idea我记得前段时间有人切了一个很有意思的文章说他可以 generate HTML code 他可以 generate code 是吧我觉得还是比较有趣的但我那个没有仔细读就是说你不用写code了你用它generate html code就可以了但是我没有仔细读,我没有看它具体怎么样子然后我觉得它就是一方面是generator,一方面是做这个,你看它这块有个react component generator他帮你generate code 是吧?帮你generate code谢谢大家我看到它能generate code,然后我看到有generate的email,然后 generate summary 什么的,反正就是还是挺有趣的它是挺有趣的反正它这个也是用这个Deep Learning做的这个是领先的比较多的我看说能generate code我们是不是快失业了 不会的它只是generate已有的code 你比如说这种非常简单的HTML给你画个地方,然后弄个 reference 什么的,这个 code 中最复杂的不是那个什么,不是那个 code generation, code 中最复杂的是那种 logic还是比较复杂的,我觉得感兴趣的话可以读一下,然后读一下这个东西,我觉得还是比较revolutionary的。我觉得还是比较Revolutionary的。好,今天讲Replication 2,就是给overview一下一个Progress,Replication 1,Part 1,也overview一下这个Progress,是我们今天讲的这一部分了。然后,就是下次的那个System Design呢,就是Mock Interview的话,可能是讲Tiny URL 或者是 cracklist 中的一个,因为我们下一周的这个interview 的这个 Leo 是吧,candidates 是 new grades 是吧,还没有毕业,还没有毕业。所以他这个项目问题可能会简单一点,但是可能会问到。然后我们今天就看 replication。对刚才那个感兴趣的话,你如果有什么好的 idea,然后你想试一下的话,你可以联系我,我可以share一下我的 API Token。然后你可以试一下,我觉得是比较有趣的,我仔细看了一下我觉得比较有趣,其中几个use case可能还用的挺好的。
[5:00] 他这个比之前的improve很多好好 讲 replicationReplication就是跟Partition是在一块的,就是在内容书上一块的。Replication是在Partition之前,但我觉得我应该把它放到Partition之后。Replication 相对来说是整个Distribute System里面造成麻烦最多的地方因为我们不停地在强调一件事情,就是在distribute system 里最重要的是data嗯data的话有不同的version,是吧?不同的version data,然后有不同的code,不同的version code,然后一般data都是out to code的然后在replication里面,在data中,造成data的inconsistency的时候,很多时候是你做replicate的时候,你有一个replicate的时候不是以下replicate过去的,是吧,是async replicate,然后我们都有一个概念叫eventually consistent,所以这个replication 因为这个eventual consistent和这个async replicate就造成了很多问题你这个 data copy 的时候造成很多问题所以 distribute system 里面这个是单机没有的问题,就是distribute system里面replication是造成很多问题的源泉之一很多问题的原权之一也是有不同的database流派之一所以说你说就是Sycle和NoSycle,其中比如说DynamoDB,DynamoDB这个是我们不说,就是我不喜欢把DynamoDB叫WideColonialDatabase,我也不喜欢把DynamoDB叫做KValueDatabase我觉得DenemoDB更像Leaderless Replication的Database,或者Denemo-like Database因为它主要解决的问题很多时候我觉得它最多解决的问题就是replication的一部分问题,就是它解决replication的问题,focus on replication的问题。然后distribute system 中很多最复杂的问题也是就是比如说那个 concurrency control 啊然后Transaction也是多多少少和replication有点关系的然后replication使它的东西更复杂了一点然后然后说的conflict,distribute system中基本上conflict基本上所有的这个distribute system的conflict也多少来自于replication好所以说这个replication是distribute system中最复杂的一个问题所以这块的话我打算分两次讲 分两次讲然后如果大家 我也希望大家有空的话去读一下这个细节啊 特别很多东西的话 有一些细节的话你可能需要再反复读一下反复思考一下这个是相对比较复杂的一个部分然后我觉得这个艳语写得很好,就copy过来了,说,a major difference between a thing might go wrong and a thing cannot possibly go wrong,是如果一个 thing cannot possibly go wrong,go wrong,then turn out to be impossible to get a repair.就是说可能会出错和不可能出错的区别就是如果一个不可能出错的东西出错了,那就变成一个disaster了是吧,就很有可能impossible to repair 了这也是distribute system 里面我觉得很重要的一个概念就是一定要分清什么东西是可能出错什么东西是不可能出错的如果是一个可能出错的东西在distribute system 里面有个概念就是 what could be go wrong?就是eventually will go wrong 是吧一个东西可能出错,给它足够长的时间它一定会出错的但是不可能出错的话就比如说有一些physical law是不可能出错的是吧那就不可能出错我们就可以我们就可以safely assume不可能出错所以这个是有本质的区别的但是在包括我们设计一个系统的时候,特别你要考虑到这个DataSafetyNess的时候,特别是比如说这个Data要AbsolutelySafe的时候,或者AbsolutelyCorrect的时候,那你一定要想到它什么时候可能会出错,那可能出错这个scenario,这个condition是一定会出现的,给它足够长的时间是一定会出现的。然后从replication的意义上来说,它就是把一个同样的data在不同的 machine 上 copy 了很多份然后这个的话是通过 network 来连接起来的我们为什么要做 replication 呢?replication 主要做有几个原因一个是为了让这个 data 呢就是从 data 呢 geographically close to you比如说你现在的data的话,比如说Amazon的话有十几个,二十几个available room,是吧,Data center available room。如果你现在只有一个Data center,北美只有一个Data center的话,那你是个欧洲的用户,你的lentency就非常高。那比如说Uber只有两个data zone,是吧,Data center,Phoenix和DCA。那如果你去比如说Russia打一辆车的话,那你的lentency就很高。所以你的当你的data center,geographically close to you的时候,lentency也会低很多。这个的话会低,可能average可能低几十毫秒,就是几十毫秒到100毫秒之间,因为这个跨太平洋的这个lentency大概就是
[10:00] Es que no... P99 + 100 mts Y también, hay que replicación de la aplicación, que es para que si el sistema de la data center se desvanece, o que se desvanece, o que se desvanece, o que se desvanece, o que se desvanece. O que el sistema de la data center se puede ayudar a hacer su servicio. Esto es lo que está en el caso de la área de la área de la área. Es decir, que puede, al menos, que en un lugar de la data center, o que hay que tener una data center o que hay que tener un centro de la área de la área. Y el servicio no es de la área de la área. Es decir, que es lo que no es el servicio. Y eso es lo que se ha hecho. Y luego, Otra requiem es que es Si se ha hecho una aplicación, si no hay una garantía reciente de datos, no hay garantía que la red es el primer dato. Si se ha hecho una aplicación, puede servir la red-corred. Esto es muy necesario. Es posible que la red-corred de datos. Y este libro es muy largo, hice un gran cagón, un contenido de la cagón. Hoy vamos a hablar de single leader replication. Single leader replication es un parte más de un parte más de un parte. El single leader replication es más de lo que es usar MySQL o Relational SQL. hay una primera server y dos backup server Y si hay que tener que hablar de multiliter replicator "Multi-leaders replication" es el primer de la aplicación de Uber, es el "multi-leaders replication". en poco a Facebook ato, a multiliter replication. Es una forma de una obra de un gran tipo de trabajo. Es decir, es más que un líder de un líder de un líder de un líder. y entonces se utiliza multileadar replicación. Pero en el caso de una sola leadar replicación, no hay que resolver el conflicto. Es como resolver el conflicto, porque multileadar es muy difícil de conflicto. No es como single leadership, es muy conflicto. Y finalmente, es hablar de un líder. Cuando se hace un líder de replicación, lo que es un líder de replicación es muy diferente. Es decir, en el database, como el DynamoDB, es el Best Effort Database. Es posible que la data se puede hacer un dirty read o dirty write, ¿es verdad? O sea, la data se puede hacer un repair, ¿es verdad? Y la data se puede estar estale. Entonces, no es el dato que la garante es que la garante es el dato que la garante es el dato. El dato consistencia y garantía de compromiso mucho. Es decir, más de lo que más se sienten como el mejor esfuerzo de datos. Gracias. Entonces, vamos a hablar de tres partes. Y ahora, el enfoque es el single leader replicación. En el single leader replicación en MySQL o PostgreSQL, en la aplicación de MySQL, en la aplicación de PostgreSQL, muchas veces, como nosotros estamos haciendo un servicio, no hay ningún servicio, probablemente necesitar un uso de usuario. Entonces, cuando se publicó un usuario de un usuario, cuando se publicó un usuario de un usuario de un usuario, que se puede cambiar el usuario de un usuario de un usuario. Y en el usuario de un usuario de un usuario, que se puede cambiar el usuario de un usuario de un usuario. El nuevo es el nuevo, es el nuevo nuevo. Y en el primer database de nuevo, el nuevo nuevo nuevo nuevo. El Follower puede ser que no se puede ver. Depende de la synchronized replication o asynchronized replication. Entonces, cuando se despegue a la redactoria, cuando se despegue a la redactoria, se puede haber perdido el contenido. y no se han cambiado el dato. ¿Y por qué? Y entonces, es un single leader replicator. Es decir, cuando se ha hecho todo el requerimiento de las preguntas, todos los que hayan un líder replicas. El líder replicas es que es en línea, el show the request es de la respuesta. El show the right request es de la respuesta. El read request es que puede ir a leer replicas y a follow the replica. Cuando se... Replicado en el réplica, lo que tú lo has visto es el día de la data. Cuando se ha visto el seguidor replicas de la página web ¿No lo que no es el caso? Es el caso de los datos. Y ahora, todos los relaciones de datos de base están en la base. Es una herramienta de la construcción. En configuración de MySQL y Postgres, no sé si hay una experiencia de Terrafo. ¿Qué es el balancer? ¿Cómo se coloca en topology? ¿Y el método de mi SQL? ¿Cuáles son los primarios, los master, los slave? Es escribir esto. Lo que se dice con MySQL integración
[15:00] 挺好的Terriful.和MySQL的Integregation 写的挺好的,然后你可以这样的话通过Configure,写Terraform,然后Configure一个Architecture,是吧?你可以把这个,比如说可以把LodeBalancer放前面,然后你MySQL primary是哪一个IP address,然后Secondary是哪一个IP address,你是Synchronize replicate还是Asynchronize replicate,这个都是可以Configure的是吧?其次的话,这个Single Leader Replication 不止是用在Database的它也用在 Kafka,Message Queue 等等的我始终认为 Kafka 就是一个简化版的Database,它不能用作Database,但是它就是一个简化版Database,就是它就做了Replication和Partition,就是 Kafka是实现了Replication和Partition的一个就是 Durabody 一个 message broker或者是replication和partition的一个system,实现了replication和partition的一个system。我觉得如果感兴趣的话,读著Cafrica的原代码,看一下设计理念,也能看到它不同的replication和partition的处理方式。我们就还有个问题说CDN向Cache多一点还是向Replica多一点?CDN是Cache今天去看一下我觉得Cache和Replica其中一点很不同的区别是就是有几点不同吧第一点不同是, Replica 是当你 Master 挂掉以后,当你的 Leader 挂掉以后,你的 Replica 要随时 Reddit 成为 Leader 的这是一点不同,你的 Replica 和 Master 本质上是没有区别的你的 replica 随时可以成为 leader 如果 leader permanent 和 offline 的话 这是一点其次的话 在 database 的 transaction 里面 你的一个 transaction 可能 update 是多个 field 是吧你比如说你更新 transaction 做一个 payment transaction 你从 A 账户里面划走钱 要把 B 账户里加上钱 是吧这是一个就是你要在两个record更新,那你就是两个road更新。然后Cash的话是什么呢?Cash的话它是没有这个transaction概念,所以你读A账户的话,你和再读B账户,你可能两个Cash是不同的state但是 Replica的话你是有这个Transaction的概念的当你进行 Replication 的时候你不会出现一个中间State 是A账户少了100块钱B账户没有加到那100块钱你在replica是读不到这个state的这个更像RebeccaReplica 就是这个 transaction 的连续性, transaction consistency 是保证的,就是你进行 replicate 的时候不是简单的,就是 single record 的你去整个 transactions in your replicate如果Single Record进行Replication的话,你的Data在很多时候是broken的,是吧?你不能从A账户里面拿出100块,B账户里面没有加进100块,你的Data是broken的。如果你这时候Master down掉的话,那凭空就少了100块钱。所以这个是 Replica 和 Cache 还是有本质的区别然后我们进化看一下Synchronized和Asynchronized的一个replicationSynchronized replication这种情况下,有一个Leader有两个Follower,当User1234往Leader写Data的时候,他写Data说我要update一个新Message,新Image,然后这种情况下,Leader自己搞定了以后,Leader会告诉Follower,请把这个data更新Follower1返回了以后,Leader返回OK。当我们这种情况下的话,这个Follower1就是Synchronized Replication,也就是说当Leader返回给UserOK的时候它至少有 leader 和 follower 一 是 data 是一致的 就是 in sync 的但是它FollowR是Asynchronized Replicated所以这种情况下如果比如说第二个user比如说我来读这个data的话就是我要看user1,2,3的profile的话Image 的话,如果Corel是User2,就在这个之前CorelUser2的话我读的是旧的 data,尽管这个如果靠这个 follower 1 的话,我会看到新的 data,但是如果靠 follower 2 的话,看到旧的 data因为它是Asynchronized 进行Replicated,所以这个是有很等质的不同的。这里面有个Special Case,如果有一个叫Chain Replication,我觉得设计比较有趣的。什么叫那个Train Replication什么叫Train Replication呢比如说它有若干台机器,第一台机器是Master,第一个Replica,第二个Replica,第三个Replica所有的写,所有的write都是写到master的,就是没有问题的然后写了Master以后就开始replicate了第一个机器,然后replicate了第二个机器,然后replicate了第三个机器所有的读都是从第四个机器里面,就是最后一个机器读的所以当你读到这个data的时候,你能guarantee这个,基本上这个data呢,基本上在之前几个全部就是
[20:00] applicative work. It's just that you read the data, it has at least in the APC on all the replays. So it's consistency guarantee will be higher. Microsoft Azure of chain replication Of course, it may have different topologies Let's think about it. If we set up a new floor, we can simply simply simply copy the data file from a node to another node. There are many reasons. If we just copy the data file, for example, we discussed the A to 100. If you copy the data file, you may see that A to 100. So this result is broken, it makes sense. But if you don't consider performance performance, You can lock the database. Now many traditional companies say it will maintain. When you maintain, you have six hours left. You can do this and then put the database down. and dump it after copy it But you can't do that in a network company. How can you do that? There are several ways. There are several ways. The easiest way to do consistent snapshots is to make a consistent snapshot. So, you can use this data for consistent snapshot, You have transactions from 12345 to 100. You now have the data from the 50 transactions applied after the snapshot. And when you read this, we will talk about concurrency and control. You often support this read, but not block read. When you read the last 50 transactions or snapshots, you actually don't block the other data, so the data availability is no influence. Right? And then when you copy the snapshot to follower node, and follower node copy after you can connect to the leader, and say, I have 50 transactions, I can give you the remaining transactions. And the leader starts to send the transaction to the other. And also send the 51 to 100 transactions to the follower. And the follower is to apply. and then the approach will not change. The approach will change. The approach will change. The approach will change. The approach will change. The approach will change. The approach will change. The transaction can change. When it was done with all the 50 to 100 transactions, the master has already had an extension of 101 to 102. Yeah. Now we can continue processing the replica, just from the replica process. This replica can serve the read request. Of course, if the leader is down, the replica can be held as leader's responsibility. This is the process of setting up new followers. And then we'll see if we have two databases. One is follower and one is leader. When you have follower failure, we call it failure. So if you have follower failure, it is a recovery model. We talked about system design model. Filiere recovery, Filiere fill, right? and I forgot what else is, I have an asynchronous model. So if we can see the follower, we can recover. If we can recover, we can create a new instance, and then instink and master. If it recover, it will keep a list of log change. It will be a list of log change. It will be a list of log change from leader. Then it will be a list of log change from leader. If it is a lot of time, it will then put all transactions in the next few months and sync it. Then it will then say it is in sync. It will be like this. If it is a leader failure, it will be more difficult. There are different ways, depending on what you do, the overall design is what you do. If you are two-faced If you use two-phase commit, it is a serialized, Serialized transaction, it's our consensus model, two-phase commit. If you are two-phase commit, many times you will not support the leader. We will talk about it, if you are full-phase commit, many times you will not support the leader. If you are not a two-phase commit, you don't need two-phase commit restrictions
[25:00] 你可以把一个 follower 执行成 leader然后可以重新 configure 一下这个这个过程叫 fill over很多时候这个feel over不是被动的feel over,很多时候是主动的feel over,就是为了,就有点像那个File drill,就是你File drill的次数是远远多于你这个File的次数,像Uber的话我记得之前的话每一周会有一次feel over,后来好像改了,改的更infrequent一点,还是一个月还是两个月一次feel overFillover就是它把Primary datacenter就变成Secondary,然后把Secondary datacenter变成Primary就做这个过程,感觉很多时候更像file drill一点,保证你真的file fill over 的时候,你的service不会到。那么fuel over的话,它会发生以下几个步骤。首先是,它要看一下这个先要判断出这个leader是不是真的fuel掉了。这个leaderfuel掉可能比如说这个机器leadercrush了,或者是power outage,或network issue,是吧?你是没有,如果没有一个oracle的话,你是不知道什么东西可能go wrong的所以大部分时候我们是用timeout的说这个leaderfail掉了当你比如说你timeout的设置成三秒然后你这三秒leader没有反应的话就说这个leaderfail掉了那第二步的话你需要truth一个newleader这个truth newleader的process呢其实是非常非常complicated的因为你要达到consensus在truth newleader的时候很有可能你有新的truth newleader的时候很有可能你有新的这个就是follow也go down掉了是吧可能会出现各种各样很复杂的情况所以这个Consensus Algorithm是其实设计起来是非常复杂的我们再稍后也会看一下这个Consensus Algorithm当这两个都完成的时候,你会 configure 整个系统用你的新的 leader 作为新的 leader 。然后这个是很重要的一部分,就是不只要所有 follower 认识到这个新的 leader, 新的 leader 自己要知道自己是新的 leader 。并且当你旧的 leader 回来的时候,他自己还是以为他自己是leader,他没有意识到已经有一个新的老大了是吧就是旧的黑社会老大挂掉了,然后你选了一个新老大,然后就黑社会老大突然又复活了,他没有意识到自己不是老大了是吧?所以他必须跟其他人沟通,别人都说你不是老大了,你必须成新的老大的小弟是吧?然后你必须要意识到这个问题,然后如果没有意识到这个问题,你如果有一个旧的leader,坚持认为他还是leader,然后同时有一个新的leader,别人都认识他,他新的leader的话,这个问题叫Split SpringsSplit brain 就是脑分裂,Split brain这个问题其实还是很复杂的稍后的话,也会讲,这个系统,这本书里面也会讲一下怎样处理Split Brain的过程。Split Brain在历史上其实出现过挺多次,并且每一次出现都有一些非常catastrophic结果,就是非常糟糕的结果。这个有很多学以类的教训,这个Split Brain是非常惨痛的一个教训。好,这个Leader field还是比较复杂的,我想这块提一下的就是我想这块提一下的问题就是,我们注意到,因为它第一步的detection 是timeout如果我们注意到的话第一步Detection Timeout很有可能有一个机器它的连接很不好比如说三分钟后timeout了,然后过一会儿就回来了经常会有split brain的问题并且比如说我们再举这个复杂度还是很高的比如说再举一个例子我们就是上周四讲了partition我们上次讲了partition,在partition中,如果你比如说像设计Uber Schema类似这样的database,你一上来要有4000多个partition然后4000多个partition,就表示你有8000个follower那就是说,你其实是有多少个Master和两个Slave的?你有4000个一个Master和两个Slave。就是很复杂的,你有4,000个 master 和 8,000 个 slave然后是这样子的,所以在这么大一个系统中,假设你其中的一部分 network出问题了你一部分 network 出问题了,你的 network 有个 partition 是吧,你的 topology 在 database 里面有一部分 network彻底挂掉了,那你很有可能同一时间内有几千个Leader有几百个到上千个leader,同时要重新被election。这个其实复杂度是非常非常高的你的系统也是很有可能你的service就直接dun掉了因为这个一个Leader Election的过程经常要花100到200毫秒,就是200毫秒,当你做一个Leader Election的时候,你做Consensus的时候,不管你是做Rraft还是Paxels,你很多时候要花100到200毫秒。当你有几千个机器同时在做Leader election的时候,你的Service很有可能
[30:00] 是有这个就是很不稳定的所以这个 Network Partition 就是Data Center里面Network如果有一条主干线,这个Network被PART-D,就是这个主干线不通的话其实很有问题严重性很大的好,我们接着讨论这个Synchronized Replication这部分我在讨论这一张这块之前,我想问一下之前有没有问题,大家在这有没有问题,这个fill over, synchronize, and asynchronous replication, and follower setup,没有问题?没有问题的话我们就接着讨论replication的问题好就是我们是做replication的时候可能是asynchronized replication当我们用asynchronized replication的时候我们的新的Leader可能还没有把所有的这个新的Leader可能还没有接收到所有的old leader 的updates比如说你开始做 transaction 是吧银行做transaction,你从A账户转了100块到B账户,你在master写好了以后就返回了,然后所有的master和slive之间transaction是asynchronized做的,当你 master 返回 OK 的时候,结果你 master 刚返回给 OK 然后 master 挂掉了,是吧?然后你的那个 replica, data replication 还没有到 slave 上但是user以为上户转钱完成了然后Yoser就回去了,结果Yoser下一次访问的时候,因为这个Master已经挂掉了,他知道的东西没有人知道,这个人含恨而终,Master含恨而终,然后Slave上来以后他其实并没有新的信息,所以你以为完成了这个Transaction,实际上并没有完成。所以说这个就很严重的一个事故了,但是这个还是大部分database还是采用这个asynchronized replication,因为当你做synchronized replication的时候,你很多时候你的P99的performance要直接层二了,就是你之前是100个mins的lentency的话,现在就直接变成200个mins的lentency了,所以这个Synchronized Transaction, Synchronized Replication,这个Cost是非常非常高的,Synchronized Replication Cost是非常非常高的。然后其次的话,我们刚讨论的这个Asynchronized Replication,当你有新的Leader,就是旧的Leader挂掉以后,新的Leader可能会lost data,这个呢会变得有时候会变得非常非常的dangerous。这块就举了一个GateHub的例子,就是GateHub里面它实际上是,就是GateHub当时有一块设计就是说,他用这个database的这个Autoincrement的这个index 是吧?就是当你insert一个row的时候开始是1,然后是2,然后是3然后是4 然后是做这个就PrimaryK的 牛肉的PrimaryK的然后它发生了一件事情就是它这个PrimaryKey呢,这个Data又连接到了另一个Redis里面,就是它这个Row又连接到了RedisRow里面然后用这个呢作为Prep 就是用这个Redis进行这个Record我这块稍微给大家画一下稍微有点复杂我这块稍微给大家画一下,我们画一个Primary,旧的Primary和新的Primary。然后我们这块假设一个table,之前是1的话写的是,比如说是Uber的因为是Github,假设是Uber的一个Pool Request,是吧?然后这个是Uber的Pool Request,然后它还没有Think到这个New Primary时候,Done掉了。然后这个Primary down掉了,所以说到这个新的Primary的时候呢,你就写了一个Leaf的一个ToolRequest,是吧?也就是说这个Replication并没有完成到这个就是写了旧的primary档架以后这个replication并没有完成所以这个Uber的pr呢就是只有旧的有了然后他就喊恨而踪了然后新的里面呢因为他是UltraincrementID嘛就写了一个新的pr到LiftRequest 是吧所以他这个Lift的pr呢他这块因为是metadata所以他用这个它要连接到这个Redis上的,有一个第三方的就是一个Storage RedisRedis上到的是具体的code具体的code 但是它这个row其实连的是uber的code
[40:00] 不好意思啊 电脑死机了不知道怎么会是死机掉了啊啊然后我觉得这个故事很有趣的,这个不是一个故事,真实的例子还挺有趣的,其实跟故事一样嘛。GitHub 里面发生了安全原因,然后安全DOWN的原因就是因为它用这个 MySQL 的 Alter Incremental ID 和 Asynchronized Replication然后并且它这个这个 SQL 的这个 data 是 source of truth 然后 refer 到一个 redis 上做这个具体的这个Data Read的所以这个这个就很有趣啊,就导致了你可能能访问其他公司的代码,是吧?或者是这种很糟糕的事情其实有一种简单的方式可以guarantee这个事情从来不发生,就是当你不用这个AltrIncrementID而用GenerateUID啊,就就,至少Garantee你不能访问,就是当你出现这个事情的时候,你只是不能访问你公司的代码是吧,你不会突然让别人访问了你们公司的代码,如果它copy下来怎么办是吧,你会不会有奇怪的法律纠纷是吧,然后这个这个问题还是很严重的。谢谢大家所以这个包括我们前两天看到这个之前那个整个这个Cloud Flare 弄掉了是吧也是一个configuration 称之它把所有的 data 全部所有的 Cloud Flare 的 data 全部就是分配到Atlantis City了亚特兰大那个City了,然后Data Center了,然后整个这个Cloudflare,这个Backbone Network就全部挂掉了我觉得这个也是一个Human Arrow吧,就是你读这个Human Arrow,就是看到我们能不能从中学到一点东西。我觉得那个文章里面学到一点东西是这个Cloudfire 居然有自己的 private network,它整个backbone的这个network,都是private的network是吧我觉得要我选CDN的话,我可能会有先选他们的吧,因为他毕竟有钱,见得起自己的private network 不管是security还是performance都会好很多我觉得这个我可能会就如果我选CDN的话我可能会优先选他们因为他毕竟是有自己的private network好我们接着谈着replication的问题其次的话就是比如说你旧的老大挂掉,然后新老大上任的话,你可能会有 split-bring 这个问题是吧?然后两个人都认为,都可以认为自己可以接受 rights然后当你两个都接受Rise的时候,那你就有conflict 是吧然后比如说user向A转了100块钱然后User A 向 B 赚了100块钱,然后存到这个 Leader 1 里面了然后user向B又赚了100块钱存到LeaderB里面了那如果这两个有config的时候那到底是user赚了200块钱给B呢还是user只赚了100块钱,其中一个是fuel retry呢,这个问题就很复杂了,这个就很难解决了,是吧,所以他这个当你有speed brain的时候,这个data是很容易出问题的然后再depends on你的use case和business use case的话这个data可能会造成非常catastrophic result 是吧然后其次的话最后一点就是什么样是合适的一个read timeout的时间如果你这个read timeout的时间选择太长的话比如说你这个recover timeout的时间选择三秒的话如果你这个Server不停的这个不停的就是就是Server这个Leader不停的挂掉那你经常的话你的Response Time在三秒以上是吧就比如说当你有Leader挂掉的时候你低点挂掉这段期间,至少有三秒左右,不能送任何request。每当有个Leader挂掉的Events的时候,你三四秒不能serve一个request,或者我们可以把这个时间放的更长点,就是extreme thinking,经常是你做design的时候一个很好的一个标志,就是说假设我们把这个timeout时间设成一个小时,那假设设置成一个小时就一个小时已经forever对抗
[45:00] 就是上次来说一个小时是forever了就是特别request来说是forever了假设你timeout设置成一个小时如果你把timeout设置成一个小时的话你有一个request过来就说明这一个小时这个request我不能得到任何response那这样的话肯定从user experience很糟糕的但你把timeout的时间如果设置特别小的话比如说设置成50毫秒50毫秒的话那么的话当你的那个network稍微有点 congested或者是当你这个server就是master稍微有点 congested稍微有点毛那你这个server就这个master就被declare dead然后就promote一个slave了那你这个performance来说当你做这个你想思考一下你首先要做consensus选成一个新的master是吧先50毫秒然后说这个leader挂掉了然后做consensus选一个新的master需要200毫秒然后要所有人同意他是新的master是吧其实也在consensus里面就是200多毫秒两三百毫秒那你救的回来以后你还要认证它是新的Master就是300毫秒的一个cost 是吧就是从时间来讲大概300毫秒cost然后你还要resolve所有的conflict和data inconsistency 是吧你Master有Data如果你slave没有的话你的Data就会loss你要处理这个问题所以这个时间太短了,可能更糟糕所以说这个选正确的时间是非常困难的一个方式如果你对 network 熟悉的话你记得 network 里面,就是 TCP 那块的话是有一个 timeout 的时间就是你开始是就是按它那个有一个叫有一个叫TTP是吧好像叫TTP的一个东西TTP的一个东西还是叫什么Round Trip TimeRTTP对Round Trip Time然后你可以攻击RTTP然后再加一个具体的计算值比如说你RTTP是平均值是多少然后variance是多少如果你是一个正态分布的话你可以算一下它多少个data然后可以进行计算然后它是个正态分布但很多时候不是正态分布就是你可以通过恐惧学然后得出一个概率来计算出来它到底有设置这个timeout的时间多少比较好是吧我记得Cassandra是有一个Cassandra是有一个小的一个service是自动的计算这个timeout的时间的但很多时候这个timeout时间可能就是hardcode的一个时间是200毫秒300毫秒但Cassandra是可以根据这个RTT和这个Variance来计算自动计算出一个Timeout时间的我觉得Cassandra有一个Cassandra 5什么的Service好我们就是Synchronize和AsynchronizeReplication这块就讲完了然后我们讲这个Replication Log我在讲replication log 之前我想问一下大家有没有问题如果有问题的话直接问就好反正我们直接问就好好没有的话我们直接讲replication logreplication log 的话有多种方式最简单的就是statement based replication这也是最直观的讲做法其实也是很多时候就是database最开始的做法就是做replication最开始的做法什么意思呢就比如说我现在有一个insert statement然后我copy的时候就直接把insert statementcopy到follow比如说我有insert statement到这个leader上我就直接把insert statement copy到follow这个里面是有一个问题的是有很多问题最常见的问题是比如说我InsertStatement有一些non-deterministic functionSculptistic function比如说NOW那你这种情况下呢你就不能把这个NOW copy到Follower因为你这样的话就是在Leader的NOW和在Follower的NOW就不是同一个时间所以很多时候如果有这个non-deterministic function的话比如说Random和NOW它实际上会把这个值呢替代成一个具体的值比如说把NOT就替代成一个具体的时间把random就替换成一个具体的generate的数字放过去然后其次的话你很多时候这个statement呢是有alter incremental column 的比如说它这个它是depends on existing data database 中是吧比如说你这个有alter incremental这个primary key或者是你有这个update然后有condition 是吧然后说你这个statement必须是exactly same order去execute it因为你如果不是Same Order的话你可能之前的一个Statement会改变了这个Condition然后就天原地北了是吧天原就整个就不一样了所以这个是很就是很这个HCase很多其次的话最后的话你可能有一些Side Effect Statement比如说有的Statement是有TriggersTriggers是什么意思比如说常见的Triggers
[50:00] 这个 Column A改变的话你要把Column B的值加1比如说Count这个更改多少次所以Column A改变了以后Column B的值要加1这种常见的这种triggersStop procedure什么呢?Stop procedure是也是另一种比较长的一种你可以认为是比较长的一种就是把很多statement写到一起的一种一种一种把很多直信一句写到一起的一种一个一个blockal statement相对比较长一点是吧?比较复杂一点然后它减少了这个就是interaction的过程的stop procedure,现在的话其实stop procedure是之前就是很早之前比较火的,你要是去成传统的公司还会写stop procedure,但基本上新的公司都不写stop procedure,它的弊端太多,它的set effect太多,不管是trigger 还是stop procedure,trigger 可能还好,stop procedure 的弊端太多,也是经常被现在的从事员拿出来说,这个stop procedure 特别容易出现 bug,非常 fragile 的一个常见的批评的对象。然后其次的话,这个 database,relational database 还支持一些 user-defined function,这个也是这个也是,因为它是User Defend Function,你可以在里面写任何东西,你这个Side Defend就很难估算了,比如说你甚至可以User Defend Function,甚至可以做什么API Call也是有可能的。Depends on configuration,API 考甚至有可能的,所以你加上 user define function 的 behavior 就很难估算的,当你进行 replicate 的时候,当你把 statement 从 machine A 考到 machine B 的时候,你就可能会造成 machine A 和 machine B 的 data 有完全不同的完全不同的结果因为你这个set effect如果不是determinist的的话你可能有完全不同的结果当然这些都是可以被解决的,但是它就是会非常非常多的age cases,所以就是为什么说这个statement replication不是一个很好的replication方式,现在基本不用statement replication了。然后第二种replication叫riderheadlog,我们在讲这个Btrade的时候说我们在讲 btrade 时候说怎么样保证你的 data 是变成 durable那实际上在写data在你进行B-TRAID更新的时候在你进行B-Trade光线的时候你的Data是先写了Red Hat Log里面然后如果你的data挂掉的话你会这个database如果你这个database挂掉的话database restart的时候你会先do ready-high log然后把这个ready-high log全部apply完然后你才认为这个database recover了Recover了以后才会所有新的Request所以我们因为这个WriteHeadLog就是一个log嘛,所以这个就有点像记录一下这个log,所以说它可以用来做replication,虽然它不是设计用来做replication, 而是设计用来做durability的。就是当你比如说你当你进行crash recovery的时候你用rider headlog做这个recovery是吧所以它是为了durability设计的它不是为了replication设计的它可以用来做这个replication那不是为replication设计的是吧所以这个这种情况下的话我会看到它的弊端是什么的好B端是什么呢?首先这个rata-hat-log,因为它是做Durability的,所以它其实是一个byte,就是a sequence of bytes,也就是说它不是 human readable,它是一个 binary 的 sequence然后是直接写了database所以我们可以直接把这个log呢就是replicator 另一个replicator呢它的有一个assumption是什么呢?有一个assumption是它的这个internal implementation,internal data structure is exactly the same也就是说你的replicator internal data structure is exactly the same as leader大部分时候这个不是问题因为你写的是 Binary 嘛,你直接是,比如说你从 Database 角度来看的话,你就是直接把一个 File Page 是吧,把一个 File Page 以 Binary 进行修改,然后再写回去 是吧那你写的是 Binary 的话,那你必须 Data Structure 因为它不懂 Data Structure 嘛,它直接 Binary 修改的话,你不懂 Data Structure 。如果你 Data Structure 两个机器不一样的话,那你实际上这个replica是完全不work的,replication是完全不work的。那什么时候你的datastructure会完全不一样的?当你进行database更新的时候,比如说你当你进行database更新,你要把这些,比如说就拿postgres说吧,因为这个postgres是这么用的,postgres和oracle database是怎么用的。比如说你database更新,要从version1更新到version2,然后version2的这个datastructure是不backward compatible,和version1是不backward compatible的。是一定要把它bring off来的,然后等它全部replicate好了以后,然后进行更新。那你这样的话,master和slave都是到同一个version。如果你不把它bring off来的话,那势必会造成你的master和slave在某一个时间window里
[55:00] 在某个time window里面 version 不一样当这个time window里 version 不一样同时你在做replication的时候你这个data structure 直接math up 是吧这个data structure 直接math up所以这个是如果你是想做那个no zero downtime就是 zero downtime 的upgrade database 的话那你很多时候可能你是不是要考虑一下是不是不采用这个 Postgres或者 Oracle database 是吧因为你不知道它这个你不知道它 database这个implementation 里面它是不是backward compatible因为这个implementation特别Oracle你都没有明码的你都不知道它代码怎么实践的它如果不是backward compatible的话你整个replicate就不能用了Data就不能用了好所以说我们看前面两个log这个replicate的方式都是不适合做replication的log为什么呢因为第一个log实践方式是用来执行statement第一个就是replication方式它这个log是用来执行statement第二个是用来做durability的所以它不适合做replication log所以在我们非常多的前人的非常聪明的前人的经验下他们就专门设计了一个用来做replication的log叫logical log replication这个是专门用来做replication的它的main goal就是做replication所以可想而知它这个满足所有replication可想而知它满足所有replication的条件我这块要稍微暂停一分钟不好意思好我们看到这个是这个专门做replication这个logical log就是它这个它就是因为它专门设置着 application所以它这个问题会少很多首先呢比如说它这个你写到 database 的时候它会contentual new就是那个 new value all column 是吧然后你delete 的时候会有它delete的 key如果没有 primary key 的话会把这个 old value 的全部 log 出来如果是 update 的的话就是 identify the update row然后把新的value写过去然后呢其次呢因为它是logical log replication所以它其实是有sequence的也就是说像不管是之前statement像statement是没有sequence但是它这个logical log的话它就说哎我这是这是我transaction1这是transaction2是吧这是transaction3按它commit的顺序来是吧就是我进行replicate的时候这是replicate log1这是replicate log2所以你只要严格的按照它的顺序来的话data是不会有 corrupted 的然后然后因为它并且这个 replication log 呢它是和这个 storage engine internal 是 decoupled 的所以它是 separate concern所以你不管你的 storage engine 是怎么实践的你之前是 b-tray 你全部改成 log structure merge tray 也可以但是从这个全部从这个 logical log 来讲它是完全独立的一套语言它只是用就是同样的 data它用一套独立的语言去描述了一下所以它不管你的Internal是怎么实践的它永远是compatible所以你的Follower和Leader可以run不同的version甚至是可以run完全不同的storage engine是吧你Follower可以runlogstructuremergeTree你的Leader可以runBtree也是可以的因为它完全是为了replication设计的一个log format最后一点的话是这个log format是可以可以被这个external application to post的所以您可以读这个log format然后做这个change data capture就是说你可以把这个database本身变成一个streaming的一个structure比如说这个Cassandra是支持这个的是吧就是当你做任何这个Cassandra的upgrade的时候update的时候,你实际上所有的update可以把它组成一个CDC,然后CDC以后可以接一个reader,然后进行相应的计算和操作。最后一点的话就是这个trigger-based replication,这个就是根据这个database update,然后进行trigger,比如说这个oracle-golden-gate是这么做的,它实际上就是比如说你当update role了以后比如说你update这个 role 然后发生一个trigger这个trigger 因为你可以执行任何code 任何一段code这个code 甚至包含你去replicate上把这个data变得一致所以这个trigger based replication 它的overhide 是比其他样高一点
[60:00] - So, Thank you. really directly hand over to Thank you. So actually, we have a question. Log3 is strong isolation. Replication and isolation are not related. Isolation is related to transaction, it is related to master. Master is related to isolation, concurrency and control. Replication is what is the master and slave. replication and isolation are orthogonal replication or transaction. Yes, sure, I was talking on. So this is an orthogonal problem. You can divide these two. I'll repeat it again Replication is master to slave. You won't have config. Master is what is called slave? This is replication. And isolation and control is at the same time. So the master is to decide who is winner and who is loser. So these two are different questions. So this is not related. I love puppies, but the problem is Thank you. Let's see the question called Read Your Write Problem Radial write problem is that when you do asynchronous replication, like the template, for example, if a user added a comment, You write when you write the leader, but you do when you write the follower. There is a small time window. You user said comments and inserts are just done, but it's just master and inserts. If it's from followers, it will say no results. Right? You just didn't read or write. You just wrote the data and didn't read. This is a problem. Super long, no sound insulation. So in this case, there are several functions that you can do. For example, if your use case is like Facebook, you can do your profile. If you're using the use case or Facebook or Twitter, you can read your profile. You can read your profile. You can read your profile. You can read your profile. You can read your profile. You can read your profile. You can read your profile. You can read your profile. You can read your profile. You can read your profile. You can read your profile. You can read your profile. You can read your profile. You can read your profile. You can read your profile. But when you read other profiles, you don't know what he wrote. For example, when you're new, you'll see it in a minute later, you'll think There is a common sense, if you read it, it will be a little more new. So, even if you read it after, for the 15th minute, you read it after the 60th minute. It's not a problem. But you write your profile, the first time you write it, the first time you can expect it to read it. So the expectation is not the same. So you can read your profile from the master's profile. You can read your profile from the follower's profile. So this can be very simple to solve Facebook and Twitter's problems. And then, the other thing is: You can check the last update time. If this thing is just updated, you can read the master. If you can read the follower, you can read the replica. How do you check the time? Because the database is not the same. If you read the MySQL database, if you read the infrequent data, you will read disk. You read disk is the memory of the time of 100 to 1000 times. So you read disk is the memory of the time of 1000 times. So I
[65:00] 从in-memory database上读的话那你这个时间是你就可以减少这个时间所以你可以把这个last update time存在一个in-memory database上然后你甚至可以用一个bloom filter然后这个可以使效率很高就用bloom filter一样的东西效率可以很高那这样的话你就说我读这个肉的时候我track它过去一分钟内没有更新过那我就可以放心地从follow而读如果它过去一分钟内更新过那我可能就得从mask上读所以这也是一种方式然后还有一些其他的方式可以读这块的话有一些额外的complicities是比如说你这个service是可以从多个device上返回的比如说你可以通过desktop返回你可以从mobile返回比如说可以从fone上返回那你怎么样提供cross device的read after write consistency他最近常掉线大家是丢了啥?你丢了你怎么掉下呢?几分钟前的事吧OK 所以你这个read after write就是 multi-device 的read after write 的 consistency是就是 multi-device 的read after write 的 consistency你可以通过其他的方式来解决比如说你就是 Facebook 自己的 profile 从 master 读是可以解决这个 multi-Device的ReadAfterWriteConsistency你可以通过其他的方式来解决比如说你就是Facebook就是自己的profile从Master就可以解决这个MultiDevice的ReadAfterWriteConsistency还有一点的话就是ReadAfterWrite的话还有一个很复杂的问题是如果你的repli卡是在多个datacenter现在要求基本上都有多个datacenter你的repli卡基本上是比如说你有两个datacenter的话你可能有一个repli卡是在同一个datacenter然后另一个repli卡一定是在不同datacenter这样能guarantee就是你一个datacenter全部completed down的话其他datacenter也可以serve你的request所以如果你的repli卡在crossdatacenter的话那你没有guarantee你的connection从不同的device比如说你手机连的是一个Data Center你的那个Phone就是你手机连的一个Data Center你的Browser不一定连的是同一个Data Center是吧可能是不同Data Center那么这样的话你如果RAID的话如果RAID from Leader的话那么你可能你的Performance会比较糟糕如果你RAID from follower的话你基本上guarantee你有一个device有一一个 device 有个 time window 是不能 read afterread or write 的所以说 这种情况下可能你有多种 trade off 是吧你可以说 只要是这个 user 统一从 data center A 里面读 data如果只要是这个 user 统一从 data center A 里面读 data你可能能 read or write但是你可能 performance 会比较糟糕 是吧可能Data Center A可能突然 down掉了或者performance degraded的话那你的performance会很糟糕你不能从最好就是当前最好的Data Center读数据然后其次的话你的write可能都要经过这个Data Center的话你的就是你可能需要一个 extra road 是吧比如说你的Data Center比如说榜第一层 San Francisco但是如果你去其他地方travel的话比如说你是去北京的话那你可能performance就很糟糕 是吧你就不能去读Asia的一个Data Center或者是你这个Account的如果是多人share的话同时有人在北京和San Francisco的话那你就不能就进了就是wrote你的request到就近的Data Center而去wrote到一个固定的Data Center那你可能performance会比较糟糕还是跟你的business case来设计到底是你到底希望consistency更好一点read write还是希望performance更好一点你的lentency 更好一点Read or Write 呢还是希望你 performance 更好一点你的 lantency 更小一点这个还是这个不一样的好Read or Write 呢是一个 consistency level就是你希望相对来说是比较低的一个 consistency level还有一个是 monotonic rate 的一个 consistency levelMonotonic rate 是什么意思呢就是说这块给了一个例子这块给了一个例子就是说当你insert一个comment的时候你这块leaders返回ok了然后开始replicate a follower比如说比如说你说这个比如说这个user12345说现在几点了是吧user12345说现在几点了然后发过来然后你2345看到说现在是现在是5点是吧然后把2345说现在是5点是吧所以正常的时间段的话你看这个电话应该是由于1234说现在几点了然后2345说现在是5点但是你在因为它这个replicate是有延迟的如果你到replicate到2的这个performance的话可能就不一样了变成什么呢
[70:00] 看到是现在5点然后一台温现在几点了可能会这样的结果甚至是一种 casual write 没有 being resolved 的情况这是一种情况,然后可能另一种情况是什么呢?就是比如说这也是一种情况,就是也是1234说现在几点了然后234我说现在5点是吧然后你从这个Follow-on-R角度来看的话,就只有看到现在五点,然后你没有看到它的问题是吧,你没有看到这个,你没有看到它一问他的问题是现在几点了,所以你其实就是导致什么呢?就是你读的时候你是read back to the time,是吧?你是实际上读到之前的data就是先看到一个之后的Data,然后再看到之前的Data先看到之后的data,然后再看到之前的data,这个是很有问题的。这个和ReaderWrite复杂度不太一致不太一致的原因是什么呢?就是假设这个radar可能来自于不同的地方,它这个monotonic rig的总体来说是比radaride更 strict的地方更strict 的一个 concurrency control一个, sorry,一个,一个,一个,一个 transaction control.为什么呢它应该是一个 consensus 要求更严的一个 consensus 为什么呢?因为这个 monotonic read 呢,假设你 reader 不管是 read 哪一台机,不管 reader 是哪一个read的哪一台机器它得到的结果都是连续一致性的,你不可能read back in time你不管ray的是谁,你不管Rate是哪一台机器你Read的是incremental的,是递增的,你不可能Read back in time但Radial Write 可能就是当你进行radial write 的时候好你可能会发生一种状态就是你某些user是能read or write 但某些user可以不read or write就是你可以read一个之前的也可以所以它这个总体来说monotonic read是要求更高一点,更难满足一点。所以Monotonic Read 呢,所以它要求,如果你怎么实践呢?一个简单的实践方法就是所有的User读的时候都是从SIM Replica 读因为你这个replica进行transaction上,除非userreverttransaction,footedtransaction是一个一个patch过来的如果你的所有的user固定的从一个固定的replica读的话他不读不同的replica的话那他是不会发生这个问题的比如说这个user 2345读的时候他是先从 Replica 1 上读到了 Comments 然后 555然后再从RubyCut2上然后因为它replica2还没有被replicated,然后读到没有这个comments,是吧?所以它是从不同的,就是它这个request wrote到不同的followers上,所以才导致它这个readback in time如果他读的是同一个 follower的话,他就不会发生这个事情,因为这个 insert operation 是不能 revoke 的谢谢大家有问题吗?好 所以是所以这个问题啊,这个的话就是,这也是Montotonic Rate的一个,另一个这个casualty violation的一个case就是Mr. Boone就说问一下Mr. Cake是几点了,我觉得这个好像是那个Starrgate的那个梗啊,就是Starrgate的一个梗。然后他就问Mr. Boone 几点了,然后他写的时候呢,写到之后了,就是replicate 之后了,然后Mr.Kig说现在是现在是,就是能看到多久到Future,然后Mr.Kick说大概10秒钟能看到Future10秒钟,然后从这个Observer的角度来讲,Observer的看都是,就是看的这个Data呢,从它的角度来讲,因为它读的时候是先读到这个answer,然后再读到这个question,所以它感觉就是violate了这个casualty rule。就是他先读到这个,先读到COS,然后再读到那个,Result 是吧?一般来说是有因有果嘛他先读到果然后再读到原因那就violet 这个casualty rule好呃我看看还有多少谢谢大家谢谢大家谢谢大家我今天就讲到这边,我觉得这块,因为我这个准备slide有点早,所以我感觉我这块
[75:00] Prepare不是太好,我可能下周稍微多花点时间Prepare一下这个,我感觉多举点例子吧,我觉得这个slide准备别点早,可能Prepare不太好,然后其次的话我觉得这块问题确实比较到这的话问题就比较hardcore一点了是吧不管是replication的问题还是后面的这个transaction的问题还是这个consensus的问题就接下来几周的问题都比较hardcore一点所以有时候我自己看的话我也得需要想一下然后我觉得这个可能需要多花点时间准备一下然后我感觉今天有时候这个逻辑讲的不是很好,我感觉今天逻辑讲的不是很好,可能花的时间有点不够,我可能下周稍微多花点时间准备一下计划。然后我们下周的话,我可能重新再讲一下这个monotonic read的计划。我稍微多准备点例子来做,因为这个其实复杂度挺高的,就是很多时候不太理解的话,复杂度还是蛮高的。我可能还是多花点时间去解释一下这个,多几点例子解释一下。这样的话我们下周差不多有22个slides,今天讲了16个slides,相对比较分布的比较均匀一点。嗯我感觉今天这周时间可能准备的不太充分啊,感觉讲的不是太好,如果大家有什么问题的话可以提一下谢谢大家Scott我有个问题,你说这个replica其实是基于transaction的嘛,你的replica每次都是对于某一个transaction完成了以后,然后他他可以replicate到剩下的地方 还是说这两个是完全独立的可以对,这两个其实是独立的概念,Transaction是Transaction, Replica是 Replica,如果你看这个对,是独立的概念,但是当你进行这个 replica 的时候,如果你 replicate 了这个 transaction 只 replicate 其中一部分,而没有 replic 另一部分的话你会造成这个 data inconsistent就是从概念的角度来讲你replicate 的时候你是没必要完整的把一个transaction 进行replicate从概念讲因为你的 transaction 我们知道 transaction 里面可能有多个 object 能 modify 是吧你可能对Object A和Object B同时进行Modify从概念上讲来说你进行Replication的时候你是没必要把这个transaction就是对A和对B的这个update全部进行replicate,同时进行replicate但是从 Use Case 来讲,从这个guarantee 来讲很多时候你要确实要同时做这件事情否则的话比如说你从银行账户里A减了100块钱B加了100块钱你在replicate的时候如果replicate只replicate一半的话这个账户上钱就对不上了所以就是说如果你是只是从这个概念讲的话从replication这个概念讲的话是没必要按这个transaction的顺序来进行replicate的的如果你没有 transaction 这个 consistency 这个 requirement 的话 你是可以单独 replicate 的但是实际上如果大部分时候 你是有 transaction 特别是这个我们讲的 single leader replication 很多时候就是讲的这个 relational database 你看我们现在讨论说的东西都是 relational database 的如果是relational database replication的话你是有transaction的概念的,所以很多时候你进行replicate的时候,你这个transaction进行replicate。谢谢大家所以我们刚刚讨论的就是任何三种log based他们其实如果我们讨论了是SQL database的话都是都是基于transaction上面的,都是基于transaction的都是GCAN,不管是我们可以看一下,不管是之前的statement,不管是statement,你一个transaction可能多个statement,那这几个statement就同时进行replicate就可以了,就是打包起来进行replicate,就list的statement进行replicate,还是这个write-hand log,你一个transaction可能有几百条上千条write-hand log是吧,也有可能,那你只要打包进行replicate就行了,然后最后一条的话也是一样的,也是可以打包进行replicate的。既然有了,我打断一下,如果既然有了这个log的话,那就说明他们是一条一条之心的得到这个transaction是一条一条之形的就是有有甚实性能你是一个 transaction 里面的 statement 是一条一条制行的吧一个Transaction 可以很大的哦,一个Transaction 很大,你知道就是Database的Transaction设计的时候是什么呢?就是之前最早的70年代80年的Database,它的Transaction设计是整个,你比如说去PriceLite,去订一条机票是吧,或者是你去DataBase,
[80:00] 一个电影票,你整个一套是一个transaction你一个transaction是持续几十分钟的可能所以Transaction之前的设计是很大的一个Transaction,就是之前的interaction很多,比如说你要订个电影票,你首先要写上电影,然后开始记录,然后再写上到底哪个场次,然后再写上哪一个实践,甚至还要可能额外订点什么爆米花什么的,然后再把它TransactionComb掉,就是整个是一个Transaction。就是Interactive Transaction 是一个 Transaction,这个 Transaction 可以很大,可以知识声很久里面可以有几十条 statement 哦那也应该是到最后完成的时候再写进去吧就是写到这个replica log 里面去吧对,Transaction,就是我们说这个 concurrency control和这个replication不同的一点就是Concurrency and Control is the responsibility of the transaction. If you have a transaction, you can commit to the same. If there is conflict, you can revert to the same. If there is conflict, you can commit to the same.就是它是 concurrence and control然后这个replication是我知道有哪些transaction,然后transaction123453这个选项 committed我现在要把这个12345 transaction12345从MasterCopy到Slave上懂了,了解。懂了吧,所以我们思考的时候,这个Database之前有一些前因后果,之前的上世纪80年代的这个Database的设计思想就是一个transaction就包含了整个business flow,那你一个sonsession持续几十分钟都可能,因为你不停地等Client输入新的Data现在的话都是讲究这种短的transaction,就是你比如说你选个位置就是一个transaction,不是整个变成一个transaction,这个设计其实很糟糕。好,我们有什么额外的问题吗?所以有没有人在那边好谢谢大家好我还是推荐大家读一下这个次来的,因为这个replication,从replication这一章开始,不管是后面的这个Transaction还是Consensus,而后面第三章可能还稍微好一点点是吧第二张这几张都是非常Hardcode的,就是有时候我自己解释的时候,我也得稍微想一下,稍微想一下,我确实得多花点时间稍微准备一下。谢谢大家稍微额外的看一下这个问题还是很复杂的所以大家其实如果不看的话它确实确实就比较hardcore一点了,比较难一点了好,今天就到这里吧,谢谢大家。Scott,我让你有时间,我还有一个就比较小的一个实际的问题。你问好了。就是假设我们现在比如说做一个,比如说一个系统就比如说类似于像Facebook这种,就是比如说Friendship或者user这种 service,然后这很有可能就是全球性的那个,就是部署的嘛然后这个用户数量也会很大然后如果是这样的话我是在想是你如果是做replica的话你是建议就比如说像用MySQL这么做就是你就把一个挑一个主的stack就是作为那个所有的写都在这个主stack然后把剩下的地区全都变成replica情况会多一点。那 depends on the use case.Multi leader,Multi leader 的好处就是,就是availability,就是你的performance更好一点,但是你可能要resolve the conflict.谢谢大家你可能会有conflict来resolve,那你希望你的performance更好一点吗?就是你的availability更高一点,然后lentency更低一点,还是你希望这个data就是更consistent的一点,就是你读的时候你的data更consistent的一点就是看你的 Use Case 相关谢谢大家好OK 但是如果从我刚刚取决于这种application level来说的话是怎么样去我知道你刚说的两个一个availability一个是consistency但是如果你分析的就是就是user service这样一个服务的话就到底具体到业务上面有可能会什么样的影响User Service的话,你看是什么User Service了,你像Uber的User Service和Facebook的User Service是完全两种概念。我为什么说Uber User Service完全两种概念?因为Uber User是没有Friendship这种说法的。你是你看不到其他user的,你最多看到一个driver和看到一个driver,他的interaction比较少你看到 driver 就是你比如说
[85:00] 你直接上只看到就是你 driver 的一个 user 是吧?你会看到自己的 user那这种情况下的话我觉得就是你所有的写和读,你可能都得看最新的嘛,你比如说这个,你可能看最新的,你写和读可能就是Rode到同一个Data Center上然后你就是一个user就是roll的同一个代表上,然后从这个最新的读我觉得是可能比较make sense 的。然后像Facebook的话你这个你其实读的时候你其实写和读的时候你这个读是远大于写的你读诗远大学写的是吧你读的时候你可能要读几十个User的updateHLets然后你可能经常去访问其他优责是吧然后其实Facebook的话是基本上你是希望一定要订个read or write 吗所以你写的话,你写和读自己的user的话写和读可能都是从master的,你读别人的话你可能从slave上读这是一点,然后其次的话Facebook可能他自己应该就是那个Face 还是做了一些denomalization的,就是他实际上是把那个data呢,就是denomalize 一下,他不是normalize data,是denomalize data,然后这样的话他读的一个就是DNOM 的 data 所以它放弄的时候的数字可以更快一点这个还是 我觉得从 High Level 来讲 其实怎么样都可以 但是你有些东西可能一定要满足的话比如radial write一定要满足的话那你可能得考虑一下是不是做一些优化HIGH LEVEL的话我觉得这个还是太HIGH LEVEL了,我个人觉得我个人觉得不管你是从Leader上读还是从Follower 读还是不管是Single Leader Replication还是Multiable Leader Replication,从High Level来说都还是可以的。这个还是跟具体Use Case来相关的。可能还是要说,哪些论则是绝对不能break 的。那如果比如说有些论则是某种Consistency,某种Consistency是绝对不能break 的。那你如果是Multi Leader的话,有一些conflict是很难resolve 的。好multi leader 的一些 config 是很难 resolve 的所以你那种情况下的话你可能要么就考虑用一个 CRDT 的一个 data structure 是吧要么就直接考虑用 single leader 来做谢谢大家就是CRDT的这个Dial Structure和这个MultiLeader这个Architecture我们下周也会讲所以这块不懂的话其实也没事好好,CRDC相对来说比较新,其实最近炒的比较火,但是其实本质上也不是很复杂我自己没用过,但我读了一下它这个concept,我觉得本账不是很复杂的谢谢大家谢谢大家好的 如果大家没有问外问题的话 今天就到这了 我下周可能多花点时间 然后还是希望大家读一下 这个真的是有点复杂的 解释一遍也挺复杂的 希望大家读一下多点自己的思考 然后有问题的话 我可以多讨论一下好,谢谢大家。