You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
12 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 23 | MySQL经常遇到的高可用、分片问题NewSQL是如何解决的
你好,我是李玥。
在这个系列课程中,我们讲的都是如何解决生产系统中面临的一些存储系统相关的问题。在最后两节课里面,我们来说点儿新东西,看一下存储这个技术领域,可能会有哪些值得关注的新技术。当然,技术圈每天都有很多新的技术出现,也会经常发很多论文,出现很多的开源项目,这些大多数都不太靠谱儿。
今天我给你要说的这个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](https://github.com/cockroachdb/cockroach)都属于New SQL数据库。Cockroach这个英文单词是蟑螂的意思所以一般我们都把CockroachDB俗称为小强数据库。
这些New SQL凭什么就能做到Old SQL和No SQL做不到的这些特性呢那我们就以开源的CockroachDB为例子来看一下New SQL是不是真的这么厉害。
## CockroachDB是如何实现数据分片和弹性扩容的
首先我们一起先来简单看一下CockroachDB的架构从架构层面分析一下它是不是真的像宣传的那么厉害。我们先来看一下它的架构图(图片来自于[官方文档](https://github.com/cockroachdb/cockroach/blob/master/docs/design.md))
![](https://static001.geekbang.org/resource/image/8c/82/8c78db973e66bb62b23c8e85afe78082.jpg)
这是一个非常典型的分层架构我们从上往下看。最上层是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](https://raft.github.io/)一致性协议来实现每个分片的高可靠、高可用和强一致。这个Raft协议它的一个理论基础就是我们之前讲的复制状态机并且在复制状态机的基础上Raft实现了集群自我监控和自我选举来解决高可用的问题。Raft也是一个被广泛采用的、非常成熟的一致性协议比如etcd也是基于Raft来实现的。
CockroachDB的元数据直接分布在所有的存储节点上依靠流言协议来传播这个流言协议我们在《[16 | 用Redis构建缓存集群的最佳实践有哪些](https://time.geekbang.org/column/article/217590)》这节课中也讲到过在Redis Cluster中也是用流言协议来传播元数据变化的。
CockroachDB用上面这些成熟的技术解决了集群问题在单机的存储引擎上更是直接使用了RocksDB作为它的KV存储引擎。RocksDB也是值得大家关注的一个新的存储系统下节课我们会专门讲RocksDB。
你可以看到CockroachDB的存储引擎也就是它的分布式KV存储集群基本上没有什么大的创新就是重用了已有的一些成熟的技术这些技术在我们之前讲过的其他存储系统中全部都见到过。我讲这些并没有贬低CockroachDB的意思相反站在巨人的肩膀上才能看得更远飞得更高这是一种非常务实的做法。
## CockroachDB能提供金融级的事务隔离性么
接下来我们说一下CockroachDB是怎么实现ACID的它的ACID是不是类似于分布式事务的残血版这是一个非常关键的问题直接影响到它有没有可能在未来取代MySQL。
在说ACID之前我们还是要简单说一下CockroachDB是怎么解析和执行SQL的。我们在《[10 | 走进黑盒SQL是如何在数据库中执行的](https://time.geekbang.org/column/article/213176)》这节课中讲过SQL是如何在MySQL中执行的在CockroachDB中这个执行的流程也是差不多的。同样是先解析SQL生成语法树转换成逻辑执行计划再转换为物理执行计划优化后执行物理执行计划返回查询结果这样一个流程。
只是在CockroachDB中物理执行计划就更加复杂了因为它的物理执行计划面对的是一个分布式KV存储系统在涉及到查找、聚合这类操作的时候有可能需要涉及到多个分片Range。大致过程就是类似于Map-Reduce的逻辑先查找元数据确定可能涉及到的分片然后把物理执行计划转换成每个分片上的物理执行计划在每个分片上去并行执行最后再对这些执行结果做汇总。
然后我们再来说CockroachDB的ACID。我们在《[04 | 事务:账户余额总是对不上账,怎么办?](https://time.geekbang.org/column/article/206544)》这节课中讲到过四种事务隔离级别分别是RU、RC、RR和SERIALIZABLE那CockroachDB能提供哪种隔离级别呢答案是以上四种都不是。
CockroachDB提供了另外两种隔离级别分别是**Snapshot Isolation (SI)** 和 **Serializable Snapshot Isolation (SSI)**其中SSI是CockroachDB默认的隔离级别。
这两种隔离级别和之前提到的四种隔离级别是什么关系呢我们通过下面这张表和MySQL默认的隔离级别RR做一个对比。
![](https://static001.geekbang.org/resource/image/20/67/20e20d983ad7519e6eae11821a3f1567.jpg)
首先我们看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数据库都还处于高速发展阶段并没有被大规模地应用到生产系统中去。我也不建议你做小白鼠在重要的系统上去使用它。
## 思考题
课后请你去看一下[Raft](https://raft.github.io/)一致性协议然后简单总结一下CockroachDB是如何利用Raft协议实现Range高可用、高可靠和强一致的。欢迎你在留言区与我讨论。
感谢你的阅读,如果你觉得今天的内容对你有帮助,也欢迎把它分享给你的朋友。