mirror of
https://github.com/cheetahlou/CategoryResourceRepost.git
synced 2025-11-17 22:53:42 +08:00
del
This commit is contained in:
194
极客时间专栏/geek/分布式数据库30讲/实践篇/24 | 全球化部署:如何打造近在咫尺且永不宕机的数据库?.md
Normal file
194
极客时间专栏/geek/分布式数据库30讲/实践篇/24 | 全球化部署:如何打造近在咫尺且永不宕机的数据库?.md
Normal file
@@ -0,0 +1,194 @@
|
||||
<audio id="audio" title="24 | 全球化部署:如何打造近在咫尺且永不宕机的数据库?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/01/f4/017fd5ff930856ee08bdffdc33b011f4.mp3"></audio>
|
||||
|
||||
你好,我是王磊,你也可以叫我Ivan。
|
||||
|
||||
这一讲我们要聊的是“全球化部署”,其实这个词在我们的课程中已经出现很多次了。我猜说不定你心里一直有个问号:“全球化啊,这么高大上的东西和我有关系吗?”耐心看完这一讲,我相信你会有新的理解。
|
||||
|
||||
我们不妨给全球化部署起一个更接地气的小名,“异地多活”。怎么样,感觉亲切多了吧?全球化部署本质就是全球范围下的异地多活。总体上看,异地多活的直接目标是要预防区域级的灾难事件,比如城市级的断电,或是地震、洪水等自然灾害。也就是说,在这些灾难发生时,要让系统还能保障关键业务的持续开展。
|
||||
|
||||
因此,这里的“异地”通常是指除同城机房外,在距离较远的城市配备的独立机房,在物理距离上跳出区域级灾难的覆盖范围。这个区域有多大呢?从银行业的实践来看,两地机房的布局通常会部署在南北或者东西两个大区,比如深圳到上海,或者北京到武汉,又或者北京到西安,距离一般会超过1000公里。
|
||||
|
||||
对于银行业的异地机房建设,监管机构是有具体要求的,也就是大中型银行的“两地三中心”布局。而对于互联网行业来说,虽然没有政策性要求,但业务本身的高可用需求,也推动了头部公司进行相应的布局。
|
||||
|
||||
说完了“异地”这个概念,我们再来看异地多活是怎么回事。首先,异地多活是高可用架构的一种实现方式,它是以整个应用系统为单位,一般来说会分为应用和数据库两部分。
|
||||
|
||||
应用部分通常是无状态的,这个无状态就是说应用处理每个请求时是不需要从本地加载上下文数据的。这样启动多个应用服务器就没有什么额外的成本,应用之间也没有上下文依赖,所以就很容易做到多活。
|
||||
|
||||
数据库节点要最终持久化数据,所有的服务都要基于已有的数据,并且这些数据内容还在不断地变化。任何新的服务节点在接入这个体系后,相互之间还会存在影响,所以数据库服务有逻辑很重的上下文。因此数据库的多活的难度就大多了,也就产生了不同版本的解读。
|
||||
|
||||
## 单体数据库
|
||||
|
||||
数据库层面的异地多活,本质上是要实现数据库的高可用和低延迟,也就是我们在标题中说“永不宕机”和“近在咫尺”。即便是单体数据库时代的技术方案,也是朝着这个方向努力的,我们不妨先来看看。
|
||||
|
||||
### 异地容灾
|
||||
|
||||
异地容灾是异地多活的低配版,它往往是这样的架构。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/05/1d/0599a4bbf048c8f783f7749fa3e9951d.jpg" alt="">
|
||||
|
||||
整个方案涉及同城和异地两个机房,都部署了同样的应用服务器和数据库,其中应用服务器都处于运行状态可以处理请求,也就是应用多活。只有同城机房的数据库处于运行状态,异地机房数据库并不启动,不过会通过底层存储设备向异地机房同步数据。然后,所有应用都链接到同城机房的数据库。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/29/80/29ae8bbffb951520a426bc353aabc380.jpg" alt="">
|
||||
|
||||
这样当同城机房整体不可用时,异地机房的数据库会被拉起并加载数据,同时异地机房的应用切换到异地机房的数据库。
|
||||
|
||||
显然,这个多活只是应用服务器的多活,两地的数据库并不同时提供服务。这种模式下,异地应用虽然靠近用户,但仍然要访问远端的数据库,对延迟的改善并不大。在系统正常运行情况下,异地数据库并没有实际产出,造成了资源的浪费。
|
||||
|
||||
按照正常的商业逻辑,当然不能容忍这种资源浪费,所以有了异地读写分离模式。
|
||||
|
||||
### 异地读写分离
|
||||
|
||||
在异地读写分离模式下,异地数据库和主机房数据库同时对外提供服务,但服务类型限制为只读服务,但只读服务的数据一致性是不保证的。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/ea/d3/ea56a0298c6ac1yy44fdcc90c832e9d3.jpg" alt="">
|
||||
|
||||
当主机房完全不可用时,异地机房的运作方式和异地容灾模式大体是一样的。
|
||||
|
||||
读写分离模式下,异地数据库也投入了使用,不再是闲置的资源。但是很多场景下,只读服务在业务服务中的占比还是比较低的,再加上不能保证数据的强一致性,适用范围又被进一步缩小。所以,对于部分业务场景,异地数据库节点可能还是运行在低负载水平下。
|
||||
|
||||
于是,我们又有了进一步的双向同步模式。
|
||||
|
||||
### 双向同步
|
||||
|
||||
双向同步模式下,同城和异地的数据库同时提供服务,并且是读写服务均开放。但有一个重要的约束,就是两地读写的对象必须是不同的数据,区分方式可以是不同的表或者表内的不同记录,这个约束是为了保证两地数据操作不会冲突。因为不需要处理跨区域的事务冲突,所以两地数据库之间就可以采用异步同步的方式。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/76/87/76bee484b559a3a858b1c26c31835887.jpg" alt="">
|
||||
|
||||
这个模式下,两地处理的数据是泾渭分明的,所以实质上是两个独立的应用实例,或者可以说是两个独立的单元,也就是我们[第1讲](https://time.geekbang.org/column/article/271373)说的单元化架构。而两个单元之间又相互备份数据,有了这些数据可以容灾,也可以开放只读服务。当然,这个只读服务同样是不保证数据一致性的。
|
||||
|
||||
可以说,双向同步是单元化架构和异地读写分离的混合,异地机房的资源被充分使用了。但双向同步没有解决一个根本问题,就是两地仍然不能处理同样的数据,对于一个完整的系统来说,这还是有很大局限性的。
|
||||
|
||||
## 分布式数据库
|
||||
|
||||
分布式数据库的数据组织单位是更细粒度的分片,又有了Raft协议的加持,所以就有了更加灵活的模式。
|
||||
|
||||
### 机房级容灾(两地三中心五副本)
|
||||
|
||||
比较典型的分布式数据库部署模式是两地三中心五副本。这种模式下,每个分片都有5个副本,在同城的双机房各部署两个副本,异地机房部署一个副本。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/f1/14/f1cb7a12a5294ae5daf671c64acc1714.jpg" alt="">
|
||||
|
||||
这个模式有三个特点:
|
||||
|
||||
1. 异地备份
|
||||
|
||||
保留了“异地容灾”模式下的数据同步功能,但因为同样要保证低延迟,所以也做不到RPO(Recovery Point Objective, 恢复点目标)为零。
|
||||
|
||||
1. 容灾能力
|
||||
|
||||
如果同城机房有一个不可用或者是同城机房间的网络出现故障,异地机房节点的投票就会发挥作用,依然可以和同城可用的那个机房共同达成多数投票,那么数据库的服务就仍然可以正常运行,当然这时提交过程必须要异地通讯,所以延迟会受到一定程度影响。
|
||||
|
||||
1. 同城访问低延迟
|
||||
|
||||
由于Raft或Paxos都是多数派协议,那么任何写操作时,同城的四个副本就能够超过半数完成提交,这样就不会因为与异地机房通讯时间长而推高数据库的操作延迟。
|
||||
|
||||
两地三中心虽然可以容灾,但对于异地机房来说RPO不为零,在更加苛刻的场景下,仍然受到挑战。这也就催生了三地五副本模式,来实现RPO为零的城市级容灾。
|
||||
|
||||
#### 城市级容灾(三地五副本)
|
||||
|
||||
三地五副本模式是两地三中心模式的升级版。两个同城机房变成两个相临城市的机房,这样总共是在三个城市部署。
|
||||
|
||||
这种模式在容灾能力和延迟之间做了权衡,牺牲一点延迟,换来城市级别的容灾。比如,在北京和天津建立两座机房,两个城市距离不算太远,延迟在10毫秒以内,还是可以接受的。不过,距离较近的城市对区域性灾难的抵御能力不强,还不是真正意义上的异地。
|
||||
|
||||
顺着这思路,还有更大规模的三地五中心七副本。但无论如何,只要不放弃低延迟,真正异地机房就无法做到RPO为零。
|
||||
|
||||
无论是两地三中心五副本还是三地五副本,它们更像是单体数据库异地容灾的加强版。因为,其中的异地机房始终是一个替补的角色,而那些异地的应用服务器也依然花费很多时间访问远端的数据库。
|
||||
|
||||
这个并不满足我们“近在咫尺”的愿望。
|
||||
|
||||
#### 架构问题
|
||||
|
||||
为什么会这样呢?因为有些分布式数据库会有一个限制条件,就是所有的Leader节点必须固定在同城主机房,而这就导致了资源使用率大幅下降。TiDB和OceanBase都是这种情况。
|
||||
|
||||
Raft协议下,所有读写都是发送到Leader节点,Follower节点是没有太大负载的。Raft协议的复制单位是分片级的,所以理论上一个节点可以既是一些分片的Leader,又是另一些分片的Follower。也就是说,通过Leader和Follower混合部署可以充分利用硬件资源。
|
||||
|
||||
但是如果主副本只能存在同一个机房,那就意味着另外三个机房的节点,也就是有整个集群五分之三的资源,在绝大多数时候都处于低负载状态。这显然是不经济的。
|
||||
|
||||
那你肯定会问,这个限制条件是怎么来的,一定要有吗?
|
||||
|
||||
其实,这个限制条件就是我们在[第5讲](https://time.geekbang.org/column/article/274908)说过的全局时钟导致的。具体来说,就是单时间源的授时服务器不能距离Leader太远,否则会增加通讯延迟,性能就受到很大影响,极端情况下还会出现异常。
|
||||
|
||||
增加延迟比较好理解,因为距离远了嘛。那异常是怎么回事呢?下面我们就来解释下。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/10/e3/10b922b86751c62ab8dbebef81d208e3.jpg" alt="">
|
||||
|
||||
我们把这种异常称为“远端写入时间戳异常”,它的发生过程是这样的:
|
||||
|
||||
1. C2节点与机房A的全局时钟服务器通讯,获取时间。此时绝对时间(At)是500,而全局时钟(Ct)也是500。
|
||||
1. A3节点也与全局时钟通讯,获取时间。A3的请求晚于C2,拿到的全局时钟是510,此时的绝对时钟也是510。
|
||||
1. A3节点要向R2写入数据,这个动作肯定是晚于取全局时钟的操作,所以绝对时间来到了512,但是A3使用的时间戳仍然是510。写入成功。
|
||||
1. 轮到C2节点向R2写入数据,由于C2在异地,通讯的时间更长,所以虽然C2先开始写入动作的流程,但却落后于A3将写入命令发送给R2,此时绝对时间来到了550,而C2使用的时间戳是500。A3与C2都要向R2写入数据,并且是相同的Key,数据要相互覆盖的。这时候问题来了,R2中已经有了一条记录时间戳是510,已经提交成功,稍后又收到了一条时间戳是500的记录,这是R2只能拒绝500的这条记录。因为后写入的数据使用更早的时间戳,整个时间线就会乱掉,否则读取的进程会先看到510的数据,再看到500的数据,数据一致性显然有问题。
|
||||
|
||||
这个例子说明,如果远端计算节点距离时钟节点过远,那么当并发较大且事务冲突较多时,异地机房就会出现频繁的写入失败。这种业务场景并不罕见,当我们网购付款时就会出现多个事务在短时间内竞争修改商户的账户余额的情况。
|
||||
|
||||
### 全球化部署
|
||||
|
||||
全球化部署的前提是多时间源、多点授时,这样不同分片的主副本就可以分散在多个机房。那么数据库服务可以尽量靠近用户,而应用系统也可以访问本地的分片主副本,整体效果达到等同于单元化部署的效果。
|
||||
|
||||
当出现跨多地分片参与同一个分布式事务的情况,全球化部署模式也可以很好地支持。由于参与分片跨越更大的物理范围,所以延迟就受到影响,这一点是无法避免的。还有刚刚提到的“远端写入时间戳异常”,因为每个机房都可以就近获得时钟,那么发生异常的概率也会大幅下降。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/5c/da/5cb2d256cce6a0b7b886e919c7dc45da.jpg" alt="">
|
||||
|
||||
全球化部署模式下,异地机房所有的节点都是处于运行状态的,异地机房不再是替补角色,和同城机房一样提供对等的支持能力,所有机房同等重要。
|
||||
|
||||
在任何机房发生灾难时,主副本会漂移到其他机房,整个系统处于较为稳定的高可用状态。而应用系统通过访问本地机房的数据库分片主副本就可以完成多数操作,这些发生在距离用户最近的机房,所以延迟可以控制到很低。这样就做到了我们说的永不宕机和近在咫尺。
|
||||
|
||||
### 同城双机房
|
||||
|
||||
接下来,我们再谈一些例外情况,比如下面这种架构。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/84/b0/842edd950b1df093fdafca8078ff1bb0.jpg" alt="">
|
||||
|
||||
有了前面的铺垫,再看这种方式你可能觉得有点奇怪。主机房保留了过半的副本,这意味着即使是同城备用机房,也不能实现RPO为零。那么主备机房之间就退化成了异步复制,这不更像一个单体数据库的主备模式吗?这样部署的意图是什么呢?
|
||||
|
||||
有的运维同学给我解释了这个部署架构,这样可以保证其他机房不存在时,主机房能够单独工作。后来我发现持这种观点的并不是极少数。还有同学会提出来,当主机房只有少数副本时,是不是可以继续工作呢?如果对Raft协议有所了解,你会觉得这个要求不可思议,少数副本还继续工作就意味着可能出现脑裂,这怎么可以呢?这里的脑裂是指发生网络分区时,两个少数节点群仍可以保持内部的通讯,然后各自选出的Leader,分别对外提供服务。
|
||||
|
||||
但是换个角度去想,你就会发现这些同学也有他的理由。既然我的数据还是完整的,为什么我不能提供服务呢?虽然,我损失掉了备份机房,但这不影响主机房的工作呀。
|
||||
|
||||
如果这个理由也成立,那么哪种选择是更优呢?别急,做判断前,我想和你分享一下对恶意攻击的理解。
|
||||
|
||||
#### 恶意攻击
|
||||
|
||||
通常来说,架构设计的高可用都是面对正常情况的,机器、网络的不可用都是源于设备自身故障不是外力损坏。但是,有没有可能发生恶意攻击呢?
|
||||
|
||||
回到两地三中心的模式,如果三个机房之间的光纤网络被挖断,整个数据库就处于不可用状态,因为这时已经不可能有过半数的节点参与投票了。自然状态下,这个事情发生的概率太低了,三中心之间同时有三条路线,甚至有些机构为了提高安全性,会设置并行的多条线路。但是,如果真的是恶意攻击,多搞几台挖掘机就能让银行的系统瘫痪掉,这比黑客攻击容易多了,而且成本也很低的。
|
||||
|
||||
同城双机房的设计,其实一种比较保守的方案,它力图规避了主机房之外因素的干扰因素。为了系统平稳运行,甚至可以放弃RPO为零这个重要的目标。虽然我并不认为这是最优的方案,但也确实可以引发一些思考。
|
||||
|
||||
RPO为零是一种保障手段,而持续服务才是目标。那么,也就不应该为了追求RPO为零这个手段,而让原本还能正常运行的服务终止掉。这是为了手段而放弃了目标,不就成了舍本求末吗?在必要的时候,还是要保证主要目标舍弃次要的东西。
|
||||
|
||||
所以,Raft协议还需要一个降级机制,也就是说不一定要过半投票,仍然维持服务。类似这样的设计在有些分布式数据库中已经可以看到了。因此,我觉得三地五副本模式加上Raft降级,应该算是目前比较完善的方案了。
|
||||
|
||||
### Follower Read
|
||||
|
||||
全球化部署还有一个远端读的性能问题。如果分片的主副本在主机房,而异地机房要读取这些数据,如何高效实现呢?读写分离当然可以,但这损失了数据一致性,在有的场景下是不能接受的。CockroachDB目前支持的Follower Read虽然提升了性能,但也是不保证数据一致性的;而TiDB的Follower目前还不支持跨机房部署。
|
||||
|
||||
但是,这并不妨碍我们探讨未来的可能性,在[第22讲](https://time.geekbang.org/column/article/291009)我提出了一个思路就是利用Raft协议无“日志空洞”的特点,等到日志时间戳超过查询时间戳,数据就足够新了。但这仅限于写入操作密集的分片,如果分片上的数据比较冷,根本等不到时间戳增长,又该怎么办呢?
|
||||
|
||||
其实还有可优化的地方,那就是利用Raft协议的合并发送机制。事实上,在真正实现Raft协议时,因为每个Raft组单独通讯的成本太高,通常会将同一节点的多个Raft协议打包后对外发送,这样可以考虑增加其他分片的最后更新时间戳,再通过协议包的发送时间戳来判断包内分片的最新状态。由于节点级别的Raft协议是源源不断发送的,这样只要冷分片和热分片在同一个包内,就可以及时得到它的状态。
|
||||
|
||||
### 全服务的意义
|
||||
|
||||
异地多活的终极目标应该是让异地机房提供全服务,也就是读写服务。这样的意义在于让备用机房的设备处于全面运行的状态,这不仅提升了资源利用率,也时刻确保了各种设备处于可运行的状态,它们的健康状态是实时可知的。
|
||||
|
||||
而在异地容灾模式下,备机房必须通过定期演练来确认是可用的,这耗费了人力物力,但并没有转化为真正的生产力,而且仍然存在风险。演练的业务场景足够多吗?出现问题时,这个定期演练的系统真的能够顶上去吗?我想很多人心中或许也是一个问号。显然,一个时刻运行着的系统比三个月才演练一次的系统更让人放心。
|
||||
|
||||
所以,我认为一个具有全球化部署能力,或者说是能真正做到异地多活的分布式数据库,是有非常重要的意义的。
|
||||
|
||||
## 小结
|
||||
|
||||
那么,今天的课程就到这里了,让我们梳理一下这一讲的要点。
|
||||
|
||||
1. 全球化部署就是全球范围下的异地多活。异地多活通常是指系统级别,包括了应用和数据库,难点在于数据库的多活。
|
||||
1. 单体数据库的异地多活主要有三个版本,异地容灾、异地读写分离和双向同步。但是都无法让应用在同城和异地同时操作相同的数据,没有解决数据库大范围部署的问题。
|
||||
1. 分布式数据库常采用的部署方式是两地三中心五副本,可以实现机房级别的容灾和异地备份数据但RPO不为零。在此基础上,还可以升级到三地三中心五副本,提供城市级别容灾,在邻近城市实现RPO为零。使用单点授时的分布式数据库,必须将所有分片的主副本集中在主机房,这一方面是由于访问全局时钟的通讯成本高,另外是为了避免异常现象。
|
||||
1. 如果从恶意攻击的角度看,基于Raft协议的多中心部署反而会带来数据库的脆弱性,因为机房间的通讯链路将成为致命的弱点。所以,应在一定条件下允许对Raft协议做降级处理,保证少数副本也可以对外提供服务。
|
||||
1. 缩短从节点读操作延迟对于异地多活也有重要的意义,目前尚没有完善的解决方案,我们探讨了一些优化的可能性。真正的异地多活必须是异地机房提供全服务,这样才能在本质上提升系统可用性,比定期演练更加可靠。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/74/ac/74cda65149a4cb2890918473a9d18bac.jpg" alt="">
|
||||
|
||||
## 思考题
|
||||
|
||||
课程的最后,我们来看看今天的思考题。今天的课程中,我们提到了Raft协议降级处理,它允许数据库在仅保留少数副本的情况下,仍然可以继续对外提供服务。这和标准Raft显然是不同的,你觉得应该如何设计这种降级机制呢?
|
||||
|
||||
欢迎你在评论区留言和我一起讨论,我会在答疑篇和你继续讨论这个问题。如果你身边的朋友也对全球化部署或者异地多活这个话题感兴趣,你也可以把今天这一讲分享给他,我们一起讨论。
|
||||
155
极客时间专栏/geek/分布式数据库30讲/实践篇/25 | 容灾与备份:如何设计逃生通道保证业务连续性?.md
Normal file
155
极客时间专栏/geek/分布式数据库30讲/实践篇/25 | 容灾与备份:如何设计逃生通道保证业务连续性?.md
Normal file
@@ -0,0 +1,155 @@
|
||||
<audio id="audio" title="25 | 容灾与备份:如何设计逃生通道保证业务连续性?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/b8/a1/b8f1a34022c702d01175b7e7dabyyfa1.mp3"></audio>
|
||||
|
||||
你好,我是王磊,你也可以叫我Ivan。
|
||||
|
||||
我们今天的关键词是“逃生通道”。在生活中,我们去任何一个公共场所,比如火车站、商场、写字楼,都能看安全出口或者紧急疏散通道的提示,这就是逃生通道。逃生通道的作用就是人们能够快速脱离危险的地方。而在系统领域,逃生通道是指让业务能够脱离已经不可用的原有系统,在一个安全的备用系统中继续运转。
|
||||
|
||||
可以说逃生通道就是系统高可用的一种特殊形式。它的特别之处在于,备用系统要提供差异化的、更高级别的可靠性。为什么备用系统能够提供更高级别的可靠性呢?这是主要由于它采用了异构方案。
|
||||
|
||||
对于分布式数据库来说,逃生通道存在的意义应该更容易理解。作为一种新兴的技术,分布式数据库还没有足够多的实践案例来证明自身的稳定性,即使是它本身的高可用架构也不足以打消用户的顾虑。这时候就需要设计一种异构的高可用方案,采用更加稳定、可靠的数据库作为备用系统。我们通常把这个备用数据库称为“逃生库”。
|
||||
|
||||
在分布式数据库的实践没有成为绝对主流前,逃生通道都是一个不容忽视的用户需求。它可以降低实施风险,打消用户的顾虑,减少新技术应用中遇到的各种阻力。
|
||||
|
||||
## CDC
|
||||
|
||||
作为一个数据库的高可用方案,首先要解决的是数据恢复的完整性,也就是我们提过多次的RPO。这就需要及时将数据复制到逃生库。通常异构数据库间的数据复制有三种可选方式:
|
||||
|
||||
1. 数据文件
|
||||
1. ETL(Extract-Transform-Load)
|
||||
1. CDC(Change Data Capture)
|
||||
|
||||
数据文件是指,在数据库之间通过文件导入导出的方式同步数据。这是一种针对全量数据的批量操作,如果要实现增量加载,则需要在数据库表的结构上做特殊设计。显然,数据文件的方式速度比较慢,而且对表结构设计有侵入性,所以不是最优选择。
|
||||
|
||||
ETL是指包含了抽取(Extract)、转换(Transform)和加载(Load)三个阶段的数据加工过程,可以直连两端的数据库,也可以配合数据文件一起用,同样必须依赖表结构的特殊设计才能实现增量抽取,而且在两个数据库之间的耦合更加紧密。
|
||||
|
||||
最后,CDC其实是一个更合适的选择。CDC的功能可以直接按照字面意思理解,就是用来捕获变更数据的组件,它的工作原理是通过读取上游的 redo log 来生成 SQL 语句发送给下游。它能够捕捉所有DML的变化,比如delete和update,而且可以配合redo log的设置记录前值和后值。
|
||||
|
||||
相比之下,CDC的业务侵入性非常小,不改动表结构的情况下,下游系统就可以准确同步数据的增量变化。另外,CDC的时效性较好,对源端数据库的资源占用也不大,通常在5%-10%之间。
|
||||
|
||||
CDC是常规的配套工具,技术也比较成熟,在[第18讲](https://time.geekbang.org/column/article/287246)的Kappa架构中很多流式数据的源头就是CDC。CDC工具的提供者通常是源端的数据库厂商,传统数据库中知名度较高的有Oracle的OGG(Gold Gate)和DB2的Inforsphere CDC。
|
||||
|
||||
确定了数据同步工具后,我们再来看看如何选择逃生库以及如何搭建整体逃生方案。
|
||||
|
||||
## 逃生方案
|
||||
|
||||
对于分布式数据库来说,要选择一个更加成熟、稳定的逃生库,答案显然就是单体数据库了。那具体要选择哪种产品呢?从合理性角度来说,肯定就要选用户最熟悉、最信任、运维能力最强的单体数据库,也就是能够“兜底”的数据库。
|
||||
|
||||
按照这个思路,这个异构高可用方案就由分布式数据库和单体数据库共同组成,分布式数据库向单体数据库异步复制数据。使用异步复制的原因是不让单体数据库的性能拖后腿。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/03/25/0334802f0a5b359442c0c872c5a36c25.jpg" alt="">
|
||||
|
||||
这样,当分布式数据库出现问题时,应用就可以切换到原来的单体数据库,继续提供服务。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/f7/06/f7a7b4yy17cd099c717de6ff2300b206.jpg" alt="">
|
||||
|
||||
这个方案看似简单,但其实还有一些具体问题要探讨。
|
||||
|
||||
### 1. 日志格式适配
|
||||
|
||||
首先是单体数据库的日志适配问题。
|
||||
|
||||
逃生方案的关键设计就是数据异步复制,而载体就是日志文件。既然是异构数据库,那日志文件就有差别吧,要怎么处理呢?
|
||||
|
||||
还记得[第4讲](https://time.geekbang.org/column/article/274200)我介绍的两种分布式数据库风格吗?其中PGXC风格分布式数据库,它的数据节点是直接复用了MySQL和PostgreSQL单体数据库。这就意味着,如果本来你熟悉的单体数据库是MySQL,现在又恰好采用了MySQL为内核的分布式数据库,比如GoldenDB、TDSQL,那么这个方案处理起来就容易些,因为两者都是基于Binlog完成数据复制的。
|
||||
|
||||
而如果你选择了NewSQL分布式数据库也没关系。虽然NewSQL没有复用单体数据库,但为了与技术生态更好的融合,它们通常都会兼容某类单体数据库,大多数是在MySQL和PostgreSQL中选择一个,比如TiDB兼容MySQL,而CockroachDB兼容PostgreSQL。TiDB还扩展了日志功能,通过Binlog组件直接输出SQL,可以加载到下游的MySQL。
|
||||
|
||||
如果很不幸,你选择的分布式数据库并没有兼容原有的单体数据库规范,也没有提供开放性接口,那么就需要做额外的转换工作。
|
||||
|
||||
### 2. 处理性能适配
|
||||
|
||||
第二个问题是性能匹配问题。用单体数据库来做逃生库,这里其实有一个悖论。那就是,我们选择分布式的多数原因就是单体不能满足性能需求,那么这个高可用方案要再切换回单体,那单体能够扛得住这个性能压力呢?
|
||||
|
||||
比如,我们用MySQL+x86来做TiDB+x86的逃生库,这个方案就显得有点奇怪。事实上,在分布式数据库出现前,性能拓展方式是垂直扩展,导致相当一部分对性能和稳定性要求更高的数据库已经切换到Oracle、DB2等商用数据库加小型机的模式上。所以,对于金融行业来说,往往需要用Oracle或DB2+小型机来做逃生库。
|
||||
|
||||
当然,性能问题还有缓释手段,就是增加一个分布式消息队列来缓存数据,降低逃生库的性能压力。这样就形成下面的架构。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/90/b8/90925611cf026d5e5a1e07cb2bbae4b8.jpg" alt="">
|
||||
|
||||
另外,有了分布式消息队列的缓冲,我们就可以更加方便地完成异构数据的格式转换。当然,日志格式的处理是没有统一解决方案的,如果你没有能力做二次开发,就只能寄希望于产品厂商提供相应的工具。
|
||||
|
||||
这样,完成了日志格式的适配,增加了消息队列做性能适配,逃生方案是不是就搞定了呢?
|
||||
|
||||
别急,还差了那么一点点。
|
||||
|
||||
### 3. 事务一致性
|
||||
|
||||
我们知道数据库事务中操作顺序是非常重要的,而日志中记录顺序必须与事务实际操作顺序严格一致,这样才能确保通过重放日志恢复出相同的数据库。可以说,数据库的备份恢复完全建立在日志的有序性基础上。逃生库也是一样的,要想准确的体现数据,必须得到顺序严格一致的日志,只不过这个日志不再是文件的形式,而是实时动态推送的变更消息流(Change Feed)。
|
||||
|
||||
如果一个单体数据库向外复制数据,这是很容易实现的,因为只要将WAL的内容对外发布就能形成了顺序严格一致的变更消息流。但对于分布式数据库来说,就是一个设计上的挑战了。
|
||||
|
||||
为什么这么说呢?
|
||||
|
||||
如果事务都在分片内完成,那么每个分片的处理逻辑和单体数据库就是完全一样的,将各自的日志信息发送给Kafka即可。
|
||||
|
||||
对于NewSQL来说,因为每个分片就是一个独立的Raft Group,有对应的WAL日志,所以要按分片向Kafka发送增量变化。比如,CockroachDB就是直接将每个分片Leader的Raft日志发送出去,这样处理起来最简单。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/00/a5/007e9afd2e9e542235f951f91b2886a5.jpg" alt="">
|
||||
|
||||
但是,分布式数据库的复杂性就在于跨分片操作,尤其是跨分片事务,也就是分布式事务。一个分布式事务往往涉及很多数据项,这些数据都可能被记录在不同的分片中,理论上可以包含集群内的所有分片。如果每个分片独立发送数据,下游收到数据的顺序就很可能与数据产生的顺序不同,那么逃生库就会看到不同的执行结果。
|
||||
|
||||
我们通过下面的例子来说明。
|
||||
|
||||
小明打算购买番茄银行的自有理财产品。之前他的银行账号有60,000元活期存款,他在了解产品的收益情况后,购买了50,000元理财并支付了50元的手续费。最后,小明账户上有50,000元的理财产品和9,950元的活期存款。
|
||||
|
||||
假设,番茄银行的系统通过下面这段SQL来处理相应的数据变更。
|
||||
|
||||
```
|
||||
begin;
|
||||
//在小明的活期账户上扣减50,000元,剩余10,000元
|
||||
update balance_num = balance_num - 50000 where id = 2234;
|
||||
//在小明的理财产品账户上增加50,000元
|
||||
update fund_num = fund_num + 50000 = where id = 2234;
|
||||
//扣减手续费50元
|
||||
update balance_num = balance_num - 50 where id = 2234;
|
||||
//其他操作
|
||||
……
|
||||
commit;
|
||||
|
||||
```
|
||||
|
||||
小明的理财记录和活期账户记录对应两个分片,这两个分片恰好分布在Node1和Node2这两个不同节点上,两个分片各自独立发送变更消息流。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/e3/fc/e3eac10d560396482f0d71c883960cfc.jpg" alt="">
|
||||
|
||||
在前面的课程中我们已经介绍过,同一个事务中发生变更的数据必定拥有用相同的提交时间戳,所以使用时间戳就可以回溯同一事务内的相关操作。同时,晚提交的事务一定拥有更大的时间戳。
|
||||
|
||||
那么按照这个规则,逃生库在T1时刻发现已经收到了时间戳为ts2的变更消息,而且ts2 > ts1,所以判断ts1事务的操作已经执行完毕。执行ts1下的所有操作,于是我们在逃生库看到小明的活期账户余额是10,000元,理财账户余额是50,000元。
|
||||
|
||||
但是,这个结果显然是不正确的。在保证事务一致性的前提下,其他事务看到的小明活期账户余额只可能是60,000元或9,950,这两个数值一个是在事务开始前,一个是在事务提交后。活期账户余额从60,000变更到10,000对于外部是不可见的,逃生库却暴露了这个数据,没有实现已提交读(Read Committed)隔离级别,也就是说,没有实现基本的事务一致性。
|
||||
|
||||
产生这个问题原因在于,变更消息中的时间戳只是标识了数据产生的时间,这并不代表逃生库能够在同一时间收到所有相同时间戳的变更消息,也就不能用更晚的时间戳来代表前一个事务的变更消息已经接受完毕。那么,要怎么知道同一时间戳的数据已经接受完毕了呢?
|
||||
|
||||
为了解决这个问题,CockroachDB引入了一个特殊时间戳标志“Resolved”,用来表示当前节点上这个时间戳已经关闭。结合上面的例子,它的意思就是一旦Node1发出“ts1:Resolved”消息后,则Node1就不会再发出任何时间戳小于或者等于ts1的变更消息。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a9/a2/a96992ec2eefd9f6ed5739a68effbca2.jpg" alt="">
|
||||
|
||||
在每个节点的变更消息流中增加了Resolved消息后,逃生库就可以在T2时间判断,所有ts1的变更消息已经发送完毕,可以执行整个事务操作了。
|
||||
|
||||
## 小结
|
||||
|
||||
好了,今天的课程就到这里了,让我们梳理一下这一讲的要点。
|
||||
|
||||
<li>
|
||||
分布式数据库作为一种新兴技术,往往需要提供充分可靠的备用方案,用于降低上线初期的运行风险,这种备用方案往往被称为逃生通道。逃生通道的本质是一套基于异构数据库的高可用方案。用来作为备库的数据库称为逃生库,通常会选择用户熟悉的单体数据库。
|
||||
</li>
|
||||
<li>
|
||||
整套方案要解决两个基本问题,分别是日志格式的适配和性能的适配。如果逃生库与分布式数据库本身兼容,则日志格式问题自然消除,这大多限于MySQL和PostgreSQL等开源数据库。如果日志格式不兼容,就要借助厂商工具或者用户定制开发来实现。传统企业由于大量使用商业数据库,这个问题较为突出。性能适配是因为分布式数据库的性能远高于基于x86的单体数据库,需要通过分布式消息队列来适配,缓存日志消息。
|
||||
</li>
|
||||
<li>
|
||||
因为分布式数据库的日志是每个分片独立记录,所以当发生分布式事务时,逃生库会出现数据错误。如果有严格的事务一致性要求,则需要考虑多分片之间变更消息的顺序问题。CockroachDB提供一种特殊的时间戳消息,用于标识节点上的时间戳关闭,这样在复制过程中也能保证多分片事务的一致性。
|
||||
</li>
|
||||
|
||||
逃生通道作为一个异构高可用方案,在我们日常的系统架构中并不常见。这是因为传统数据库的高可用方案已经有足够成熟,我们对它也足够信任。所以,那些CDC工具对单体数据库来说,也是一个有点边缘化的产品,甚至很多有经验的DBA也不熟悉。
|
||||
|
||||
CDC的主要工作场景是为分析性系统推送准实时的数据变更,支持类似Kappa架构的整体方案。但是对于分布式数据库来说,CDC成为了逃生通道的核心组件,远远超过它在单体数据库中的重要性。目前很多分布式数据库已经推出了相关的功能或组件,例如CockroachDB、TiDB、GoldenDB等。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/51/7c/51309df8e77341a49b24dff47d7c427c.jpg" alt="">
|
||||
|
||||
## 思考题
|
||||
|
||||
课程的最后,我们来看下思考题。今天课程中介绍的逃生通道实际上是一个异构的高可用方案。整个方案由三部分构成,除了分布式数据库和单体数据库以外,还增加了Kafka这样的分布式消息队列,通过缓存变更消息的方式适配前两者的处理性能。
|
||||
|
||||
我们还说到,对于单个分片来说WAL本身就是有序的,直接开放就可以提供顺序一致的变更消息。我的问题是,单分片的变更消息流在这个异构高可用方案中真的能够保证顺序一致吗?会不会出现什么问题呢?
|
||||
|
||||
欢迎你在评论区留言和我一起讨论,我会在答疑篇和你继续讨论这个问题。如果你身边的朋友也对逃生通道这个话题感兴趣,你也可以把今天这一讲分享给他,我们一起讨论。
|
||||
130
极客时间专栏/geek/分布式数据库30讲/实践篇/26 | 容器化:分布式数据库要不要上云,你想好了吗?.md
Normal file
130
极客时间专栏/geek/分布式数据库30讲/实践篇/26 | 容器化:分布式数据库要不要上云,你想好了吗?.md
Normal file
@@ -0,0 +1,130 @@
|
||||
<audio id="audio" title="26 | 容器化:分布式数据库要不要上云,你想好了吗?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/1a/a3/1a50ff278ea67c7cd645cf72e39f2da3.mp3"></audio>
|
||||
|
||||
你好,我是王磊,你也可以叫我Ivan。
|
||||
|
||||
今天,我想和你分享的话题是分布式数据库的容器化部署。当数据库遇到容器,我知道这一定是个很有争议的话题。但是,在容器化技术大规模落地的背景下,这也是一个无法回避的话题。
|
||||
|
||||
容器化技术可以将资源虚拟化,从而更灵活快速地调配。容器镜像为应用打包提供了完美的解决方案,也为DevOps理念的落地扫清了技术障碍。可以说,容器已经成为现代软件工程化的基础设施,容器化已经成为一个不可逆的发展趋势。
|
||||
|
||||
但是,具体谈到数据库的容器化,我们又有太多的纠结。常见的反对意见就是数据库因为有状态、高I/O消耗和稳定运行等要求,所以不适合容器化部署。
|
||||
|
||||
那么,随着技术的快速发展,这些理由是不是还成立呢?为了说清楚这个问题,我们先来介绍一些Kubernetes的基本概念。
|
||||
|
||||
## Kubernetes基本概念
|
||||
|
||||
<li>
|
||||
<h3>Container</h3>
|
||||
</li>
|
||||
|
||||
容器化就是将物理机划分为若干容器(Container),应用程序是直接部署在容器上的,并不会感知到物理机的存在。具体来说,这个容器就是Docker,它使用的主要技术包括Cgroup和Namespace。
|
||||
|
||||
Cgroup是控制组群(Control Groups)的缩写,用来限制一个进程组能够使用的资源上限,包括CPU、内存、磁盘、网络带宽等,本质上实现了资源的隔离。Namespace修改了进程视图,使当前容器处于一个独立的进程空间,无法看到宿主机上的其他进程,本质上实现了权限上的隔离。这两项其实都是Linux平台上的成熟技术,甚至在Docker出现前已经被用在Cloud Foundary的PaaS平台上。
|
||||
|
||||
Docker能够快速崛起的重要原因是,它通过容器镜像可以将文件系统与应用程序一起打包。这个文件系统是指操作系统所包含的文件、配置和目录。这样,就不会出现各种环境参数差异导致的错误,应用的部署变得非常容易,完美解决了应用打包的问题。
|
||||
|
||||
容器的本质是进程,但复杂的应用系统往往是一个进程组。如果为每个进程建立一个容器,那么容器间就有非常密切的交互关系,这样管理起来就更加复杂。
|
||||
|
||||
那么,有什么简化的办法吗?
|
||||
|
||||
Kubernetes给出的答案就是Pod。
|
||||
|
||||
<li>
|
||||
<h3>Pod</h3>
|
||||
</li>
|
||||
|
||||
在 Kubernetes 的设计中,最基本的管理单位是 Pod,而不是容器。
|
||||
|
||||
Pod是Kubernetes在容器之上的一层封装,它由运行在同一主机上的一个或者多个容器构成。而且,同一个Pod中的容器可以共享一个Network Namespace和同一组数据卷,从而高效的信息交换。因为具有了这些特性,Pod通常会被类比为物理机。
|
||||
|
||||
Pod存在的意义还在于可以屏蔽容器之间可能存在依赖关系,这样做到Pod在拓扑关系上的完全对等,调度起来更加简单。
|
||||
|
||||
那么Pod又是如何被管理的呢?这就要说到Kubernetes的整体架构。
|
||||
|
||||
<li>
|
||||
<h3>整体架构</h3>
|
||||
</li>
|
||||
|
||||
总体上,Kubernetes是一个主从结构(Master-Slave)。其中Master是一个控制面板,每个Salve就是物理节点上代理Kubelet,Master与Kubelet通讯完成对物理节点上Pod和Container的管理。外部网络可以直接通过节点上的Proxy,调用容器中的服务,不需要经过Master。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/4b/72/4b0b3a0f84c1005c6209e0b419571d72.jpg" alt="">
|
||||
|
||||
Master内部又包括API Server、Scheduler、Controller和ETCD四个部分,它们的职责分工和这一讲的内容没有直接关系,为了降低学习难度,这里就不做具体介绍了。如果你想再深入了解Kubernetes相关知识,可以在张磊老师的专栏找到更多资料。
|
||||
|
||||
## 有状态服务(StatefulSet)
|
||||
|
||||
对于无状态服务的管理,用户可以定义好无状态服务的副本数量,Kubernetes调度器就会在不同节点上启动多个 Pod,实现负载均衡和故障转移。多个副本对应的 Pod 是无差别的,所以在节点出现故障时,可以直接在新节点上启动新的Pod替换已经失效的Pod。整个过程不涉及状态迁移问题,管理起来很简单。
|
||||
|
||||
但是,作为应用系统的基石,数据库和存储系统都是有状态服务。如果将它们排除在外,那容器化的价值将大打折扣。所以,Kubernetes 在V1.3 版本开始推出PetSet用于管理有状态服务,并在V1.5版本更名为StatefulSet。
|
||||
|
||||
通常,我们说数据库是一个有状态的服务,是指服务要依赖持久化数据,也就是存储状态。而对于StatefulSet来说,状态又分为两部分,除了存储状态,还有系统的拓扑状态。
|
||||
|
||||
### 拓扑状态
|
||||
|
||||
拓扑状态是指集群内节点之间的关系,在Kubernetes中就是Pod之间的关系。
|
||||
|
||||
对于应用服务器来说,因为它们互相之间是不感知、不依赖的,所以可以随意创建和销毁。但数据库就不一样了,即使是单体数据库,也会有主从复制的关系,从节点是依赖于主节点的。
|
||||
|
||||
而分布式数据库的节点角色更加复杂。除了CockroachDB这样的P2P架构,多数分布式数据库中的节点拓扑关系是不对等的,会明确的划分为计算节点、数据节点、元数据和全局时钟等。
|
||||
|
||||
拓扑状态管理的第一步是标识每个Pod。我们已经知道,Pod随时会被销毁、重建,而重建之后IP会发生变化,这将导致无法确定每个Pod的角色。StatefulSet采用记录域名的方式,再通过DNS解析出Pod的IP地址。这样Pod就具有了稳定的网络标识。
|
||||
|
||||
同时,为了确保体现Pod之间的依赖关系,StatefulSet还引入顺序的概念,将Pod的拓扑状态,也就是启动顺序,按照 Pod 的“名字 + 编号”的方式固定了下来。
|
||||
|
||||
### 存储状态
|
||||
|
||||
数据库的核心功能是存储,我们再来看看如何实现存储状态的管理。
|
||||
|
||||
早期版本中,提供了两种存储方式,分别是本地临时存储和远程存储。顾名思义,本地临时存储中的数据会随着Pod销毁而被清空,所以无法用做数据库的底层持久存储。
|
||||
|
||||
远程存储可以保证数据持久化,所以是一种可选方案。具体来说,就是使用持久化卷(Persistent Volume)作为数据的存储载体。当Pod进行迁移时,对应的PV也会重新挂载,而 PV 的底层实现是分布式文件系统,所以新的Pod仍然能访问之前保存的数据。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/2d/d1/2d729737d75e0419e9ec8accc27a6cd1.jpg" alt="">
|
||||
|
||||
远程存储虽然可以使用,但是它与分布式数据库的架构设计理念存在很大冲突。我们在课程中介绍过,分布式数据库都是采用本地磁盘存储的模式,并且对存储层做了很多针对性的优化。如果改为远程存储,这些设计将会失效,导致性能上有较大的损失。
|
||||
|
||||
事实上,这就是很多人反对数据库容器化部署的最主要的原因,数据密集型应用对I/O资源的消耗巨大,远程存储无法适应这个场景。
|
||||
|
||||
针对这个不足,Kubernetes尝试引入本地持久卷(Local Persistent Volume)来解决。简单来说,就是一个Local PV 对应一块本地磁盘。开启Local PV特性后,调度器会先获取所有节点与Local PV对应磁盘的关系,基于这些信息来调度Pod。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/21/66/215a6d5cc03f95e7dcaf499e3fc03266.jpg" alt="">
|
||||
|
||||
与普通PV不同,当挂载Local PV的节点宕机并无法恢复时,数据可能就会丢失。这和物理机部署方案面临的问题是一样的,而分布式数据库的多副本机制正好弥补了这一点。
|
||||
|
||||
不过Local PV推出得较晚,直到V1.10(2018年发布)Kubernetes才相对稳定地支持调度功能,在2019年3月的V1.14中正式发布。
|
||||
|
||||
通过对拓扑状态和存储状态的管理,StatefulSet初步解决了有状态服务的管理问题,但其中的一些关键特性(比如Local PV)还不够成熟。另外,由于Kubernetes的抽象程度比较高,所以在真正实现分布式数据库的部署还需要很多复杂的控制。
|
||||
|
||||
## Operator
|
||||
|
||||
控制逻辑的复杂性是与具体软件产品相关的,比如一个常见的问题就是对于Pod状态的判断。
|
||||
|
||||
Kubernetes 判断节点故障依据是每个节点上的 Kubelet 服务上报的节点状态。但是,Kubelet作为一个独立的进程,从理论上说,它能否正常工作与用户应用并没有必然联系。那么就有可能出现,Kubelet无法正常启动,但对应节点上的容器还可以正常运行。
|
||||
|
||||
这时,如果不处置原来的Pod,立即在其他节点创建新的Pod,应用系统可能就会出现异常。所以,调度过程还需要结合应用本身的状态来进行,其中的复杂性无法被统一封装,于是也就催生了一系列的Operator。
|
||||
|
||||
Operator 的工作原理就是利用了 Kubernetes 的自定义资源,来描述用户期望的部署状态;然后在自定义控制器里,根据自定义 API 对象的变化,来完成具体的部署和运维工作。简单来说,Operator 就是将运维人员对软件操作的知识代码化。
|
||||
|
||||
etcd-operator是最早出现的Operator,用于实现etcd的容器部署。Operator封装了有状态服务容器化的操作复杂性,对于应用系统上云的有重要的意义,有的分布式数据库厂商也开发了自己的Operator,比如TiDB和CockroachDB。
|
||||
|
||||
## 小结
|
||||
|
||||
那么,今天的课程就到这里了,让我们梳理一下这一讲的要点。
|
||||
|
||||
1. 容器可以更加精细的控制资源,并通过镜像功能实现应用打包部署,使开发、测试、生产等各个环境完美统一,因此得到了越来越广泛的使用。
|
||||
1. 容器是单进程模型,为了适应更复杂的应用,Kubernetes又引入了Pod概念,一个Pod包含了同一节点上的多个容器。Kubernetes通过调度管理Pod将复杂的应用系统快速容器化部署,这种技术称为“容器编排”。因为容器的本质是进程,所以Kubernetes也被成为下一代操作系统。
|
||||
1. Kubernetes早期以支持无状态服务为主,Pod完全对等,调度过程简单。为了适应更复杂的应用部署模式,Kubernetes也在不断完善对有状态服务的支持,使用StatefulSet对象封装了相应的功能,包括拓扑状态管理和存储状态管理。在1.14版本中发布了本地持久化卷特性,增强了存储状态管理能力。
|
||||
1. 对于分布式系统来说,有状态服务的管理非常复杂,通过简单的Kubelet无法把握各个服务的真实状态,所以就有了Operator这个扩展方式,每个产品厂商可以拓展自定义控制器,进行更有针对性的管理。目前,Operator的接受程度在不断提高,TiDB、CockroachDB都开发了自己的Operator。
|
||||
|
||||
今天,容器化对于分布式数据库来说并不是一个默认选项。少数产品如TiDB和CockroachDB开始提供容器化部署方案,这和他们正在开展的云服务商业模式有比较直接的关系。而更多的分布式数据库仍然使用物理机,例如OceanBase和GoldenDB等。没有厂商的支持,依靠用户自身的力量实现容器化,还有比较大的困难。
|
||||
|
||||
我认为在未来的一两年里,“数据库是否要容器化部署”仍然是一个有争议的话题。但数据库的容器化趋势应该是确定的,因为Kubernetes提供支持越来越完善,真正大规模落地只是时间早晚的问题。而随着分布式数据库普及,数据库的节点规模必然会快速扩大,运维成本随之提升,这也给数据库容器化带来更强的推动力。
|
||||
|
||||
如果你想更积极地尝试数据库容器化,可以把大数据应用作为一个风向标。这是因为大数据应用的可用性要求低于OLTP场景,而集群规模更大,上百甚至上千节点都是正常规模。这意味着,大数据应用的容器化改造要承担的风险更小,但收益更大。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/21/b4/21bf3396750b548a66bdbf7f7a18efb4.jpg" alt="">
|
||||
|
||||
## 思考题
|
||||
|
||||
课程的最后部分是我们今天的思考题。今天的课程中,我们简要介绍了Kubernetes对有状态服务的支持情况,从中不难发现,资源调度是它非常核心的功能。我的问题是,除了Kubernetes你还知道哪些集群资源调度系统?它们在设计上有什么差异吗?
|
||||
|
||||
欢迎你在评论区留言和我一起讨论,我会在答疑篇和你继续讨论这个问题。如果你身边的朋友也对数据库的容器化部署这个话题感兴趣,你也可以把今天这一讲分享给他,我们一起讨论。
|
||||
156
极客时间专栏/geek/分布式数据库30讲/实践篇/27 | 产品测试:除了性能跑分,还能测个啥?.md
Normal file
156
极客时间专栏/geek/分布式数据库30讲/实践篇/27 | 产品测试:除了性能跑分,还能测个啥?.md
Normal file
@@ -0,0 +1,156 @@
|
||||
<audio id="audio" title="27 | 产品测试:除了性能跑分,还能测个啥?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/6d/ef/6dac7702305e644426f7057364625def.mp3"></audio>
|
||||
|
||||
你好,我是王磊,你也可以叫我Ivan。
|
||||
|
||||
这一讲我们的关键词是“测试”。无论是作为程序员还是架构师,我们都不会忽视测试的重要性,它贯穿于软件工程的整个生命周期,是软件质量的重要保障手段。
|
||||
|
||||
不过,提到分布式数据库的测试,你也许会有些疑问,我又不是数据库研发人员,还要关心测试吗?
|
||||
|
||||
当然是需要了。比如,拿我来说,一名银行的科技人员。银行和很多传统企业一样,多数应用系统都是构建在商业软件之上,对于基础软件研发的投入比较有限,所以多数银行是不具备自研分布式数据库能力的。但是,分布式数据库的高并发、高可用性特点,意味着使用它的一定是非常重要和关键的业务系统。那么,为了保证系统的安全运行,即使不是开发者,我们也仍然需要做大量的验证和测试工作。
|
||||
|
||||
说到这,我猜你会想到一个词。对,就是POC(Proof of Concept)。POC的意思是概念验证,通常是指对客户具体应用的验证性测试。那验证性测试又具体要测些什么呢?对于数据密集型系统,很多企业的POC都会使用TPC基准测试。
|
||||
|
||||
## TPC-C
|
||||
|
||||
TPC(Transaction Processing Performance Council),也就是国际事务性能委员会,是数十家会员公司参与的非盈利组织。它针对数据库不同的使用场景组织发布了多项测试标准,其中被业界广泛接受有TPC-C 、TPC-H和TPC-DS。
|
||||
|
||||
这三个测试标准针对不同的细分场景。简单来说,TPC-C针对OLTP场景;TPC-H针对OLAP场景;而更晚些时候推出的TPC-DS,在TPC-H的基础上又针对数据仓库的建模特点做了更新,并且在2.0版本中又增加对大数据技术的针对性测试。
|
||||
|
||||
这里,因为我们讲的分布式数据库主要服务于OLTP场景,所以我们重点关注TPC-C。
|
||||
|
||||
TPC-C发布的[标准规范](http://www.tpc.org/tpc_documents_current_versions/pdf/tpc-c_v5.11.0.pdf)中,模拟了一家大型电子商务网站的日常业务。根据规范中的背景设定,这家公司的业务覆盖了很大的地理范围,所以设立了很多的仓库来支持邻近的销售区域,每个仓库都要维护100,000种商品的库存记录并支持10个销售区域,每个销售区域服务3,000个客户。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/eb/bf/eba73a94b276297e9eb9d0ed258a8ebf.png" alt="" title="引自 TPC-C 标准规范(Revision 5.11)">
|
||||
|
||||
这个场景对应的数据库模型一共包含9张表,覆盖了订单创建、支付、订单状态查询、发货和检查库存等五种事务操作。客户会查询已经存在订单的状态或者下一个新的订单。平均每个订单有10个订单行(Order-Line),有1%订单行的商品在其对应的仓库中没有存货,必须由其他区域的仓库来供货。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/d2/0e/d29ec7c6e83754255e76d4dfe266520e.png" alt="" title="引自 TPC-C 标准规范(Revision 5.11)">
|
||||
|
||||
可以看出,TPC-C模拟的整个业务场景和我们日常使用的电子商务网站是非常相似的。所以说,TPC-C测试场景是很有代表性的OLTP业务。
|
||||
|
||||
TPC-C为数据库测试提供了一个开放的测试标准,很多POC甚至会直接套用这些数据模型和事务操作。可POC做起来真有这么容易吗?
|
||||
|
||||
如果你实际组织过POC,就肯定听到过类似这样的一些说法:
|
||||
|
||||
“A公司的数据库是针对TPC-C做了优化的,只是测试分数高,实际用起来不行。”
|
||||
|
||||
“B公司的数据库为某个查询语句设置了缓存,这样的测试对我们不公平。”
|
||||
|
||||
总之,就是友商为刷高分做了优化,有作弊的嫌疑。
|
||||
|
||||
这时,作为组织者该怎么处理呢?可以用一些管理上的办法去协调,但真正解决问题的只有一个,就是要对产品架构有深入的了解,这样才能判断特定的优化措施在自己的真实业务场景下是否普遍有效。如果是普适的,那自然就没问题。
|
||||
|
||||
你看,要做好甲方工程师,也是有要求的。
|
||||
|
||||
TPC-C的测试用例除了性能测试,也包含了事务一致性的测试,但实际测试中这部分往往会被忽略。这一方面是为了简化测试过程,另一方面是因为大家会觉得没有必要。既然这些产品都有不少实际案例了,那事务一致性应该就没问题了吧。
|
||||
|
||||
可是,对于分布式数据库来说,这真不是个简单的事情,甚至要更加严谨的技术手段来证明。那么,事务一致性方面有没有比TPC-C更权威的测试标准呢?
|
||||
|
||||
当然有了,这就是Jepsen。
|
||||
|
||||
## Jepsen
|
||||
|
||||
这个名字是不是有点耳熟?其实我们在[第3讲](https://time.geekbang.org/column/article/272999)介绍事务一致性时就提到过它。Jepsen是一个开源的分布式一致性验证框架,专门用来测试分布式存储系统,比如分布式数据库、分布式键值系统和分布式消息队列等等。
|
||||
|
||||
Jepsen曾经对很多知名的分布式存储系统进行了测试,而且往往都会发现一些问题,其中分布式数据库就包括CockroachDB、YugabyteDB、TiDB、VoltDB和FaunaDB等。以下是摘自[Jepsen官网](http://jepsen.io/analyses)的所有测试系统列表。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/4d/42/4d236826a0852f3232d45655e9a11542.png" alt="" title="引自Jepsen官网">
|
||||
|
||||
要知道这些测试并不是Jepsen单方面开展的,而都是和产品团队共同协作完成的,并且这些产品厂商还要向Jepsen支付费用。由此可见,Jepsen在分布式系统测试方面,已经具有一定的权威性。
|
||||
|
||||
作为开源软件,你可以从Github上下载到[Jepsen的源码](https://github.com/jepsen-io/jepsen),所以有些厂商就在它的基础上定制自己的测试系统。但是比较遗憾的是,Jepsen的作者选择了一种小众的开发语言Clojure。我猜,这给多数程序员带来了障碍,因为我能想到的Clojure项目似乎只有Storm。
|
||||
|
||||
这里,我们简单介绍下Jepsen的架构。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/32/19/3271638fe2857f947d54830c638f7619.jpg" alt="">
|
||||
|
||||
按照Jepsen的推荐方案,被测试的分布式系统通常部署在5个节点上,而Jepsen的程序主要部署在另外的控制节点上。这个控制节点会初始化若干个进程作为分布式系统的访问客户端,当然这里也包括了分布式系统提供的客户端代码。
|
||||
|
||||
测试过程中,控制节点要完成三项工作,第一是通过Generator生成每个客户端的操作,第二是通过Nemesis实现故障注入,最后使用Checker分析每个客户端的操作记录来验证一致性。
|
||||
|
||||
在整个测试框架中,Nemesis是特别重要的部分,这是因为Jepsen的核心逻辑就是要在各种错误情况下,检测分布式系统还能否正常运行。
|
||||
|
||||
“故障注入”在普通测试中并不常见,这里的故障是特指网络分区、时钟不同步这样的底层基础设施层面的问题。因为分布式系统的架构复杂,节点间有千丝万缕的联系,任何软硬件基础设施的错误都可能造成不可收拾的后果,但业务逻辑层面的测试用例又无法覆盖这类场景,所以要靠Jepsen来填补这块空白。
|
||||
|
||||
说到这,你或许会问,既然故障注入这么重要,那么Jepsen注入的这些故障就够了吗?我们是不是要按照自己的业务场景增加一些故障呢?
|
||||
|
||||
嗯,不少人也有类似的想法。这就要说一下混沌工程的概念了。
|
||||
|
||||
## 混沌工程
|
||||
|
||||
混沌工程(Chaos Engineering)最早是由Netflix工程师提出来的。他们给出了这样的定义:混沌工程是在分布式系统上进行实验的学科, 旨在提升系统的容错性,建立对系统抵御生产环境中发生不可预知问题的信心。
|
||||
|
||||
我们可以从三个层面来理解这个定义。
|
||||
|
||||
1. 复杂性
|
||||
|
||||
首先,分布式系统的复杂性是混沌工程产生的基础。相比传统的单体系统,分布式系统中包含更多硬件设备,多样化的服务和复杂交互机制。这些因素单独来看似乎是可控的,也有完备的异常处置手段,但当它们组合在一起就会相互影响从而引发不可预知的结果,导致故障发生。而人力是不可能完全阻止这些故障。
|
||||
|
||||
混沌工程就是在这些故障发生前,尽可能多的识别出导致这些异常的因素,主动找出系统脆弱环节的方法学。
|
||||
|
||||
1. 实验
|
||||
|
||||
第二关键点是实验。混沌工程与单纯的故障注入是有区别的,混沌工程的输入是尝试性,目的是探索更多可能发生的奇怪场景,促使正常情况下不可预测的事情发生,从而确认系统的稳定性。我想,正是因为结果具有很大的不确定性,这个过程才会称为“实验”。
|
||||
|
||||
最早的混沌测试工具是Netflix的Chaos Monkey,它只会注入一种混乱,那就是随机杀死节点。后来逐步发展,混沌测试框架引入的故障越来越多,包括模拟网络通讯延迟、磁盘故障、CPU负载过高等等。而混沌测试的观察对象也不仅是一致性(像Jepsen那样),而是从系统的各个维度上定义一系列稳态指标,观察混乱注入后系统是否能够快速恢复。
|
||||
|
||||
1. 生产环境
|
||||
|
||||
第三点,也是混沌工程非常核心的理念,混沌实验在生产环境进行才会获得更大的价值,因为这样才能真正建立起信心,相信系统能抵御各种故障。不过,这个理念也有一定的争议。比如,你今天坐飞机出差,这时混沌工程师要在飞机的控制系统上注入一些故障,想看看系统会不会崩溃,你能接受吗?我想,正常人都会拒绝吧。
|
||||
|
||||
显然,对真实业务造成什么后果是做出判断的依据。虽然混沌工程还有一个爆炸半径理念,要限定对生产环境的影响。但是,在生产环境注入混乱来验证系统稳定性的这个理念,对哪些行业适用,进一步又对哪些业务适用,我觉得还是有待探讨的话题。
|
||||
|
||||
目前,一些分布式数据库也应用混沌工程进行系统测试,例如GoldenDB、CockroachDB和TiDB。
|
||||
|
||||
到这里,对于测试这个话题,我们已经谈了很多,但其实还漏掉了很重要的一点。你能猜到是什么吗?别着急,让我先给你讲一个小故事。
|
||||
|
||||
## TLA
|
||||
|
||||
在前面的课程中,我曾提到过我设计的一款软件Pharos。它有一个试验特性是在写入数据时,始终保持索引与数据的事务一致性,要知道它的底层是HBase,本身是不支持跨行事务的,所以说实现这个特性还是有点难度的。
|
||||
|
||||
有一次在介绍Pharos时,一位同学问我,怎么证明Pharos实现了事务一致性呢?我列举了做过的很多破坏性测试,比如杀掉进程、直接重启服务器等等,这些都没影响到事务一致性。但是,讲完之后,我们两个人似乎都对这个答案不太满意。
|
||||
|
||||
后来,我就想,我的测试方法还能改进吗?再增加一些异常场景?可似乎都没有本质上的变化。你看,无论TPC-C、Jepsen还是混沌工程,虽然方法、理念各不相同,但是都有一个共同点,就是它们只能发现错误,却无法证明正确性。
|
||||
|
||||
换句话说,测试是在用证伪的方式来检查软件质量,但是对一个复杂系统来说,测试用例是无法穷尽的,那也就永远不能排除存在Bug的可能性。这个结论很让人沮丧,那么,有没有“证明”的方法呢?
|
||||
|
||||
方法也是有的,叫做形式化验证(Formal Verification),就是用数学方法去证明我们的系统是无 Bug 的,具体就是用数学工具进行定义、开发和验证(Specification, Development and Verification)。从一个更高阶的视角来看,不论硬件还是软件,归根结底是在解决数学问题。形式化验证的逻辑就是,如果能够按照严格的数学方法描述设计,那么结果的正确性就也是可以被证明。
|
||||
|
||||
但是,要把关键设计按照数学的方式表述一遍,这个实现成本就比较高。所以,形式化验证在软件领域并不常见,而是从硬件领域开始普及,比如Intel就在芯片设计中就广泛采用形式化方法。而后随着分布式系统的流行,形式化验证被应用的越来越多。
|
||||
|
||||
那么,形式化方法如何在软件工程落地呢?方法就是Leslie Lamport提出的TLA(Temporal Logical of Actions,行为时态逻辑),对又是这位大神。TLA就是使用数理逻辑来描述系统的时序状态,并验证程序的正确性。
|
||||
|
||||
1994年Lamport发表了[同名论文](https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.33.4815&rep=rep1&type=pdf)。1999年Lamport又发表“[Specifying Concurrent Systems with TLA+](https://www3.risc.jku.at/education/oldmoodle/file.php/28/marktoberdorf.pdf)”论文,提出了TLA+。TLA+是一种软件建模语言,再加上配套的模型校验工具TLC,这样我们就可以像写程序一样编写TLA,可以运行来验证最终结果的。2002年Lamport又发布了一本完整的TLA+教科书[**Specifying Systems: The TLA+ Language and Tools for Software Engineers**](http://lamport.azurewebsites.net/tla/book-02-08-08.pdf)。因为TLA+使用的是数学化的表达方式,对程序员并不友好,所以后来又出现了PlusCal。它比TLA+更接近于编程语言,写好的代码可以很方便的转换成TLA+并使用TLA+的模型验证。
|
||||
|
||||
## 小结
|
||||
|
||||
好了,今天的课程就到这里了,让我们梳理一下这一讲的要点。
|
||||
|
||||
1. TPC-C是国际事务性能委员会针对OLTP数据库建立的一套测试规范,也是目前广泛接受的测试基准。在很多企业的POC测试中会引入TPC-C,但是由于TPC-C的开放性,有的产品会进行针对性优化,使得最终的评测指标失真。要能够分辨优化手段是否对你的业务有普适性,还需要对产品架构的深入掌握。
|
||||
1. Jepsen是针对分布式存储系统,进行数据一致性和事务一致性测试的工具。目前已经测试了很多知名系统,具有一定的权威性。Jepsen通过故障注入的方式进行测试,会覆盖很多在普通测试不能发现的场景。
|
||||
1. 混沌工程是针对分布式系统提出的方法学。它和测试一样都是为了提高系统的可用性和稳定性,以故障注入为主要手段。混沌工程并不仅是针对某个具体分布式系统提出的。它强调在生产环境注入故障,在受控的范围内观测系统,体现了反脆弱的思想。总之,混沌工程试图从企业整体运维的视角,用截然不同的理念来提升系统的可用性。
|
||||
1. 所有的测试方法都只能发现问题,但无法证明正确性。形式化验证可以完美解决这问题,并在很多硬件设计领域有落地实践。Lamport提出的TLA将形式化验证引入软件工程,使用数学工具定义程序逻辑,从而可以达到证明软件无Bug的目标。经过不断完善,TLA从模型到语言、工具建立了一套完备的机制,很多企业也开始使用TLA证明关键设计逻辑的正确性。
|
||||
|
||||
今天的课程内容可以归结为测试和形式化验证两部分,我们也做了一些比对说明,但并不是说要用验证(Verification)来代替测试(Testing)。通过TLA可以验证程序逻辑是否正确,这是个了不起的成就,但是要用数学语言再翻写一遍,付出的成本太高。而且,实际工程中也不可能将所有的代码都转换为PlusCal或TLA+来做全面的验证。更多情况下,只是TLA来验证关键设计逻辑,剩余的多数代码还是要靠测试来发现问题。总之,测试是不能被验证替代的。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/ce/12/ce294dc8e2343571dyy67f2a4c2da212.jpg" alt="">
|
||||
|
||||
## 思考题
|
||||
|
||||
课程的最后,我们来看下思考题。今天我们的关键词是“测试”,也谈了很多测试方法和理念。不难发现,这些规范和工具都伴随着分布式系统的普及演进。而分布式系统并不限于分布式数据库,其他类型的分布式存储系统也越来越多,所以单一面向数据库的测试工具已经不能满足要求。那么,我今天的问题就是,对于其他类型的分布式存储系统,你知道有哪些主流的测试工具吗?
|
||||
|
||||
欢迎你在评论区留言和我一起讨论,我会在答疑篇和你继续讨论这个问题。如果你身边的朋友也对数据库测试这个话题感兴趣,你也可以把今天这一讲分享给他,我们一起讨论。
|
||||
|
||||
## 学习资料
|
||||
|
||||
GitHub: [**jepsen**](https://github.com/jepsen-io/jepsen)
|
||||
|
||||
Jepsen: [**Analyses**](http://jepsen.io/analyses)
|
||||
|
||||
Leslie Lamport: [**A Temporal Logic of Actions**](https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.33.4815&rep=rep1&type=pdf)
|
||||
|
||||
Leslie Lamport: [**Specifying Concurrent Systems with TLA+**](https://www3.risc.jku.at/education/oldmoodle/file.php/28/marktoberdorf.pdf)
|
||||
|
||||
Leslie Lamport: [**Specifying Systems: The TLA+ Language and Tools for Software Engineers**](http://lamport.azurewebsites.net/tla/book-02-08-08.pdf)
|
||||
|
||||
Transaction Processing Performance Council: [**TPC BENCHMARK™ C:Standard Specification (Revision 5.11)**](http://www.tpc.org/tpc_documents_current_versions/pdf/tpc-c_v5.11.0.pdf)
|
||||
166
极客时间专栏/geek/分布式数据库30讲/实践篇/28 | 选型案例:银行是怎么选择分布式数据库的?.md
Normal file
166
极客时间专栏/geek/分布式数据库30讲/实践篇/28 | 选型案例:银行是怎么选择分布式数据库的?.md
Normal file
@@ -0,0 +1,166 @@
|
||||
<audio id="audio" title="28 | 选型案例:银行是怎么选择分布式数据库的?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/b4/3c/b4fff21859f44d3f4f9824c3960dc43c.mp3"></audio>
|
||||
|
||||
你好,我是王磊,你也可以叫我Ivan。
|
||||
|
||||
在前面的课程中,我们已经介绍了分布式数据库方方面面的知识。这些知识,我觉得大概会在三个方面帮到你,分别是数据库研发、架构思维提升和产品选型。今天,我会通过几家银行的案例带你了解如何做分布式数据库的选型。
|
||||
|
||||
为什么要讲银行的分布式数据库选型呢?
|
||||
|
||||
你肯定在想,这是因为王磊老师刚好是在银行工作,更熟悉这个行业。这么说也对,银行业确实是我最熟悉的行业。但是更重要的原因是,数据库作为一款基础软件,稳定性和可靠性就是它的立身之本。而对稳定性要求最严苛的行业,就是金融业,尤其是银行业。所以,只有经过金融场景的考验,一款数据库产品才能真正扬名立万,让其他行业的用户放心使用。
|
||||
|
||||
也是因为这个原因,不少厂商都打出了“金融级分布式数据库”的旗号。
|
||||
|
||||
分布式数据库的应用场景主要特征是海量并发,所以理论上说,业务规模越大,使用分布式数据库的需求也就越迫切。无论从用户数量还是资产规模,国内最大的银行肯定是工商银行。
|
||||
|
||||
## 工商银行(分布式中间件)
|
||||
|
||||
工行之前的数据库主要是Oracle和IBM的DB2,这很代表性,过去的20年银行业基本上就是在这两种产品中二选一。
|
||||
|
||||
Oracle和DB2都是单体数据库,只能采用垂直扩展方式,在碰到技术天花板后就会限制业务的发展。作为业务量最大的“宇宙行”,工行面对这个问题的选择是,从单体数据库向以MySQL为基础的分库分表方案转型。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/19/a3/190985f37f6f535718f7b92e429c74a3.jpg" alt="">
|
||||
|
||||
为什么工行没有选择真正的分布式数据库呢?
|
||||
|
||||
我认为,其中主要原因是产品成熟度。工行的架构改造在2018年大规模落地,而调研和试点工作则在更早的2016-2017年。这个时点上,商用NewSQL数据库刚刚推出不久,而金融场景的种种严苛要求,注定了银行不会做第一个吃螃蟹的人,那么这种可能性就被排除了。同样,另一种PGXC风格的分布式数据库也正待破茧而出,反而是它的前身,“分布式中间件+开源单体数据库”的组合更加普及。
|
||||
|
||||
所以,对当时的工行来说,产品架构上是没有什么选择余地的,能做的就是选择产品。后来的结果是选择了DBLE + MySQL的组合,选择MySQL是因为它的普及程度足够高;而选择DBLE则因为它是在MyCat的基础上研发,号称是“增强版MyCat”,由于MyCat已经有较多的应用案例,所以这一点给DBLE带来不少加分。
|
||||
|
||||
现在看来,这个方案显得有点平淡无奇。但正是这种稳妥,或者说有点保守的选择,最大程度规避了风险,也坚定了工行从主机下移应用系统的决心。从后来MySQL上千节点的使用规模看,这个方案更大的意义在于,使工行逐步脱离了对IBM主机和Oracle数据库的依赖。分布式数据库的尝试只是这个大目标下的副产品。
|
||||
|
||||
相对于OLTP技术应用上的平淡,工行在OLAP方面的技术创新则令人瞩目。基本是在同期,工行联合华为成功研发了GaussDB 200,并在生产环境中投入使用。这款数据库对标了Teradata和Greenplum等国外OLAP数据库。在工行案例的加持下,目前不少银行计划或者正在使用这款产品替换Teradata数据库。
|
||||
|
||||
## 邮储银行(单元化)
|
||||
|
||||
邮政储蓄银行,简称邮储银行,由于特殊的历史沿革,它没有被归入通常所说“四大国有银行”,但这不意味着它的业务规模小。事实上,邮储银行的零售用户在2019年已经超过6亿。
|
||||
|
||||
这个庞大的用户基数使得邮储银行也早早地就开始探讨分布式数据库的使用。那他们采用了什么方案呢?
|
||||
|
||||
可能又让你失望了,他们也没有选择分布式数据库。邮储的核心业务系统改造方案更接近于单元化架构,所以连分布式中间件都没使用。它的设计思路就是将原来商业数据库拆分成若干个小的单体数据库,分别设置对应的应用实例。邮储在单体数据库上选择了PostgreSQL,这个在银行业中是相对较少使用的。
|
||||
|
||||
当然,单元化方案从应用整体看也是一种分布式架构,通过应用层面的重构弱化了对数据库的性能和稳定性等方面的要求。说到这,你可能会有个疑问,如果两种方式都能解决问题,那要怎么在单元化和分布式数据库之间选择呢?
|
||||
|
||||
从成本上看,系统的单元化改造要付出巨大的代价,是一个推倒重建的过程,远高于过渡到分布式数据库的代价。我认为,邮储之所以会选择这个方式,可能有两个原因:
|
||||
|
||||
1. 对数据库的技术把控能力。毕竟分布式数据库带来的技术挑战不容忽视。
|
||||
1. 核心系统本身重构的必要性。如果应用系统的分布式改造势在必行,那么两个方案的目标都截然不同,成本的比较也就无从谈起了。
|
||||
|
||||
同样,民生银行也是在核心系统改造的背景下,完成了向分布式架构的升级。在民生银行的一份宣传材料中对分布式技术平台做了整体描述,其中有两段是和数据库相关,是这么写的“通过分库分表和读写分离实现分布式数据访问功能;基于可靠消息的最终一致性和基于冲正模型的反向处理实现分布式事务功能”。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/7a/a5/7a7b7bfc0ea2712401fbbccce771f5a5.jpg" alt="">
|
||||
|
||||
可见民生银行也选择了与邮储银行大致相同的路线,弱化了分布式数据库的作用,更加强调整体架构改造,在应用系统层面做了更多的工作。
|
||||
|
||||
好了,刚才我们说到的三家银行都采用了迂回的方案,下面终于要用到分布式数据库了。
|
||||
|
||||
## 交通银行(研发NewSQL)
|
||||
|
||||
交通银行的分布式数据库之路走得比较特别,它采用联合高校研发的方式,与华东师范大学和西北工业大学共同研发了分布式数据库CBase。
|
||||
|
||||
CBase研发开始于2014年,在分布式数据库中算是非常早的了,但它的整体架构风格非常接近于NewSQL。不同于前几家银行,CBase并不是某个重要业务系统的附属品,已经有点技术驱动的味道。
|
||||
|
||||
它最先用于历史库系统的数据存储,而后逐步实现了复杂SQL语句处理和高并发事务处理能力,在供应链、贷记卡授权和网联支付等系统使用。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/ac/f2/acb8d35e2ac23d9a97ac3302f7c76ff2.png" alt="" title="引自刘雷 等 (2019)">
|
||||
|
||||
通过架构图,我们可以看到CBase的主要工作负载放在三类节点上,其中的数据存储节点与NewSQL风格完全一致,而剩下的SQL处理节点和事务处理节点,就是计算节点的细化。而且,CBase也基于Raft协议设计和实现了轻量级分布式选举协议,分布式事务同样是在2PC上进行改进的。
|
||||
|
||||
这款数据库主要在交通银行内部使用,目前并没有看到其他的商业化案例,所以能够找到的资料比较少。不过,CBase开发团队在2019年发表了一篇论文《[分布式数据库在金融应用场景中的探索与实践](http://www.infocomm-journal.com/bdr/CN/article/downloadArticleFile.do?attachType=PDF&id=168111)》(刘雷 等(2019)),介绍了CBase的部分设计,如果你有兴趣可以仔细研读下。
|
||||
|
||||
交通银行研发分布式数据库在银行业是很有代表性的,因为之前还很少有在基础软件上进行大规模投入的先例。同样在2014年,中信银行也走上了联合研发的道路。
|
||||
|
||||
## 中信银行(研发PGXC)
|
||||
|
||||
终于要说到中信银行了,课程中我们已经多次讲过的GoldenDB就是中信银行与中兴通讯联合研发的产品,而目前GoldenDB主要用户也是中信银行。中信银行的核心业务系统在2020年5月正式上线切换到GoldenDB。这之前,基于GoldenDB的信用卡新核心系统已经在2019年10月投产运行。这两个重要系统的运行,使中信银行无可争议地成为分布式数据库应用最为深入的一家银行。核心业务系统是银行业务的心脏,它的稳定运行无疑为其他银行树立了标杆,客观上也加快分布式数据库的普及速度。
|
||||
|
||||
GoldenDB和CBase有大致相同的发展路径,从产品研发到试点应用,只不过中信银行的步子更快些。当然,这并不是说交行研发人员的能力不行,因为这个速度上的差别确实有架构上的因素。GoldenDB是PGXC风格的分布式数据库,遇到的技术挑战更小;当然NewSQL架构上的优势,也让我们对CBase的未来充满期待。
|
||||
|
||||
你有没有注意到,还有一个很有意思的地方,同样是核心系统改造,为什么中信银行就使用了分布式数据库呢?
|
||||
|
||||
答案还是在于项目目标不同。中信的目标就是完成AS400小机下移,将应用程序翻写到开放平台,但是对应用架构本身并没有改造诉求。所以,数据库层面的平滑过渡就有很大的优势,编码逻辑改动小,测试成本低,最重要的是不会因为技术原因变动业务流程,这样就大大降低了项目的实施难度。
|
||||
|
||||
## 北京银行(NewSQL)
|
||||
|
||||
北京银行是城市商业银行中的佼佼者,但相对于前几家银行,在资产规模和用户数量上有较大的差距。北京银行从2018年开始,先后在网联支付系统和网贷系统中应用了TiDB。
|
||||
|
||||
事实上,很多比北京银行规模更小的城市商业银行,比如南京银行(OceanBase)、张家港银行(TDSQL)都已经上线了分布式数据库。表面上,我们似乎很难捕捉到他们替换数据库的动因。从业务压力的角度,业务量通常没有达到海量并发级别;同时城商行通常也不涉及“主机下移”带来可用性下降问题。
|
||||
|
||||
那么,他们为什么要做出这个选择呢?我觉得主要有三点原因。
|
||||
|
||||
1. 国产化的诉求
|
||||
|
||||
由于各种原因,继续依赖Oracle这样的国外商业产品,很可能让银行将面临更大的风险。而对于小型银行来说,使用开源数据库还是分布式数据库,在成本上可能差异并不大。
|
||||
|
||||
随着国内厂商加大技术投入,隐约有一种趋势,就是分布式数据库正在逐步成为国产数据库的代名词。那些原本深耕单体数据库技术的厂商,比如达梦、人大金仓,也在朝着分布式架构转型。
|
||||
|
||||
所以,选择分布式数据库也就满足了国产化的诉求。
|
||||
|
||||
1. 实际收益
|
||||
|
||||
由于小型银行的数据量并不大,上线分布式数据库后集群的节点规模没有大幅增长,对运维的冲击也相对小些。此外,利用分布式数据库的多租户特性,转变成类似Aurora使用方式,还能降低数据库实例管理的复杂度。所以,使用分布式数据库也是有一些实际收益的。
|
||||
|
||||
1. 技术潮流
|
||||
|
||||
这也是我在开篇词中说的,一旦技术的趋势形成,就会在无形中影响人们的选择。就像时尚潮流那样,在同等价位下,大家当然更愿意选那些流行款式。今天,分布式架构转型就是这样的潮流,微服务架构、分布式数据库甚至容器云都是这个大潮下的浪花。
|
||||
|
||||
在风险可控的前提下,受到技术潮流的影响,我觉得可能还会有更多的小型银行会选择分布式数据库。
|
||||
|
||||
## 光大银行(NewSQL & 分库分表)
|
||||
|
||||
下面,我来聊聊光大银行的分布式数据库实践。简单来说,光大使用了双路线策略,也就是同时使用NewSQL和分库分表方案。
|
||||
|
||||
在云缴费系统中,光大使用了自研的分库分表方案。首先,这个系统的业务量,也就是缴费的业务量是非常大的。可能你不知道,今天支付宝、微信甚至很多银行的缴费服务,在后台都是要调用光大的云缴费系统的。截至2019年,云缴费系统的累计用户达到了5.49亿。
|
||||
|
||||
其实,缴费业务是非常互联网化的业务,就是银行提供服务对接用户和缴费企业,所以它的业务模型比较简单和统一。这也意味着,它对分布式事务这样的复杂操作没有那么强烈的诉求。最后,用分库方案就很好地解决了海量业务的问题。
|
||||
|
||||
光大在另一个系统,新一代财富管理平台使用了NewSQL数据库,也就是TiDB。这个系统是理财业务的全流程管理平台,业务量相对缴费要小很多,但业务要更复杂,而且在联机和批量方面都有计算需求。
|
||||
|
||||
这个架构选择更多是面向未来,因为理财业务是光大银行重点发力的业务,对未来业务量的增长还是有很大预期的。同时,我想,伴随着NewSQL技术的发展,保持团队对新技术的感知和掌握,应该也是一个重要的原因。
|
||||
|
||||
## 选型建议
|
||||
|
||||
好了,到这里已经介绍了六七家银行的选型情况,让我们稍稍总结一下。
|
||||
|
||||
1. 产品选型要服从于项目整体目标
|
||||
|
||||
局部最优的选择拼装在一起未必是全局最优的方案。如果你的目标是要对整个应用系统做彻底重构,例如把单体架构改为微服务架构,那么要解决原来某些局部的问题,可能会有更多选择。这时候要从整体上评估技术复杂度、工程实施等因素,而不是仅选择局部最合理的方案。
|
||||
|
||||
1. 先进的产品可能会延长项目交付时间
|
||||
|
||||
最先进的产品不一定是完美的选择。尤其是有进度要求时,往往会选择更稳妥、快速的办法。但是,这本质上是在短期利益和长期利益之间做权衡,没有绝对的对错,搞清楚你想要的是什么就行。
|
||||
|
||||
1. 当产品选型可能导致业务流程变更时,请慎重对待
|
||||
|
||||
对任何项目来说,协作范围的扩大一定会增加实施难度。当技术部门对业务流程变更没有决定权时,我认为这是多数情况,通过技术手段避免这种变更往往是更好的选择。
|
||||
|
||||
1. 产品选型中的非技术因素
|
||||
|
||||
正视非技术因素,评估它的合理性不是技术团队的职责。
|
||||
|
||||
1. 评估技术潮流对选型影响
|
||||
|
||||
跟随潮流并不是人云亦云,你必须能够独立对技术发展趋势做出研判。太过小众的技术往往不能与工程化要求兼容。但同时,保持对新技术的敏感度和掌控力,也是非常必要的。
|
||||
|
||||
## 小结
|
||||
|
||||
那么,今天的课程就到这里了,让我们梳理一下这一讲的要点。
|
||||
|
||||
1. 工商银行在主机应用下移的过程中,采用分布式中间件加MySQL的方式替换了原有的单体数据库。这个选择,一方面受制于当时分布式数据库的成熟度,另外这个方案的主要意义是大量使用了MySQL数据库,降低对主机和Oracle数据库的依赖,而分布式方案是一个副产品。
|
||||
1. 邮储银行和民生银行是在新一代核心系统建设的背景下进行分布式架构改造,所以他们有更多的项目目标,也能够承受更大的改造成本,这样分布式数据库能够平滑过渡、减少应用改造的优势也就不那么重要了。最终,两家银行都采用了类似单元化的架构,在应用层处理分布式事务等工作。
|
||||
1. 交通银行和中信银行都选择了自研方式。中信银行目前已经在核心业务系统上线GoldeDB,能够更快上线的一个原因就是PGXC的架构复用了单体数据库,遇到的技术挑战更少。
|
||||
1. 北京银行和很多规模更小的城商行也在陆续上线分布式数据库。我认为他们的选择因素有三个,国产化诉求、实际收益和技术潮流。我预测,未来还有更多的小型银行将上线分布式数据库。
|
||||
1. 光大银行采用了双路线策略,同时采用分库分表方案和NewSQL。这一方面因为不同系统的业务特点不同,另一方面也是要跟进NewSQL技术发展,保持对新技术的感知和应用能力。
|
||||
|
||||
今天的课程中,我简单总结几家银行的分布式数据库选型策略。相对于互联网行业,金融场景的苛刻要求,让银行更倾向于保守的策略,但是不难发现,总会有一些企业更具开创精神。我相信,随着分布式数据库的日益成熟,技术红利会驱使更多企业做出积极的尝试。事实上,就在我们课程更新的过程中,2020年9月,工商银行宣布将在对公(法人)理财系统的主机下移方案中采用OceanBase数据库。你看,大象也要开始跳舞了。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/da/98/da1466cc83de7092fc3b07a120622b98.jpg" alt="">
|
||||
|
||||
## 思考题
|
||||
|
||||
课程的最后,我们来看下思考题。今天的课程中,我们简单介绍了几家有代表性的银行进行分布式数据库选型的情况,也给出了一些选型建议。其实,产品选型是系统建设中非常重要的工作,也是从程序员到架构师这个成长过程中的必修课。我的问题是,你觉得针对一个新建系统做产品选型时还要考虑哪些因素呢?这个产品,并不限于数据库。
|
||||
|
||||
欢迎你在评论区留言和我一起讨论,我会在答疑篇和你继续讨论这个问题。如果你身边的朋友也对产品选型这个话题感兴趣,你也可以把今天这一讲分享给他,我们一起讨论。
|
||||
|
||||
## 学习资料
|
||||
|
||||
刘雷 等: [**分布式数据库在金融应用场景中的探索与实践**](http://www.infocomm-journal.com/bdr/CN/article/downloadArticleFile.do?attachType=PDF&id=168111).
|
||||
183
极客时间专栏/geek/分布式数据库30讲/实践篇/29 | 产品图鉴:哪些分布式数据库值得看?.md
Normal file
183
极客时间专栏/geek/分布式数据库30讲/实践篇/29 | 产品图鉴:哪些分布式数据库值得看?.md
Normal file
@@ -0,0 +1,183 @@
|
||||
<audio id="audio" title="29 | 产品图鉴:哪些分布式数据库值得看?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/42/07/4269a48bc24039dc153cc10394d04f07.mp3"></audio>
|
||||
|
||||
你好,我是王磊,你也可以叫我Ivan。
|
||||
|
||||
今天是课程正文的最后一讲,时间过得好快呀。在基础篇和开发篇,课程安排追求的是庖丁解牛那样的风格,按照[第4讲](https://time.geekbang.org/column/article/274200)提到的数据库基本架构,来逐步拆解分布式数据库系统。在介绍每一个关键部件时,我会去关联主流产品的设计,分析背后的理论依据什么,工程优化的思路又是什么。
|
||||
|
||||
这样做的好处是能够将抽象理论与具体产品对应起来,更容易理解每个设计点。但它也有一个缺点,就是产品特性被分散开来,不便于你了解整体产品。
|
||||
|
||||
为了弥补这个遗憾,今天这一讲,我会把视角切换到产品方向,为你做一次整体介绍。当然对于具体特性,这里我不再重复,而是会给出前面课程的索引。所以,你也可以将这一讲当作一个产品版的课程索引,让你在二刷这门课程时有一个崭新的视角。
|
||||
|
||||
分布式数据库产品,从架构风格上可以分为PGXC和NewSQL这两个大类,以及另外一些小众些的产品。
|
||||
|
||||
## NewSQL
|
||||
|
||||
### Spanner
|
||||
|
||||
既然要说分布式数据库产品,第一个必须是Google的Spanner。严格来说,是Spanner和F1一起开创了NewSQL风格,它是这一流派当之无愧的开山鼻祖。
|
||||
|
||||
在2012年Google论文“[F1: A Distributed SQL Database That Scales](https://storage.googleapis.com/pub-tools-public-publication-data/pdf/41344.pdf)”中首先描述了这个组合的整体架构。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/7c/3f/7ccdf211f0fc32a158fa983c36af713f.png" alt="">
|
||||
|
||||
其中F1主要作为SQL引擎,而事务一致性、复制机制、可扩展存储等特性都是由Spanner完成的,所以我们有时会忽略F1,而更多地提到Spanner。
|
||||
|
||||
Google在2012年的另一篇论文 “[Spanner: Google’s Globally-Distributed Database](http://storage.googleapis.com/pub-tools-public-publication-data/pdf/39966.pdf)”中介绍了Spanner的主要设计。
|
||||
|
||||
Spanner架构中的核心处理模块是Spanserver,下面是它的架构图。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/19/7d/198bbf1dcd7be081d3c3787ef6f09e7d.png" alt="">
|
||||
|
||||
从图中我们可以看到,Spanserver的核心工作有三部分:
|
||||
|
||||
1. 基于Paxos协议的数据复制
|
||||
1. 基于Tablet的分片管理
|
||||
1. 基于2PC的事务一致性管理
|
||||
|
||||
这三个特性的我们分别在[第6讲](https://time.geekbang.org/column/article/275696)、[第7讲](https://time.geekbang.org/column/article/277028)和[第9讲](https://time.geekbang.org/column/article/278949)做了介绍。
|
||||
|
||||
在[第5讲](https://time.geekbang.org/column/article/274908)和[第12讲](https://time.geekbang.org/column/article/281671),我们还介绍了基于全局时钟的数据一致性管理机制和处理时间误差的“写等待机制”。
|
||||
|
||||
我们都知道,软件架构会随着业务发展而演进,2017年,Google又发表了两篇新论文,介绍了Spanner和F1的最新变化。它们从原来的“金牌组合”走向了“单飞”模式。
|
||||
|
||||
Spanner的论文是“[Spanner: Becoming a SQL System](http://www.cs.ucf.edu/~kienhua/classes/COP5711/Papers/Google2017.pdf)”。就像论文名字所说的,Spanner完善了SQL功能,这样就算不借助F1,也能成为一个完整的数据库。
|
||||
|
||||
这篇论文用大量篇幅介绍了SQL处理机制,同时在系统定位上相比2012版有一个大的变化,强调了兼容OLTP和OLAP,也就是HTAP。对应的,Spanner在存储层的设计也从2012版中的CFS切换到了Ressi。Ressi是类似PAX的行列混合数据布局(Data Layout),我们在[第18讲](https://time.geekbang.org/column/article/287246)专门谈了对HTAP未来发展的看法,并对各种不同的数据布局进行了分析。
|
||||
|
||||
F1的新论文是“[F1 Query: Declarative Querying at Scale](http://vldb.org/pvldb/vol11/p1835-samwel.pdf)”。这一版论文中F1不再强调和Spanner的绑定关系,而是支持更多的底层存储。非常有意思的是,F1也声称自己可以兼顾OLTP和OLAP。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/52/10/526ddab4467b1fb7a05be01369f98010.png" alt="">
|
||||
|
||||
这个架构中还有一个我们很感兴趣的点,就是F1通过UDF Server来实现存储过程的支持。我们在[第16讲](https://time.geekbang.org/column/article/285270)中对此进行了简单的探讨。
|
||||
|
||||
### CockroachDB
|
||||
|
||||
按照时间顺序,在Spanner之后出现的NewSQL产品是CockroachDB。CockroachDB和TiDB、YugabyteDB都公开声称设计灵感来自Spanner,所以往往会被认为是同构的产品。尤其是CockroachDB和TiDB,经常会被大家拿来比较。但是,从系统架构上看,这两个产品有非常大的差别。让我们先从CockroachDB角度来总结下。
|
||||
|
||||
最大的差别来自架构的整体风格。CockroachDB采用了标准的P2P架构,这是一个非常极客的设计。只有P2P架构能够做到绝对的无中心,这意味着只要损坏的节点不超过总数一半,那么集群就仍然可以正常工作。因此,CockroachDB具有超强的生存能力,而这也很符合产品名称的语义。
|
||||
|
||||
第二个重要差异是全球化部署。CockroachDB采用了混合逻辑时钟(HLC),所以能够在全球物理范围下做到数据一致性。这一点对标了Spanner的特性,不同之处是Spanner的TrueTime是依赖硬件的,而HLC机制完全基于软件实现。我在[第5讲](https://time.geekbang.org/column/article/274908)对它的设计做了深入的分析,而对于HLC的理论基础Lamport时钟,我在[第2讲](https://time.geekbang.org/column/article/272104)中也做了介绍。
|
||||
|
||||
第三个点则是分片管理机制的不同。因为整体架构的差异,CockroachDB在分片管理上也跟TiDB有明显的区别,我们在[第6讲](https://time.geekbang.org/column/article/275696)中做了介绍。
|
||||
|
||||
另外,我还在[第10讲](https://time.geekbang.org/column/article/279660)介绍了CockroachDB的2PC优化,[第11讲](https://time.geekbang.org/column/article/280925)介绍了CockroachDB的读写隔离策略,[第12讲](https://time.geekbang.org/column/article/281671)介绍了如何用读等待方式解决时间误差问题。
|
||||
|
||||
2020年,CockroachDB发表的论文“[CockroachDB: The Resilient Geo-DistributedSQL Database](https://dl.acm.org/doi/pdf/10.1145/3318464.3386134)”被SIGMOD收录。这篇论文对CockroachDB的架构设计做了比较全面的介绍,非常值得你仔细阅读。
|
||||
|
||||
### TiDB
|
||||
|
||||
TiDB也是对标Spanner的NewSQL数据库,因为开源的运行方式和良好的社区运营,它在工程师群体中拥有很高的人气。
|
||||
|
||||
不同于CockroachDB的P2P架构,TiDB采用了分层架构,由TiDB、TiKV和PD三类角色节点构成,TiKV作为底层分布式键值存储,TiDB作为SQL引擎,PD承担元数据管理和全局时钟的职责。
|
||||
|
||||
与Spanner不同的是,底层存储TiKV并不能独立支持事务,而是通过TiDB协调实现,事务控制模型采用了Percolator。我们在[第9讲](https://time.geekbang.org/column/article/278949)和[第13讲](https://time.geekbang.org/column/article/282401)介绍了TiDB的事务模型。
|
||||
|
||||
作为与CockroachDB的另一个显著区别,TiDB更加坚定的走向HTAP,在原有架构上拓展TiSpark和TiFlash,在[第18讲](https://time.geekbang.org/column/article/287246)我们介绍了这部分的设计。同时,TiDB对于周边生态工具建设投入了大量资源,由此诞生了一些衍生项目:
|
||||
|
||||
- Ti-Binlog和Ti-CDC可以将数据导出,构建逃生通道或者实现数据分析。
|
||||
- Ti-Operator可以更方便的实现容器云部署
|
||||
- Chaos Mesh支持混沌工程
|
||||
|
||||
[第25讲](https://time.geekbang.org/column/article/293722)、[第26讲](https://time.geekbang.org/column/article/293901)和[第27讲](https://time.geekbang.org/column/article/295039)的内容与上述项目具有直接的对应关系。这些项目的创立,丰富了TiDB的服务交付方式,也使TiDB的产品线变得更长。但是它们否都有很好的发展前景,还有待观察。
|
||||
|
||||
当然,TiDB架构也存在一些明显的缺陷,比如不支持全球化部署,这为跨地域大规模集群应用TiDB设置了障碍。
|
||||
|
||||
与CockroachDB一样,TiDB在2020年也发布了一篇论文“[TiDB, A Raft-based HTAP Database](http://www.vldb.org/pvldb/vol13/p3072-huang.pdf)”被VLDB收录,论文全面介绍了TiDB的架构设计,同样推荐你仔细阅读。
|
||||
|
||||
SIGMOD和VLDB是数据库领域公认的两大顶会,而TiDB和CockroachDB先后发表产品论文,颇有一时瑜亮的感觉。
|
||||
|
||||
### YugabyteDB
|
||||
|
||||
YugabyteDB是较晚推出的NewSQL数据库,在架构上和CockroachDB有很多相似之处,比如支持全球化部署,采用混合逻辑时钟(HLC),基于Percolator的事务模型,兼容PostgreSQL协议。所以,课程中对CockroachDB的介绍会帮助你快速了解YugabyteDB。
|
||||
|
||||
为数不多的差异是,YugabyteDB选择直接复用PostgreSQL的部分代码,所以它的语法兼容性更好。
|
||||
|
||||
可能是由于高度的相似性,YugabyteDB与CockroachDB的竞争表现得更加激烈。YugabyteDB率先抛出了产品比对测试,证明自己处理性能全面领先,这引发了CockroachDB的反击,随后双方不断回应。我们在[第17讲](https://time.geekbang.org/column/article/285819)引用了这场论战中的部分内容。如果你想了解更多内容可以查看的相关博客。
|
||||
|
||||
### OceanBase
|
||||
|
||||
从历史沿革看,OceanBase诞生的时间可以追溯到2010年,但是那时产品形态是KV存储,直到在1.0版本后才确立了目前的产品架构。OceanBase大体上也是P2P架构,但会多出一个Proxy层。
|
||||
|
||||
由于OceanBase是一款商业软件,所以对外披露的信息比较有限,我们的课程中在并行执行框架、查询引擎和存储模型三部分对OceanBase做了一些介绍,分别对应[第20讲](https://time.geekbang.org/column/article/289299)、[第21讲](https://time.geekbang.org/column/article/289971)和[第22讲](https://time.geekbang.org/column/article/291009)。期待OceanBase团队能够放出更多有价值的材料。
|
||||
|
||||
## PGXC
|
||||
|
||||
PGXC使用单体数据库作为数据节点,在架构上的创新远少于NewSQL,所以我们在课程内容上所占篇幅也较少,而且是作为一个整体风格进行介绍。在第3讲,我们从单体数据库的隔离级别引申到PGXC的隔离性协议。第4讲,我们详细拆解了PGXC的架构,也就是协调节点、数据节点、全局时钟和元数据管理等四个部分。第6讲,我们介绍了PGXC的分片机制。还有一些特性,例如数据复制是继承自单体数据库。事实上,有关单体数据库实现的说明都对了解PGXC有所帮助。
|
||||
|
||||
### TBase
|
||||
|
||||
TBase是最标准的PGXC,采用PostgreSQL作为数据节点。但TBase推出的时间较晚,应用案例也相对较少。从一些宣传资料看,TBase更加强调HTAP的属性。但考虑到TBase与TDSQL都是腾讯出品,我认为这或许是出于商业策略的考虑,毕竟从架构本身看,TBase与TDSQL的差异是比较有限的。
|
||||
|
||||
### TDSQL
|
||||
|
||||
TDSQL是腾讯公司内部最早的分布式数据库,它的数据节点选择了MySQL。我曾经提到过,TDSQL目前的主推版本并没有实现全局时钟,这意味着它在数据一致性上是存在缺失的。所以严格意义上说,它并不是分布式数据库,当然我们也可以通过一些公开信息了解到TDSQL在一致性方面的努力,相信完善这部分功能应该只是时间问题。
|
||||
|
||||
### GoldenDB
|
||||
|
||||
GoldenDB几乎是国内银行业应用规模最大的分布式数据库,和TDSQL同样在数据节点上选择了MySQL,但全局时钟节点的增加使它称为一个标准的PGXC架构。
|
||||
|
||||
GoldenDB对事务模型进行了改造,我们在[第9讲](https://time.geekbang.org/column/article/278949)介绍了它的分布式事务模型“一阶段提交”。
|
||||
|
||||
分库分表方案是一个长期流行的方案,有各种同质化产品,所以进一步演化出多少种PGXC风格的数据库很难历数清楚。借助单体数据库的优势,无疑会发展的更加快捷,但始终存在一个隐患。那就是单体数据库的许可证问题,尤其是那些选择MySQL作为数据节点的商业数据库。
|
||||
|
||||
MySQL采用的GPL协议,这意味着不允许修改后和衍生的代码作为商业化软件发布和销售,甚至是只要采用了开源软件的接口和库都必须开放源码,否则将面对很大的法律风险。
|
||||
|
||||
## Others
|
||||
|
||||
除了以上两种主流分布式数据库外,还有一些小众产品。虽然它们的使用不那么广泛也,但也很有特点。
|
||||
|
||||
### VoltDB
|
||||
|
||||
VoltDB一度也是开源数据库,但在2019年正式闭源,变为纯商业化产品。而同时,VoltDB在国内也没有建立完备的服务支持体系,这在很大程度上影响到它的推广。另外,VoltDB虽然支持OLTP场景,但在国内的落地项目中多用于实时分析场景,例如金融反欺诈等。
|
||||
|
||||
VoltDB的主要特点是完全基于内存的分布式数据库,使用存储过程封装业务逻辑,采用单线程方式简化了事务模型。我们在[第16讲](https://time.geekbang.org/column/article/285270)对VoltDB做了简单介绍。
|
||||
|
||||
### SequoiaDB
|
||||
|
||||
巨杉数据库(SquoiadDB)在早期并不支持完整事务,所以应用场景主要是归档数据和影像数据存储,而后从3.0版本开始逐步过渡到完整的OLTP分布式数据库。我们在[第4讲](https://time.geekbang.org/column/article/274200)介绍了巨杉的全局时钟实现方式,就是它在完善事务一致性方面的重大进展。
|
||||
|
||||
巨杉的架构其实跟MySQL架构非常相似,也分为SQL引擎和存储引擎上下两层。巨杉在上层直接复用了MySQL的SQL引擎,下层则使用自己的分布式存储引擎替换了InnoDB。这种架构设计意味着巨杉可以非常好地兼容MySQL语法,就像YugabyteDB兼容PostgreSQL那样。
|
||||
|
||||
巨杉支持的还不只MySQL,事实上它已经逐渐发展为一款多模数据库,同时兼容MySQL、PostgreSQL、SparkSQL,并支持Json类型数据部分兼容MongoDB,和S3对象存储等。
|
||||
|
||||
## 小结
|
||||
|
||||
那么,今天的课程就到这里了,让我们梳理一下这一讲的要点。
|
||||
|
||||
<li>
|
||||
2012年Google发表的两篇论文奠定了Spanner/F1作为NewSQL数据库开山鼻祖的地位。因为其中存储引擎、复制机制、分布式事务都在Spanner中实现,所以大家有时会略去F1。而后,Spanner演进为一个自带SQL引擎的完整数据库,并且同时兼顾OLAP和OLTP场景。
|
||||
</li>
|
||||
<li>
|
||||
CockroachDB与TiDB都是Github上非常热门的项目,设计灵感均来自Spanner。虽然两者在部分设计上采用了相同的策略,例如引入RocksDB、支持Raft协议等,但在很多重要特性上仍有很大差距,例如全球化部署、时钟机制、分片管理、HTAP支持程度等。
|
||||
</li>
|
||||
<li>
|
||||
YugabyteDB与CockroachDB具有更大的相似性,导致两者间的竞争更加激烈。OceanBase作为阿里的一款自研软件,整体风格上接近于NewSQL,所以很多设计在原理上完全相同的。但由于商用软件的关系,开放的资料上远少于其他NewSQL数据库。
|
||||
</li>
|
||||
<li>
|
||||
PGXC数据库是从分库分表方案上发展而来,而这一步跨越的关键就是通过全局时钟支持更严格的数据一致性和事务一致性。PGXC具有架构稳定的优势,往往被视为更稳妥的方案,但单体数据库的软件许可证始终是PGXC架构商业数据库一个很大的法律隐患。
|
||||
</li>
|
||||
<li>
|
||||
VoltDB和巨杉数据库是小众一些的数据库,在设计上采用了较为独特的方式,从而也带来了差异化的特性。
|
||||
</li>
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/9e/74/9ea0a85498f3e0d87cbe2eb6d676ce74.jpg" alt="">
|
||||
|
||||
## 思考题
|
||||
|
||||
课程的最后,我们来看下思考题。今天,我们简要总结了课程中提到的各类分布式数据库的特点。但是近年来,学术界对分布式数据库的研究非常活跃,工业实践的热潮也日益高涨,短短的30讲真的难以历数。所以,我的问题是,除了上面提到的数据库之外,你还了解哪些有特点的分布式数据库吗?提示一下,在课程中出现过的至少还有两种。
|
||||
|
||||
欢迎你在评论区留言和我一起讨论,我会在答疑篇和你继续讨论这个问题。如果你身边的朋友想快速了解分布式数据库都有哪些产品,你可以把今天这一讲分享给他,可能会帮他更高效的锁定产品,期待你的朋友们也一起加入我们的讨论。
|
||||
|
||||
## 学习资料
|
||||
|
||||
Bart Samwel et al: [**F1 Query: Declarative Querying at Scale**](http://vldb.org/pvldb/vol11/p1835-samwel.pdf)
|
||||
|
||||
David F. Bacon et al: [**Spanner: Becoming a SQL System**](http://www.cs.ucf.edu/~kienhua/classes/COP5711/Papers/Google2017.pdf)
|
||||
|
||||
Dongxu Huang et al.: [**TiDB, A Raft-based HTAP Database**](http://www.vldb.org/pvldb/vol13/p3072-huang.pdf)
|
||||
|
||||
Jeff Shute et al.: [**F1: A Distributed SQL Database That Scales**](https://storage.googleapis.com/pub-tools-public-publication-data/pdf/41344.pdf)
|
||||
|
||||
James C. Corbett et al.: [**Spanner: Google’s Globally-Distributed Database**](http://storage.googleapis.com/pub-tools-public-publication-data/pdf/39966.pdf)
|
||||
|
||||
Rebecca Taft et al.: [**CockroachDB: The Resilient Geo-DistributedSQL Database**](https://dl.acm.org/doi/pdf/10.1145/3318464.3386134)
|
||||
156
极客时间专栏/geek/分布式数据库30讲/实践篇/30 | 实践篇大串讲:重难点回顾+思考题答疑+知识全景图.md
Normal file
156
极客时间专栏/geek/分布式数据库30讲/实践篇/30 | 实践篇大串讲:重难点回顾+思考题答疑+知识全景图.md
Normal file
@@ -0,0 +1,156 @@
|
||||
<audio id="audio" title="30 | 实践篇大串讲:重难点回顾+思考题答疑+知识全景图" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/6c/a7/6c0cf4728922589f9159a5fddac3f0a7.mp3"></audio>
|
||||
|
||||
你好,我是王磊。
|
||||
|
||||
今天这一讲是我们课程的最后一个答疑篇。我会回顾第24讲到第29讲的主要内容,这部分内容是跳出数据库的架构设计,从应用系统的整体视角展开的。接下来,我照例会集中解答留给大家思考题,同时也会回复一些大家关注的热点内容。
|
||||
|
||||
## 第24讲:全球化部署
|
||||
|
||||
[第24讲](https://time.geekbang.org/column/article/293251)的主题是全球化部署,更接地气的说法就是“异地多活”。
|
||||
|
||||
异地多活的目标是保证在区域级灾难事件的发生时,关键业务仍然能够持续开展。其实,异地多活一直是高可用架构所追求的目标,它的难点是有状态服务的处理,尤其是数据库。在实践中,有好几种基于单体数据库的方案,但它们都有局限性,无法实现“永不宕机”和“近在咫尺”这两点要求。
|
||||
|
||||
分布式数据库基于新的架构设计思想,是有条件达成这两点的。
|
||||
|
||||
实现“永不宕机”的前提是让主副本可以在异地机房之间的漂移,这就对全局时钟有更高的要求,必须做到多时间源、多点授时。目前能够支持的产品有Spanner、CockroachDB和YugabyteDB,而采用单点授时的产品是无法支持的,比如TiDB、OceanBase以及PGXC风格的数据库。
|
||||
|
||||
而实现“近在咫尺”则要做到两点:
|
||||
|
||||
1. 让主本数据能够主动漂移到用户侧机房,降低写操作的延迟。
|
||||
1. 使用就近的副本提供读服务,也就是Follower Read功能。
|
||||
|
||||
关于第二点,目前还没看到完全成熟的方案,难点在于如何保持副本数据的新鲜度,从而避免访问主副本带来的延迟。目前,已经有一些产品尝试通过副本与主本、元数据管理节点间的时间戳同步,降低对主本的依赖,保持副本数据的新鲜度。
|
||||
|
||||
最后,分布式数据库的多副本机制在实践中也存在一些缺陷。我们知道Raft或者Paxos都是多数派协议。按照协议原理,当出现网络分区时,在任何一个联通的子网络中,节点数量必须大于总节点数的一半才能选举出新的Leader,从而继续对外服务。
|
||||
|
||||
那么,在两地三中心或三地五机房模式下,如果机房间网络全部中断,即使主机房节点全部正常也不能提供服务。这是因为考虑到RPO为零的目标,主机房的节点通常不会超过半数。这意味着,三机房或五机房的部署方案都会让机房间的网络成为易受到外来攻击的风险点,从而数据库变得更加脆弱。
|
||||
|
||||
这一讲的思考题是“课程中提到了Raft协议降级处理,它允许数据库在仅保留少数副本的情况下,仍然可以继续对外提供服务。这和标准Raft显然是不同的,你觉得应该如何设计这种降级机制呢?”
|
||||
|
||||
这个机制并不复杂。首先是固定主副本的位置,只有主机房的副本才能被选举为Leader,这样就能保证主机房的数据足够新;其次是引入一个“低水位线”的概念,约定节点数量的下限,允许节点数量少于半数但高于下限时,仍然可以对外提供服务。
|
||||
|
||||
事实上,这两点不单是理论探讨。第一点在很多分布式数据库的实际应用中都有实现,因为这种约束本身就能降低运维的复杂度;第二点在GoldenDB等数据库中已经可以看到类似的设计。
|
||||
|
||||
## 第25讲:逃生通道
|
||||
|
||||
[第25讲](https://time.geekbang.org/column/article/293722)的关键词是逃生通道。逃生通道本质上是一个异构高可用方案,这种设计并不常见,但在分布式数据库的应用中是一个普遍需求。背后的原因是,数据库必须实现高可靠,而分布式数据库本身的成熟度不足以让用户安心,需要用更成熟的单体数据库做兜底方案。
|
||||
|
||||
高可靠方案的核心是如何将变更信息流推送给单体数据库,这个过程中会面临三个问题。其中性能适配和日志适配这两个问题相对容易处理;第三个问题是实现逃生库的事务一致性,要在变更信息流中添加特殊的时间戳消息,用来标识消息的完整性。
|
||||
|
||||
这一讲的是思考题是“对单个数据分片来说 WAL 本身就是有序的,直接开放就可以提供顺序一致的变更消息。而逃生通道作为一个异构高可用方案,往往会使用Kafka这样的分布式消息队列。那么单分片的变更消息流在逃生通道中还能保证顺序一致吗?”
|
||||
|
||||
答案是不能保证顺序一致,原因在于Kafka的分布式架构设计。
|
||||
|
||||
Kafka按照Topic组织消息,而为了提升性能,一个Topic会包含多个Partition,分布到不同节点(Broker)。那么,所有发送到Kafka的消息,实际上是会按照一定的负载均衡策略发送到不同的Broker上。
|
||||
|
||||
这样的设计意味着,在Broker内部消息是有序的,但多个Broker之间消息是无序的。作为消息的消费者,即使接收的只是单个分片的变更消息流,也不能用当前消息的时间戳来判定小于这个时间戳的消息已经发送完毕。
|
||||
|
||||
## 第26讲:容器化
|
||||
|
||||
在[第26讲](https://time.geekbang.org/column/article/293901)中,我们讨论了分布式数据库进行容器化部署的可行性。其中的核心问题就是Kubernetes对有状态服务的支持情况。
|
||||
|
||||
StatefulSet是有状态服务的核心对象,我们围绕着它介绍了对应持久卷(Persistent Volume)特性的变化。随着Kubernetes1.14版的发布,基于本地磁盘的本地持久卷(Local Persistent Volume)已经达到生产级要求,有望彻底解决数据库容器化部署最大的障碍,I/O性能问题。
|
||||
|
||||
分布式数据库本身服务的复杂性也是不容忽视的问题。通过Kubernetes自带的简单协调机制很难定义产品级的管理策略。所以,Kubernetes提供了Operator这种扩展机制,让每个产品可以自行定义控制策略。目前,有不少分布式系统开发了自己的Operator。
|
||||
|
||||
这一讲的思考题是“ 资源调度是Kubernetes 的一项核心功能,那么除了 Kubernetes 你还知道哪些集群资源调度系统?它们在设计上有什么差异吗?”
|
||||
|
||||
随着很多基础系统向分布式架构过渡,集群资源调度成为一个非常广泛的需求,尤其是数据密集型系统。除Kubernetes外,知名度最高的可能就是Yarn和Mesos,它们都是大数据生态体系下的工具。
|
||||
|
||||
Yarn是Hadoop体系下的核心组件,被称为“数据操作系统”,所调度的资源单位和Docker有些相似,比如也使用了Cgroup隔离资源。Mesos更是直接从大数据领域杀入容器编排领域,成为Kubernetes的直接竞争对手。
|
||||
|
||||
## 第27讲:产品测试
|
||||
|
||||
[第27讲](https://time.geekbang.org/column/article/295039)中,我们谈的核心内容是测试。测试是保证软件质量的重要手段,而对于分布式数据库来说测试的难度更大,也更为重要。我们先后介绍了TPC-C、Jepsen和混沌工程三种测试方式。
|
||||
|
||||
TPC-C是由国际事务性能委员会发布的、针对OLTP数据库的测试规范,已经被业界广泛接受。
|
||||
|
||||
对于分布式数据库来说,是否正确实现了数据和事务的一致性也是测试的关键。Jepsen是针对这类测试的权威工具,很多知名的分布式存储系统购买了Jepsen的测试服务。
|
||||
|
||||
混沌工程和Jepsen一样,都是通过注入底层故障的方式进行测试。但混沌工程的测试对象更广泛,涵盖了所有的分布式系统。同时,混沌工程是一种不同的测试文化,强调在生产环境注入故障,在受控的范围内观测系统,体现了反脆弱的思想。
|
||||
|
||||
最后,所有的测试都是在证伪,只能发现错误,不能证明正确性。而形式化验证弥补了这个缺憾,提供了证明的方法。在软件工程领域,Lamport发明的TLA,衍生出一系列方法、工具甚至编程语言,使我们可以用更严谨的方式确认逻辑的正确性。
|
||||
|
||||
这一讲的思考题是“除了分布式数据库,对于其他类型的分布式存储系统,你知道有哪些主流的测试工具吗?”
|
||||
|
||||
由于分布式系统的复杂性,测试工具就显得更加重要。除数据库外,比较典型是针对分布式键值系统的测试工具,例如YCSB。YCSB(Yahoo! Cloud Serving Benchmark)是一个开源的测试框架,你可以从Github上下载到源码。
|
||||
|
||||
YCSB支持几乎所有的主流分布式键值系统,包含HBase、Redis、Cassandra和BigTable等。YCSB支持典型的PUT\GET\SCAN操作,你可以很容易地在它的基础上扩展,增加对其他键值系统的支持。
|
||||
|
||||
## 第28讲:选型案例
|
||||
|
||||
在[第28讲](https://time.geekbang.org/column/article/295796),我们讨论的话题是如何进行分布式数据库产品选型。因为对于数据库产品来说,金融场景是公认的试金石,所以我们这一讲主要介绍了银行业的选型情况。
|
||||
|
||||
总的来说,银行的态度分为三种。
|
||||
|
||||
最保守的方案是采用分库分表,甚至单元化的方案,在应用层付出更大的代价,而在数据库层沿用单体数据库,保持充分的稳定性。这种方式的前提是必须有足够的业务驱动力,才能推动应用系统进行重大的调整。
|
||||
|
||||
第二种方式是自研数据库,周期长、投入大,但可以得到更加切合自身的解决方案。PGXC数据库的难度较低,所以推进更快。
|
||||
|
||||
第三种方式是采购分布式数据库。目前随着技术的成熟,这种模式越来越普遍,甚至一些业务量较小的城商行也上线分布式数据库。
|
||||
|
||||
这一讲的思考题是“产品选型是系统建设中非常重要的工作,你觉得针对一个新建系统做产品选型时还要考虑哪些因素呢?这个产品,并不限于数据库?”
|
||||
|
||||
对于分布式数据库的选型,我认为最重要的是分析业务场景对于事务和查询方面的要求。事实上,这两部分内容也占据了我们课程的大半。在实践中,有的海量并发业务其实并没有相关性,也就是说,不同事务间数据重叠的概率非常低,这时就可以考虑分库分表方案。不过,多数的分库分表方案只能对数据做单向的路由分发,如果有跨分片的查询需求则很难满足。虽然,也可以通过CDC等工具导出到分析型系统实现这一点,但这时就要平衡系统的整体复杂度了。
|
||||
|
||||
跳出具体技术,我认为产品选型要结合具体项目目标,选择尽量少的产品或技术组件,尽量不采用同质化的多种技术,让架构更加简洁和优雅。
|
||||
|
||||
## 第29讲:产品图鉴
|
||||
|
||||
[第29讲](https://time.geekbang.org/column/article/296558),我们转换到了产品视角,对课程内容做了一次完整的回顾。
|
||||
|
||||
我相信,很多同学都会有这样的问题:哪些分布式数据库更有发展,值得花时间学习?
|
||||
|
||||
这一讲,我根据个人经验列举了常见的十款数据库产品,并给出了相关内容在课程中对应的位置,方便你快速查找。
|
||||
|
||||
谈到产品,我们还是依据[第4讲](https://time.geekbang.org/column/article/274200)的分析框架将产品分为三类,NewSQL、PGXC和其他。其中NewSQL是我们课程的重点,原因在于它体现了学术界和工业界近年来的很多创新。我们以Spanner和F1为基础,进行了比较完整的说明,并在此基础上介绍了其他四种NewSQL数据库的特点。
|
||||
|
||||
作为另一个主要流派,PGXC是从分库分表方案演进而来的,演进过程的里程碑就是全局时钟。因为PGXC更加依赖单体数据库,技术门槛相对较低,所以产品数量就较多,很难全部列举。最终,我们只挑选了比较典型的三款产品。PGXC虽然在架构上更加稳健,但部分单体数据库的许可证要求基于其开发的软件也必须开源,所以对于没有按照这一要求执行的商业产品来说,始终存在着法律风险。
|
||||
|
||||
最后,作为小众产品的代表,我们简述了VoltDB和巨杉数据库。它们也都是各种产品评测中的常客,但是由于各种原因,应用案例会相对少些。在一些特定场景下,这些产品也是重要的备选项。
|
||||
|
||||
这一讲的思考题是“除了第29讲提到的数据库之外,你还了解哪些有特点的分布式数据库吗?”
|
||||
|
||||
我在课程中还提到过两种不同的分布式数据库,分别是FoundationDB和FaunaDB。最早,
|
||||
|
||||
FoundationDB是一个开源项目,而后被苹果收购后闭源,2018年又重新开源。严格来说,它是一个支持ACID语义的NoSQL数据库,有比较独特的乐观并发控制。FoundationDB可以通过上层的扩展可以支持更多的场景,而在增加了Record Layer后,它就成为一个关系型数据库,不过还不支持SQL接口。总的来说,FoundationDB值得我们持续关注。
|
||||
|
||||
对于FaunaDB,可能了解的人更少些。它是一款商业数据库,从NoSQL逐渐过渡成为分布式数据库。FaunaDB的理论原型是Calvin,它和Spanner一样在2012年发表了[原型论文](https://dsf.berkeley.edu/cs286/papers/calvin-sigmod2012.pdf),被SIGMOD收录。虽然它们的目标都是提供强一致性的分布式关系型数据库,但设计思路截然不同。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/f0/yy/f0d88ccdc1d056793368a91396ef81yy.png" alt="">
|
||||
|
||||
在Calvin的架构中设计了Sequencer和Scheduler两个组件。
|
||||
|
||||
其中Sequencer是基于锁机制为输入的事务操作进行排序,这样在事务真正执行前就能获得确定性的顺序,避免了过程中的无效交互和资源冲突。Scheduler则是按照这个顺序执行,调度不同的事务执行线程完成最终操作。
|
||||
|
||||
这个设计思路被称为确定性并发控制,对应的数据库则称为确定性数据库(Deterministic Database)。
|
||||
|
||||
确定性并发控制算法的基本思路是,确保不同的副本始终能够获得相同的输入,所以就能独立地产生相同的结果,从而避免使用开销更大的提交协议和复制协议。通常,这类算法可以降低协调工作的通信开销,提高分布式事务的处理效率。而它的代价之一是无法为客户端提供一个交互操作过程,这就限制了它的使用场景。
|
||||
|
||||
目前基于Calvin理论模型的工业产品,似乎只有FaunaDB。作为一种有代表性的分布式数据库,它值得我们继续关注。
|
||||
|
||||
此外,确定性数据库也是学术领域的重要研究方向。VLDB2020收录的一篇论文“[Aria: A Fast and Practical Deterministic OLTP Database](http://www.vldb.org/pvldb/vol13/p2047-lu.pdf)”,就探讨了对确定性控制算法的优化方案,如果你有兴趣可以仔细研究下。
|
||||
|
||||
## 小结
|
||||
|
||||
最后,我想把这30讲的组织方式总结一下。
|
||||
|
||||
在基础篇,我重点铺垫了数据库和分布式架构的基本概念,这些内容可以独立成篇,阅读难度相对较低。
|
||||
|
||||
在开发篇,我们一起深入到分布式数据库的内部,对关键设计进行拆解,这一部分涉及大量的学术论文和工程实践。其中,事务和查询无疑是两座高峰,为了你有个歇脚喘气的地方,我在中间也穿插了一些相对简单的内容。
|
||||
|
||||
最后的实践篇,其实已经跳出数据库的范畴。这一部分的话题主要是围绕应用系统建设的整体视角展开,目的是希望将课程与你的日常工作衔接起来。
|
||||
|
||||
对于分布式数据库来说,30讲的篇幅还是很短的,有些原理可能还没有完全说透,还有些有趣的东西或许被遗漏了。不过,这并不要紧,因为课程虽然结束了,但我们的交流还在继续。
|
||||
|
||||
如果你对课程任何内容有疑问,欢迎在评论区留言和我一起讨论。要是你身边的朋友也对分布式数据库感兴趣,你也可以把这门课程分享给他,我们一起讨论。
|
||||
|
||||
## 分布式数据全景图4/4
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/c5/06/c58730d735226f2f6164e88f6d3bfb06.jpg" alt="">
|
||||
|
||||
## 学习资料
|
||||
|
||||
Alexander Thomson et al.: [**Calvin: Fast Distributed Transactions for Partitioned Database Systems**](https://dsf.berkeley.edu/cs286/papers/calvin-sigmod2012.pdf)
|
||||
|
||||
Yi Lu et al.: [**Aria: A Fast and Practical Deterministic OLTP Database**](http://www.vldb.org/pvldb/vol13/p2047-lu.pdf)
|
||||
Reference in New Issue
Block a user