「分布式系统之美」知乎圆桌精选收官篇 | 圆桌直播精彩实录放送

百家 作者:PingCAP 2020-09-27 18:50:47

持续两周的「分布式系统之美」知乎圆桌已于本月圆满落下帷幕。在收录了大家精彩问答的同时,我们也举办了一场线上直播,与四位来自知乎、伴鱼、PingCAP 的大咖们一起探讨了圆桌中热度最高的几个问题。整场直播持续了 2 个小时,干货满满,现场气氛好不热烈~

本期回顾整理了现场精选实录,来看看嘉宾们的精彩回答吧!


Q

大家知道 CAP 这个理论在分布式系统里非常的耳熟能详,但这到底是不是一个严谨的理论并不好说,所以经常会被解释成一个三选二的定律,请问这是否是一种误解?

徐成选:我这边今天看了这个问题,也浏览了一些高赞的答案,基本上都认为是一种误解。在我看来从一定程度上,尤其是从实践中来看的话确实是一种误解。首先像 CAP 的三要素是一致性、可用性和分区容错性,这几个其实是有自己的定义的,从 CAP 理论本身的一致性来看,和其他比如 BASE 或者是以前 ACID 可能会不太一样。这样基于 CAP 本身这三个定律,每一条自身的定义结合实践的时候确实会存在都是 AP 系统或 CP 系统。这是怎么来的呢?首先是 P,就是分区容错性,一般都是网络分区,因为 CAP 本身定义也是基于网络的数据共享系统,而现实中的网络问题是比较多的,尤其是跨机房的时候,就算是一个机房也经常有问题,比如像节点之间的时延过长。其实时延过长也是一种 P,网络不可达更不用说了,也是一种分区。时延过长这个问题大家在现实当中几乎经常遇到,从实践这个角度来讲的话 P 其实是一定存在的。当 P 存在的时候,剩下的就是权衡 C 和 A 的问题了,C 和 A 的问题可能针对某一项,因为状态机我们操作一个数据的情况变成 P 出现的时候,我们停止操作,保证整个数据的一致性,要不然我们就继续操作,保证了可用性,所以可能对大家比较有意义的选项就成了 AP 系统和 CP 系统了。从实践角度来讲的话,其实这个理论看起来不能叫三选二,更多的是 P 成立,我们选 A 和 C 的问题,这是我的一个理解。

如果再稍微延伸一点,像 CAP 中的 C 基本是强一致性的,A 其实强调的是 100% 可用,但我们现实中设计系统的时候,一致性的种类是比较多的,可用性我们其实也是有一定余地的,比如三个 9 的可用性甚至四个 9 的可用性。如果 C 和 A 的概念稍扩展开来,可能就不太一样了。有一些类似于最终一致性的系统,比如 Cassandra 或 AWS 的 DynamoDB,网络分区的时候也有一些合并机制,他可能就兼顾了一个网络分区、一致性还有可用性,这时候可能就都有保证了。并且还有其他一些概念,像 BASE 或者是单机的 ACID 或者是分布式的 ACID 怎么去考量,这时候可能跟 CAP 本身的三选二又不太一样了,所以整体上来讲的话,不能直接叫三选二。
白瑜庆:我是这么理解的,CAP 三选二我觉得可以先设定一个概念,就是说这个 A 是不是 100% 可用或者说是几个 9 的可用?比如我们现在做到 0.99999 或者 0.9999,那这个 CAP 其实是可以兼顾的,因为 P 在实际情况中是肯定存在的,不只是网络故障,节点故障也会出现,我们可以通过很多技术, 比如说多副本等很多一致性的方法去减少 P 的影响范围。比如说一个节点坏掉了或者一个实例坏掉了,我们启用副本的话不影响他的可用性和一致性。
如果是跨地域的,我们的系统具备地域性的感知能力,来配合上层的流量管控。本质上,如果是单机房的分区,我们也可以保证整个系统的高可用和一致性,这是我的一个理解,如果说 100%,CAP 这边可能要三选二,如果说可用性不是 100%,而是几个 9 其实是可以做到一定程度的兼顾的。
黄东旭:对,我个人的理解跟老白这边其实是比较接近的,为什么当时 PingCAP 的名字叫 PingCAP,我们其实发现 P 肯定是必选的,一个分布式系统必须选 P,第二点我们觉得 100% 的 A 是不存在的,就是说其实这个世界上没有 AP 系统。这点我可能有点极端,但真正符合 Brewer CAP 理论的 AP 系统是不存在的,因为 A 只要是一个物理存在的系统,就有可能是不可用的。比如说我这个系统三个地方同时地震了,原来理论 A 就是 100% 的可用性,不管什么情况,光纤全断了、地球毁灭了,这些情况都可能导致 A 是不存在的。但 C 其实是可以做到 100% 的,于是就变成了要不要选 C。我觉得一个更好的说法是 HA(high availability),所以现在 PingCAP 的名字我们是想把 C 跟 A 跟 P 连在一起,但 A 其实并不是真正的理论 A(availability)。
同时这里面有一个经常被人误解的点,就是 C 到底跟  ACID 里面的 C 是不是一个 C,我的理解并不是,其实这两个是完全在不同的层面上去讨论不同的事情,ACID 是事务那边的。我举个例子,CAP 里面的 C 更像是把一个存储系统当做一个寄存器来去对待,就是我一个写入,一个读取,是一个类原子操作,但是在分布式系统里面的这个 C 可能更像一个分布式寄存器。 所以对于 TiDB 来说,他其实是在底层的 CP 系统上去构建 ACID 的能力,但并不是说满足了 CP 就一定能满足 ACID,以上是我的理解。
陈现麟:我还想补充一点,刚才东旭讲很的对,没有 AP 系统,其实正常讲很多系统也不是 CP 系统,比如数据库,我们说的一致性其实不是 CAP 里面 C 所指的线性一致性,我们数据库提供的隔离级别、隔离系统其实不管是可串行化还是可重复读,它们都达不到线性一致性的要求,所以理论上来讲很多系统也不是 CP 系统,因为 C 的一致性有很多等级,比如说很多情况下可重复读已经够我们用了,像刚刚的可用性也是一样的,可能 0.9999 就够我们用了,那其实也是可以的。

另外我觉得可能对于架构师来讲,我们讲 CAP 这三个不能全得,但是对于业务系统来讲是可以做到的,比如说我们有三个数据中心,有一个挂了,那其实正常来讲肯定是不能选 C 的,或者是 A 跟 C 里面只能选一个。但如果是一个业务系统,我们可以把挂掉的数据中心的流量路由到另外两数据中心这边来,其实这个时候对于用户来讲无感知,就用户角度来讲他是 CAP 都有的。但对于我们系统,我们当时可能只能选一个,这对架构师是一个更高的要求。并且 CAP 是在 90 年代提出来的,他是为了让大家放弃 ACID 这个理念去做 BASE,所以现在来说,我认为 CAP 是一个有点过时的理论,大家要想办法把 CAP 三个都兼顾。


Q

有很多同学,特别是在业务中使用单机数据库的,包括 MySQL、Oracle ,在尝试分布式数据库系统的时候,总是会想了解前人有踩过什么坑或者说在实际业务场景落地中面临的最大的挑战是什么?

陈现麟:其实我们伴鱼用分布式数据库算是比较早的,差不多 1.0 的时候就开始用 TiDB 了,对我们来讲最大的挑战是早期,因为当时使用 TiDB 1.0 的时候我们有很多未知的情况,也不太了解 TiDB 和 PingCAP 这个公司,对我们来说最大的挑战首先是彼此的信任,我们要知道这个数据库能解决我们的问题,并且是稳定的,这个很关键。

在当时用 TiDB 的公司确实比较少,所以就只能通过技术调研跟 PingCAP 去沟通,我们从理论层面再到一些 PingCAP 给我们的数据,最后通过我们自己的验证,让我们知道这个其实是没有问题的。上线一个数据库很大的一个问题就是如果业务本身已经跑起来了,那切换的时候肯定要很平滑,一点问题都不能出。比如说我们就是用的 MySQL,协议都一样,有可能某个执行计划不一样会导致上线的问题,所以在整个切换的过程中,我们从 MySQL 或者 MongoDB 再切到 TiDB,每一步都要可回滚,万一有问题可以回来。我们就是通过这种方式一步一步可回滚地从 MongoDB 迁到了 TiDB 上。此时最大的挑战是在稳定性,不能出一些线上故障的问题。

黄东旭:在保证稳定性的过程中,你们做了什么工作?不管是在 TiDB 也好,还是像 HBase、Cassandra,甚至比如说 MongoDB,我不知道包括成选,还有老白这边有没有经验,从一个单机系统把业务改到分布式系统,中间有遇到一些实际的坑吗?来一个实际点的案例分享一下。

徐成选:像我们伴鱼这边其实会比较多一些,我们几乎从 2016 年底就开始 all in TiDB了,但在这之前还有一部分数据库大量使用了 MongoDB,尤其是在创业早期, MongoDB 还是比较有优势的,他的 Schemaless 很方便开发。但迁移过程也会比较谨慎,尤其是 MongoDB 里面积累了一些历史大表需要迁移到 TiDB 上,这其实会需要业务做一些感知,比如说双写之类的。像这样的情况我们其实遇到的比较多,并且迁移到 TiDB 之后也经历了很多,因为我们用的 TiDB 版本比较早,2.x 的版本之前也用了好长一段时间。举个例子,线上有时候跑着跑着的一个索引可能突然失效了,这时候就会出现很多的慢 SQL,这是一个踩过几次的问题。第二个可能有时候碰到潜在的问题了,针对某一条数据一执行就会非常慢,CPU 一下飙到百分之一千九的样子,这就是早期碰到的。

包括 MongoDB 我们也踩过坑,MongoDB 服务端连接数设置我们也遇到过像 CPU 非常高的情况,做教育的话稳定性特别重要,因为服务的用户都是付费用户,也有晚高峰的时候,我们都做了一些稳定性建设相关的工作,像在 SDK 层面我们分了 SDK XSQL 和 XMongoDB。SDK 层面首先会做一些统计相关的静默的打点统计,第二会做一些熔断降级相关的事情。熔断我们做的会比较早一点,因为我们可能根据在某个时间内报错达到多少或者说报错的比例超过多少,我们就会对一个库或者表级把数据库操作熔断一下,特别是表级别的熔断。  

我们现在也在做一款中间件,这款中间件有限流、降低、熔断的能力,并且能够精准到像 SQL 范式的级别,就是 SQL 指纹,并且还有像连接池或者是类似一个 SQL 的能力。

黄东旭:我用一句话来说,你们其实在上分布式数据库之前在上面做了一层 proxy,相当于做一些兜底或者熔断工作,想把这个扛一下是吧?

徐成选:是这样的,先是在 SDK 层面做的,然后现在慢慢传到一个 proxy 层,后面可能下沉到 mesh 层来做这个事情。

黄东旭:挺好的,那老白这边?

白瑜庆:我们这边上到分布式数据库还是经过一些阶段的,我们最早遇到的问题其实是单库容量的上限,有一些数据表容量已经超过了单表的上限,比如说几十亿。最开始的时候还没有合适的分布式数据库产品,我们最常用的是 HBase,其实这个很重,比如说失效或者 region server 的故障,导致可用性较差。另外一点,HBase 对于使用的学来说是有很大的侵入。于是我们又回到传统的方式,比如做分库分表,其实当时做的是水平拆分,这个方案对于使用方来说是基本透明的,但是对于数据库维护的同学来说是一个比较大的负担,就相当于他的一个库被拆成了非常多的库,整个实例管理会非常重。恰巧这个时候我们遇到了 TiDB,我们希望用 TiDB 去解决容量问题。当然第一版上市后还出了一点点小问题,因为我们有很多在线服务的,MySQL 是一主多从的架构,当时我们上了TiDB 以后,可能是给的 DB 的 server 不够多,会产生一些热点的问题。

黄东旭:好,这个问题新的版本已经在尽量解决了。

白瑜庆:对,那个是比较早期的版本,新版本有很多的 feature 对这个问题有很大的优化。另外我们上分布式数据库还有个很重要的原因,就是它对于使用方来说基本是平滑的,但不能保证他和 MySQL 是 100% 兼容,这一块对于上了业务的同学可能要做一些评估。

并且上分布式数据库可能有一些预设的条件,业务的同学需要预知,比如说原来 MySQL 读流量可能特别大,在上到分布式数据库后,他的读虽然可以在分布式数据库均摊,但因为本质上单机事务的速度会远高于分布式事务,这对于业务同学来说可能需要预知,并做一点点改造。我们也尝试了很多方式,比如做一些架构上的调整、代码上的调整,或者在前端做一些缓存层,但是本质来说需要接入的同学去感知。

分布式数据库对于 DBA 来说,维护起来很优雅,虽然他增加了学习成本,但是这个学习成本在当前来说其实是 ok 的,因为这是一种比较先进的理念,存储和计算可以分离,下层的存储可以自动的 scale。比如说我们放在 Kubernetes 上,用 Operater 去管理我们的节点,单节点的故障其实对于整个系统或者对于我们来说是可以自愈的,或者说对业务来说是无感的,这点非常棒!

黄东旭:大家知道 TiDB 有很多金融客户,其实一些银行,特别是在 TiDB 早期刚刚推到金融行业里面的时候,大家遇到的最大阻碍就是分布式数据库虽然号称支持 SQL,也支持 ACID 事务,但是在事务的支持上几乎都是走两阶段提交或者说一些新的透明的分布式事务的算法。其实单个事务的延迟会比单机的系统,例如 Oracle 或者 DB2 这样的系统大很多,所以就像刚才老白这边说的,在互联网行业还好,互联网行业大家一听可能就理解了,无非就是把我的并发搞大一点,原来可能是单线程,现在变成了多线程或者我的连接池、并发数调大一些就可以了。但是在传统行业,比如说像一些金融、银行转帐等,你说不就是转帐嘛,多简单,你们把串行改成并行不就行了吗,并发大,没事的!但实际在银行客户那边一看,才发现人家所谓的一个交易或者一个事务一展开,一百多条 SQL 的语句,这个放在像 IBM 小型机或者 Oracle Exadata 这样的超级高端的硬件,加上 DB2 或者 Oracle 数据库,真的就是在一毫秒、两毫秒就完成这个工作了,当时我们都傻眼了。 

我觉得至少对我来说,因为一开始 TiDB,包括用户也好,都是在互联网行业内,所以我们对于复杂业务的理解是比较浅的,所以 TiDB 4.0、TiDB 5.0 特别大的优化方向或者说一个进步的方向就是在金融级别的核心场景中,因为有一些场景其实不一定是金融才有,其他地方可能也有,我们希望能真正达到非常低的延迟或者说能够用起来跟单机数据库的感觉差不多。


意犹未尽的同学可以点击【阅读原文】查看完整视频哦~除了直播间讨论热烈的话题,我们也准备了最后一波精选文章诚意满满的放送给大家!


未来的数据库会是什么样的?

作者:黄东旭

文章摘要:以分布式数据库为中心的架构是什么样子的呢?很好理解,整个架构的中心是一个场景覆盖度足够广,且具有无限的水平伸缩能力的存储系统。大部分数据的流动被限制在这个数据库内部,这样应用层就可以几乎做到无状态,因为这个中心的数据库负责了绝大部分状态,每个应用可以通过自己的缓存来进行加速。

扫描上方二维码查看完整文章

深入浅出 Raft - 基本概念

作者:唐刘

文章摘要:兔小姐准备在泥坑小镇成立一家银行(就叫泥坑银行吧)。对于银行储蓄系统的设计,兔小姐找来了猪爸爸。

兔小姐:『猪爸爸,我们要保证,无论怎样用户的金钱不能有错误。假如客户存了 100 块钱,那么他的账户就会多出来 100 块钱,不会是 101,也不会是 99。』

猪爸爸:『好的,兔小姐,我觉得我们可以这样。如果一个客户来存钱,那么,首先我们可以将交易依次顺序记录下来,然后兔先生再把客户实际的钱放到金库对应的保险柜里面。当兔先生把钱放好之后,我们就可以告诉客户这笔交易完成了』

兔小姐:『好主意,猪爸爸,不过为什么要先将交易记录下来呢?直接放到金库不就可以了吗?』

扫描上方二维码查看完整文章

[译] 分布式系统中的一致性模型

作者:陈Qiu凯

文章摘要:网络分区是大概率会发生的。交换机,网络接口控制器(NIC,Network Interface Controller),主机硬件,操作系统,硬盘,虚拟机,语言运行时,更不用说程序语义本身,所有的这些将导致我们的消息可能会延迟,被丢弃,重复或被重新排序。在一个充满不确定的世界里,我们希望程序保持一种直观的正确性。

是的,我们想要直观的正确性。那就做正确的事吧!但什么是正确的事?我们如何描述它?在这篇文章里,我们会见到一些“强”一致性模型,并且看到他们是如何互相适应的。

扫描上方二维码查看完整文章

时间戳(Timestamp)与分布式系统的排序(Ordering)

作者:xd wei
文章摘要:Google 在 2012 年的 Spanner 数据库中提出了一个 TrueTime API,来避免使用一个全局时间戳服务器,同时提供的时间能够保证外部一致性。
简单来说,TrueTime 提供了一个 delta;并且保证不同机器之间的时钟最多不会超过 delta。这样,当一个事件发生时 ,最多只需要等待 delta 的事件,便可保证他的时间戳一定大于先于他之前发生的事件的时间戳。Spanner 用 TrueTime 在 geo-eplicated 的情况下支持 strict serializability 的数据库事务。
Delta 的大小对使用 TrueTime 应用的性能非常相关:通常使用 TrueTime 的应用需要等待 delta 来确保时间戳的准确。TrueTime 提供的 delta 通常是毫秒级。Delta 的大小取决于许多因素,如网络延迟。最近有研究在单数据中心的情况下,利用快速的网络(如 RDMA)可以将 delta 降低到微秒级。

扫描上方二维码查看完整文章


关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接