20 | 如何在不停机的情况下,安全地更换数据库?

随着我们的系统规模逐渐增长,总会遇到需要更换数据库的问题。我们来说几种常见的情况。
对 MySQL 做了分库分表之后,需要从原来的单实例数据库迁移到新的数据库集群上。
系统从传统部署方式向云上迁移的时候,也需要从自建的数据库迁移到云数据库上。
一些在线分析类的系统,MySQL 性能不够用的时候,就需要更换成一些专门的分析类数据库,比如说 HBase。
更换数据库这个事儿,是一个非常大的技术挑战,因为我们需要保证整个迁移过程中,既不能长时间停服,也不能丢数据。
那么,今天这节课我们就来说一下,如何在不停机的情况下,安全地迁移数据更换数据库。

如何实现不停机更换数据库?

我们都知道墨菲定律:“如果事情有变坏的可能,不管这种可能性有多小,它总会发生。”放到这里呢,也就是说,我们在更换数据库的过程中,只要有一点儿可能会出问题的地方,哪怕是出现问题的概率非常小,它总会出问题。
实际上,无论是新版本的程序,还是新的数据库,即使我们做了严格的验证测试,做了高可用方案,刚刚上线的系统,它的稳定性总是没有那么好的,需要一个磨合的过程,才能逐步达到一个稳定的状态,这是一个客观规律。这个过程中一旦出现故障,如果不能及时恢复,造成的损失往往是我们承担不起的。
所以我们在设计迁移方案的时候,一定要做到,每一步都是可逆的。要保证,每执行一个步骤后,一旦出现问题,能快速地回滚到上一个步骤。这是很多同学在设计这种升级类技术方案的时候,容易忽略的问题。
接下来我们还是以订单库为例子,说一下这个迁移方案应该如何来设计。
首先要做的就是,把旧库的数据复制到新库中。因为旧库还在服务线上业务,所以不断会有订单数据写入旧库,我们不仅要往新库复制数据,还要保证新旧两个库的数据是实时同步的。所以,我们需要用一个同步程序来实现新旧两个数据库实时同步。
怎么来实现两个异构数据库之间的数据实时同步,这个方法我们上节课刚刚讲过,我们可以使用 Binlog 实时同步数据。如果源库不是 MySQL 的话,就麻烦一点儿,但也可以参考我们讲过的,复制状态机理论来实现。这一步不需要回滚,原因是,只增加了一个新库和一个同步程序,对系统的旧库和程序都没有任何改变。即使新上线的同步程序影响到了旧库,只要停掉同步程序就可以了。
然后,我们需要改造一下订单服务,业务逻辑部分不需要变,DAO 层需要做如下改造:
 
支持双写新旧两个库,并且预留热切换开关,能通过开关控制三种写状态:只写旧库、只写新库和同步双写。
 
支持读新旧两个库,同样预留热切换开关,控制读旧库还是新库。
然后上线新版的订单服务,这个时候订单服务仍然是只读写旧库,不读写新库。让这个新版的订单服务需要稳定运行至少一到二周的时间,期间除了验证新版订单服务的稳定性以外,还要验证新旧两个订单库中的数据是否是一致的。这个过程中,如果新版订单服务有问题,可以立即下线新版订单服务,回滚到旧版本的订单服务。
稳定一段时间之后,就可以开启订单服务的双写开关了。开启双写开关的同时,需要停掉同步程序。这里面有一个问题需要注意一下,就是这个双写的业务逻辑,一定是先写旧库,再写新库,并且以写旧库的结果为准
旧库写成功,新库写失败,返回写成功,但这个时候要记录日志,后续我们会用到这个日志来验证新库是否还有问题。旧库写失败,直接返回失败,就不写新库了。这么做的原因是,不能让新库影响到现有业务的可用性和数据准确性。上面这个过程如果出现问题,可以关闭双写,回滚到只读写旧库的状态。
切换到双写之后,新库与旧库的数据可能会存在不一致的情况,原因有两个:一是停止同步程序和开启双写,这两个过程很难做到无缝衔接,二是双写的策略也不保证新旧库强一致,这时候我们需要上线一个对比和补偿的程序,这个程序对比旧库最近的数据变更,然后检查新库中的数据是否一致,如果不一致,还要进行补偿。
开启双写后,还需要至少稳定运行至少几周的时间,并且期间我们要不断地检查,确保不能有旧库写成功,新库写失败的情况出现。对比程序也没有发现新旧两个库的数据有不一致的情况,这个时候,我们就可以认为,新旧两个库的数据是一直保持同步的。
接下来就可以用类似灰度发布的方式,把读请求一点儿一点儿地切到新库上。同样,期间如果出问题的话,可以再切回旧库。全部读请求都切换到新库上之后,这个时候其实读写请求就已经都切换到新库上了,实际的切换已经完成了,但还有后续的收尾步骤。
再稳定一段时间之后,就可以停掉对比程序,把订单服务的写状态改为只写新库。到这里,旧库就可以下线了。注意,整个迁移过程中,只有这个步骤是不可逆的。但是,这步的主要操作就是摘掉已经不再使用的旧库,对于在用的新库并没有什么改变,实际出问题的可能性已经非常小了。
到这里,我们就完成了在线更换数据库的全部流程。双写版本的订单服务也就完成了它的历史使命,可以在下一次升级订单服务版本的时候,下线双写功能。

如何实现对比和补偿程序?

在上面的整个切换过程中,如何实现这个对比和补偿程序,是整个这个切换设计方案中的一个难点。这个对比和补偿程序的难度在于,我们要对比的是两个都在随时变换的数据库中的数据。这种情况下,我们没有类似复制状态机这样理论上严谨实际操作还很简单的方法,来实现对比和补偿。但还是可以根据业务数据的实际情况,来针对性地实现对比和补偿,经过一段时间,把新旧两个数据库的差异,逐渐收敛到一致。
像订单这类时效性强的数据,是比较好对比和补偿的。因为订单一旦完成之后,就几乎不会再变了,那我们的对比和补偿程序,就可以依据订单完成时间,每次只对比这个时间窗口内完成的订单。补偿的逻辑也很简单,发现不一致的情况后,直接用旧库的订单数据覆盖新库的订单数据就可以了。
这样,切换双写期间,少量不一致的订单数据,等到订单完成之后,会被补偿程序修正。后续只要不是双写的时候,新库频繁写入失败,就可以保证两个库的数据完全一致。
比较麻烦的是更一般的情况,比如像商品信息这类数据,随时都有可能会变化。如果说数据上有更新时间,那我们的对比程序可以利用这个更新时间,每次在旧库取一个更新时间窗口内的数据,去新库上找相同主键的数据进行对比,发现数据不一致,还要对比一下更新时间。如果新库数据的更新时间晚于旧库数据,那可能是对比期间数据发生了变化,这种情况暂时不要补偿,放到下个时间窗口去继续对比。另外,时间窗口的结束时间,不要选取当前时间,而是要比当前时间早一点儿,比如 1 分钟前,避免去对比正在写入的数据。
如果数据连时间戳也没有,那只能去旧库读取 Binlog,获取数据变化,然后去新库对比和补偿。
有一点需要说明的是,上面这些方法,如果严格推敲,都不是百分之百严谨的,都不能保证在任何情况下,经过对比和补偿后,新库的数据和旧库就是完全一样的。但是,在大多数情况下,这些实践方法还是可以有效地收敛新旧两个库的数据差异,你可以酌情采用。

21 | 类似“点击流”这样的海量数据应该如何存储?

对于大部分互联网公司来说,数据量最大的几类数据是:点击流数据、监控数据和日志数据。这里面“点击流”指的是在 App、小程序和 Web 页面上的埋点数据,这些埋点数据记录用户的行为,比如你打开了哪个页面,点击了哪个按钮,在哪个商品上停留了多久等等这些。
当然你不用太担心自己的隐私问题,记录的这些行为数据不是为了监控用户,主要目的是为了从统计上分析群体用户的行为,从而改进产品和运营。比如,某件商品看的人很多,停留时间很长,最后下单购买的人却很少,那采销人员就要考虑是不是这件商品的定价太高了。
除了点击流数据以外,监控和日志数据都是大家常用的,我就不再多解释了。
这类数据都是真正“海量”的数据,相比于订单、商品这类业务的数据,数据量要多出 2~3 个数量级。每天产生的数据量就可能会超过 TB(1 TB = 1024 GB)级别,经过一段时间累积下来,有些数据会达到 PB(1 PB = 1024 TB)级别。
这种量级的数据,在大数据技术出现之前,是没法保存和处理的,只能是通过抽样的方法来凑合着做分析。Hadoop 等大数据技术出现以后,才使得存储和计算海量数据成为可能。
今天这节课,我们来说说,应该选择什么样的存储系统,来保存像“点击流”这样的海量数据。

使用 Kafka 存储海量原始数据

早期对于这类海量原始数据,都倾向于先计算再存储。也就是,在接收原始数据的服务中,先进行一些数据过滤、聚合等初步的计算,将数据先收敛一下,再落存储。这样可以降低存储系统的写入压力,也能节省磁盘空间。
这几年,随着存储设备越来越便宜,并且,数据的价值被不断地重新挖掘,更多的大厂都倾向于先存储再计算,直接保存海量的原始数据,再对数据进行实时或者批量计算。这种方案,除了贵以外都是优点:
不需要二次分发就可以同时给多个流和批计算任务提供数据;
如果计算任务出错,可以随时回滚重新计算;
如果对数据有新的分析需求,上线后直接就可以用历史数据计算出结果,而不用去等新数据。
但是,这种方式对保存原始数据的存储系统要求就很高了:既要有足够大的容量,能水平扩容,还要读写都足够快,跟得上数据生产的写入速度,还要给下游计算提供低延迟的读服务。什么样的存储能满足这样的要求呢?这里我给出几种常用的解决方案。
第一种方案是,使用 Kafka 来存储。有的同学会问了,Kafka 不是一个消息队列么,怎么成了存储系统了?那我告诉你,现代的消息队列,本质上就是分布式的流数据存储系统。
如果你感兴趣的话,你可以仔细去研究一下 Kafka,它的数据是如何存储、分片、复制的?它是如何保证高可用,如何保证数据一致性的?那你会发现它和我们之前讲过的那些分布式存储系统,并没有什么太大的区别。唯一的区别就是,它的查询语言(生产和消费消息)和存储引擎的数据结构(Commit Log)比一般的存储系统要简单很多。但也正是因为这个原因,使得 Kafka 的读写性能远远好于其他的存储系统。Kafka 官方给自己的定位也是“分布式流数据平台”,不只是一个 MQ。
Kafka 提供“无限”的消息堆积能力,具有超高的吞吐量,可以满足我们保存原始数据的大部分要求。写入点击流数据的时候,每个原始数据采集服务作为一个生产者,把数据发给 Kafka 就可以了。下游的计算任务,可以作为消费者订阅消息,也可以按照时间或者位点来读取数据。并且,Kafka 作为事实标准,和大部分大数据生态圈的开源软件都有非常好的兼容性和集成度,像 Flink、Spark 等大多计算平台都提供了直接接入 Kafka 的组件。
当然,Kafka 也不是万能的,你可能注意到了,我刚刚讲 Kafka 提供“无限”的消息堆积能力,我在这个“无限”上打了个引号,这里面还是有一些限制需要注意的。Kafka 也支持把数据分片,这个在 Kafka 中叫 Partition,每个分片可以分布到不同的存储节点上。
写入数据的时候,可以均匀地写到这些分片上,理论上只要分片足够多,存储容量就可以是“无限”的。但是,单个分片总要落到某一个节点上,而单节点的存储容量毕竟是有限的,随着时间推移,单个分片总有写满的时候。
即使它支持扩容分片数量,也没办法像其他分布式存储系统那样,重新分配数据,把已有分片上的数据迁移一部分到新的分片上。所以扩容分片也解决不了已有分片写满的问题。而 Kafka 又不支持按照时间维度去分片,所以,受制于单节点的存储容量,Kafka 实际能存储的数据容量并不是无限的

Kafka 之外还有哪些解决方案?

所以,需要长时间(几个月 - 几年)保存的海量数据,就不适合用 Kafka 存储。这种情况下,只能退而求其次,使用第二种方案了。
第二种方案是,使用 HDFS 来存储。使用 HDFS 存储数据也很简单,就是把原始数据写成一个一个文本文件,保存到 HDFS 中。我们需要按照时间和业务属性来组织目录结构和文件名,以便于下游计算程序来读取,比如说:“click/20200808/Beijing_0001.csv”,代表 2020 年 8 月 8 日,从北京地区用户收集到的点击流数据,这个是当天的第一个文件。
对于保存海量的原始数据这个特定的场景来说,HDFS 的吞吐量是远不如 Kafka 的。按照平均到每个节点上计算,Kafka 的吞吐能力很容易达到每秒钟大几百兆,而 HDFS 只能达到百兆左右。这就意味着,要达到相同的吞吐能力,使用 HDFS 就要比使用 Kafka,多用几倍的服务器数量。
但 HDFS 也有它的优势,第一个优势就是,它能提供真正无限的存储容量,如果存储空间不够了,水平扩容就可以解决。另外一个优势是,HDFS 能提供比 Kafka 更强的数据查询能力。Kafka 只能按照时间或者位点来提取数据,而 HDFS 配合 Hive 直接就可以支持用 SQL 对数据进行查询,虽然说查询的性能比较差,但查询能力要比 Kafka 强大太多了。
以上这两种方案因为都有各自的优势和不足,在实际生产中,都有不少的应用,你可以根据业务的情况来选择。那有没有兼顾这二者优势的方案呢?最好能做到,既有超高的吞吐能力,又能无限扩容,同时还能提供更好的查询能力,有这样的好事儿么?
我个人的判断是,目前还没有可用大规模于生产的,成熟的解决方案,但未来应该会有的。目前已经有一些的开源项目,都致力于解决这方面的问题,你可以关注一下。
一类是分布式流数据存储,比较活跃的项目有Pravega和 Pulsar 的存储引擎Apache BookKeeper。我所在的团队也在这个方向上持续探索中,也开源了我们的流数据存储项目JournalKeeper,也欢迎你关注和参与进来。这些分布式流数据存储系统,走的是类似 Kafka 这种流存储的路线,在高吞吐量的基础上,提供真正无限的扩容能力,更好的查询能力。
还有一类是时序数据库(Time Series Databases),比较活跃的项目有InfluxDBOpenTSDB等。这些时序数据库,不仅有非常好的读写性能,还提供很方便的查询和聚合数据的能力。但是,它们不是什么数据都可以存的,它们专注于类似监控数据这样,有时间特征并且数据内容都是数值的数据。如果你有存储海量监控数据的需求,可以关注一下这些项目。

小结

在互联网行业,点击流、监控和日志这几类数据,是海量数据中的海量数据。对于这类数据,一般的处理方式都是先存储再计算,计算结果保存到特定的数据库中,供业务系统查询。
所以,对于海量原始数据的存储系统,我们要求的是超高的写入和读取性能,和近乎无限的容量,对于数据的查询能力要求不高。生产上,可以选择 Kafka 或者是 HDFS,Kafka 的优点是读写性能更好,单节点能支持更高的吞吐量。而 HDFS 则能提供真正无限的存储容量,并且对查询更友好。
未来会有一些开源的流数据存储系统和时序数据库逐步成熟,并陆续应用到生产系统中去,你可以持续关注这些项目。
在这个系列课程中,我们讲的都是如何解决生产系统中面临的一些存储系统相关的问题。在最后两节课里面,我们来说点儿新东西,看一下存储这个技术领域,可能会有哪些值得关注的新技术。当然,技术圈每天都有很多新的技术出现,也会经常发很多论文,出现很多的开源项目,这些大多数都不太靠谱儿。
今天我给你要说的这个 New SQL,它是我个人认为非常靠谱,甚至在未来可能会取代 MySQL 这样的关系型数据库的一个技术。MySQL 是几乎每一个后端开发人员必须要精通的数据库,既然 New SQL 非常有可能在将来替代 MySQL,那我们就非常有必要提前去了解一下了。

什么是 New SQL?

什么是 New SQL?这个说来话长了,还要从存储技术发展的历史来解读。我们知道,早期只有像 MySQL 这样的关系数据库,这种关系型数据库因为支持 SQL 语言,后来被叫做 SQL 或者 Old SQL。
然后,出现了 Redis 和很多 KV 存储系统,性能上各种吊打 MySQL,而且因为存储结构简单,所以比较容易组成分布式集群,并且能够做到水平扩展、高可靠、高可用。因为这些 KV 存储不支持 SQL,为了以示区分,被统称为 No SQL。
No SQL 本来希望能凭借高性能和集群的优势,替代掉 Old SQL。但用户是用脚投票的,这么多年实践证明,你牺牲了 SQL 这种强大的查询能力和 ACID 事务支持,用户根本不买账,直到今天,Old SQL 还是生产系统中最主流的数据库。
这个时候,大家都开始明白了,无论你其他方面做的比 Old SQL 好再多,SQL 和 ACID 是刚需,这个命你革不掉的。你不支持 SQL,就不会有多少人用。所以你看,近几年很多之前不支持 SQL 的数据库,都开始支持 SQL 了,甚至于像 Spark、Flink 这样的流计算平台,也都开始支持 SQL。当然,虽然说支持 SQL,但这里面各个产品的支持程度是参差不齐的,多多少少都有一些缩水。对于 ACID 的支持,基本上等同于就没有。
这个时候,New SQL 它来了!简单地说,New SQL 就是兼顾了 Old SQL 和 No SQL 的优点:
完整地支持 SQL 和 ACID,提供和 Old SQL 隔离级别相当的事务能力;
高性能、高可靠、高可用,支持水平扩容。
像 Google 的 Cloud Spanner、国产的 OceanBase 以及开源的CockroachDB都属于 New SQL 数据库。Cockroach 这个英文单词是蟑螂的意思,所以一般我们都把 CockroachDB 俗称为小强数据库。
这些 New SQL 凭什么就能做到 Old SQL 和 No SQL 做不到的这些特性呢?那我们就以开源的 CockroachDB 为例子,来看一下 New SQL 是不是真的这么厉害。

CockroachDB 是如何实现数据分片和弹性扩容的?

首先,我们一起先来简单看一下 CockroachDB 的架构,从架构层面分析一下,它是不是真的像宣传的那么厉害。我们先来看一下它的架构图 (图片来自于官方文档):
这是一个非常典型的分层架构,我们从上往下看。最上层是 SQL 层,SQL 层支持和关系型数据库类似的逻辑数据结构,比如说库、表、行和列这些逻辑概念。SQL 层向下调用的是一个抽象的接口层 Structured Data API,实际实现这个 API 的是下面一层:Distributed, Monolithic KV Store,这就是一个分布式的 KV 存储系统。
我们先不深入进去看细节,从宏观层面上分析一下这个架构。你可以看到,这个架构仍然是我们之间讲过的,大部分数据库都采用的二层架构:执行器和存储引擎。它的 SQL 层就是执行器,下面的分布式 KV 存储集群就是它的存储引擎。
那我们知道,MySQL 的存储引擎 InnoDB,实际上是基于文件系统的 B+ 树,像 Hive 和 HBase,它们的存储引擎都是基于 HDFS 构建的。那 CockroachDB 这种,使用分布式 KV 存储来作为存储引擎的设计,理论上也是可行的,并没有什么特别难以逾越的技术壁垒。
而且,使用分布式 KV 存储作为存储引擎,实现高性能、高可靠、高可用,以及支持水平扩容这些特性,就不是什么难事儿了,其中很多分布式 KV 存储系统已经做到了,这里面使用的一些技术和方法,大多我们在之前的课程中也都讲到过。CockroachDB 在实现它的存储引擎这一层,就是大量地借鉴,甚至是直接使用了已有的一些成熟技术。
它的分片算法采用的是范围分片,我们之前也讲到过,范围分片对查询是最友好的,可以很好地支持范围扫描这一类的操作,这样有利于它支撑上层的 SQL 查询。
它采用Raft一致性协议来实现每个分片的高可靠、高可用和强一致。这个 Raft 协议,它的一个理论基础,就是我们之前讲的复制状态机,并且在复制状态机的基础上,Raft 实现了集群自我监控和自我选举来解决高可用的问题。Raft 也是一个被广泛采用的、非常成熟的一致性协议,比如 etcd 也是基于 Raft 来实现的。
CockroachDB 的元数据直接分布在所有的存储节点上,依靠流言协议来传播,这个流言协议,我们在《16 | 用 Redis 构建缓存集群的最佳实践有哪些?》这节课中也讲到过,在 Redis Cluster 中也是用流言协议来传播元数据变化的。
CockroachDB 用上面这些成熟的技术解决了集群问题,在单机的存储引擎上,更是直接使用了 RocksDB 作为它的 KV 存储引擎。RocksDB 也是值得大家关注的一个新的存储系统,下节课我们会专门讲 RocksDB。
你可以看到,CockroachDB 的存储引擎,也就是它的分布式 KV 存储集群,基本上没有什么大的创新,就是重用了已有的一些成熟的技术,这些技术在我们之前讲过的其他存储系统中,全部都见到过。我讲这些并没有贬低 CockroachDB 的意思,相反,站在巨人的肩膀上,才能看得更远,飞得更高,这是一种非常务实的做法。

CockroachDB 能提供金融级的事务隔离性么?

接下来我们说一下 CockroachDB 是怎么实现 ACID 的,它的 ACID 是不是类似于分布式事务的残血版?这是一个非常关键的问题,直接影响到它有没有可能在未来取代 MySQL。
在说 ACID 之前,我们还是要简单说一下 CockroachDB 是怎么解析和执行 SQL 的。我们在《10 | 走进黑盒:SQL 是如何在数据库中执行的?》这节课中讲过 SQL 是如何在 MySQL 中执行的,在 CockroachDB 中,这个执行的流程也是差不多的。同样是先解析 SQL 生成语法树,转换成逻辑执行计划,再转换为物理执行计划,优化后,执行物理执行计划返回查询结果,这样一个流程。
只是在 CockroachDB 中,物理执行计划就更加复杂了,因为它的物理执行计划面对的是一个分布式 KV 存储系统,在涉及到查找、聚合这类操作的时候,有可能需要涉及到多个分片(Range)。大致过程就是类似于 Map-Reduce 的逻辑,先查找元数据确定可能涉及到的分片,然后把物理执行计划转换成每个分片上的物理执行计划,在每个分片上去并行执行,最后,再对这些执行结果做汇总。
然后我们再来说 CockroachDB 的 ACID。我们在《04 | 事务:账户余额总是对不上账,怎么办?》这节课中讲到过四种事务隔离级别,分别是 RU、RC、RR 和 SERIALIZABLE,那 CockroachDB 能提供哪种隔离级别呢?答案是,以上四种都不是。
CockroachDB 提供了另外两种隔离级别,分别是:Snapshot Isolation (SI)Serializable Snapshot Isolation (SSI),其中 SSI 是 CockroachDB 默认的隔离级别。
这两种隔离级别和之前提到的四种隔离级别是什么关系呢?我们通过下面这张表,和 MySQL 默认的隔离级别 RR 做一个对比。
首先我们看 SI 这一行。我们之前讲到过,RR 这种隔离级别,可以很好地解决脏读和不可重复读的问题,虽然可能会产生幻读,但实际上对绝大多数事务影响不大。SI 不会发生脏读、不可重复读,也不会发生幻读的情况,这个隔离级别似乎比 RR 还要好。
但你要注意一下,我们这个表格比之前那个表格多了一列:写倾斜。可以看到,RR 是不会出现写倾斜问题的,但是 SI 会有写倾斜问题。
什么是写倾斜?我们还是拿账户余额的例子来说明。比如说,我们的账户需要支持主副卡,主卡和副卡都分别有自己的余额,并且这个余额是可以透支的,只要满足主副卡的余额之和大于 0 就行了。如果我们需要给主卡支出 100 元,那 SQL 只要这样写就可以了:
 
 
 
 
 
 
 
 
update account
set balance = balance - 100 -- 在主卡中扣减100元
where id = ? and
(select balance from account where id = ?) -- 主卡余额
+
(select balance from account where id = ?) -- 附卡余额
>= 100; -- 主副卡余额之和必须大于100元
 
在传统的 RR 隔离级别下,由于更新数据时会对记录加锁,即使更新主副卡的两个 SQL 分别在两个事务中并发执行,也不会出现把主副卡的余额之和扣减成负数的情况。
但是在 SI 级别下,由于它没有加锁,而是采用快照的方式来实现事务的隔离,这个时候,如果并发地去更新主副卡余额,是有可能出现把主副卡余额之和扣减为负数的情况的。这种情况称为写倾斜。这里顺便提一句,写倾斜是普遍的译法,我个人觉得“倾斜”这个词翻译得并不准确,实际上它表达的,就是因为没有检测读写冲突,也没有加锁,导致数据写错了。
SSI 隔离级别在 SI 的基础上,加入了冲突检测的机制,通过检测读写冲突,然后回滚事务的方式来解决写倾斜的问题,当然这种方式付出的代价是降低性能,并且冲突严重的情况下,会频繁地出现事务回滚。
从理论上来说,CockroachDB 支持的 SI 和 SSI 这两种事务隔离级别,能提供的事务隔离性,已经与传统的 RC 和 RR 隔离级别不相上下了,可以满足大多数在线交易类系统对 ACID 的要求。

小结

New SQL 是新一代的分布式数据库,它具备原生分布式存储系统高性能、高可靠、高可用和弹性扩容的能力,同时还兼顾了传统关系型数据库的 SQL 支持。更厉害的是,它还提供了和传统关系型数据库不相上下的、真正的事务支持,具备了支撑在线交易类业务的能力。
CockroachDB 是开源的 New SQL 数据库。它的存储引擎是一个分布式 KV 存储集群,执行器则大量借鉴了 PostgreSQL 的一些设计和实现,是一个集很多现有数据库和分布式存储系统技术于一身,这样的一个数据库产品。
从设计上来看,CockroachDB 这类 New SQL 数据库,有非常大的潜质可以真正地取代 MySQL 这类传统的关系型数据库。但是我们也应该看到,目前这些 New SQL 数据库都还处于高速发展阶段,并没有被大规模地应用到生产系统中去。我也不建议你做小白鼠,在重要的系统上去使用它。
 
 
 
posted @ 2026-03-26 01:58  charyGao  阅读(15)  评论(0)    收藏  举报