NewSQL如何解决高可用、分片?

2023-01-04 08:27:35 浏览数 (1)

1 什么是New 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数据库。

这些New SQL凭什么就能做到Old SQL和No SQL做不到的这些特性呢?

CockroachDB数据分片和弹性扩容

架构图(图片来自于官方文档):

最上层是SQL层,SQL层支持和关系型数据库类似的逻辑数据结构,如库、表、行和列这些逻辑概念。

SQL层向下调用的是一个抽象的接口层Structured Data API,实际实现这个API的是下面一层:Distributed, Monolithic KV Store,这就是一个分布式KV存储系统。

大部分数据库都采用的二层架构:执行器和存储引擎。它的SQL层就是执行器,下面的分布式KV存储集群就是它的存储引擎。

MySQL存储引擎InnoDB是基于文件系统的B 树,像Hive和HBase存储引擎都是基于HDFS构建。那CockroachDB这种,使用分布式KV存储来作为存储引擎的设计,理论上也是可行。

CockroachDB在实现它的存储引擎这一层,就是大量地借鉴,甚至是直接使用了已有的一些成熟技术。

分片算法采用的是范围分片,范围分片对查询最友好,可很好支持范围扫描,有利支撑上层SQL查询。

采用Raft一致性协议来实现每个分片的高可靠、高可用和强一致。这个Raft协议,它的一个理论基础,就是我们之前讲的复制状态机,并且在复制状态机的基础上,Raft实现了集群自我监控和自我选举来解决高可用的问题。

CockroachDB的元数据直接分布在所有的存储节点上,依靠流言协议传播,Redis Cluster也是用流言协议来传播元数据变化。

CockroachDB用上面这些成熟的技术解决了集群问题,在单机的存储引擎上,更是直接使用了RocksDB作为KV存储引擎。

你可以看到,CockroachDB的存储引擎,也就是它的分布式KV存储集群,基本上没有什么大的创新,就是重用了已有的一些成熟的技术,这些技术在我们之前讲过的其他存储系统中,全部都见到过。我讲这些并没有贬低CockroachDB的意思,相反,站在巨人的肩膀上,才能看得更远,飞得更高,这是一种非常务实的做法。

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

CockroachDB怎么解析和执行SQL。CockroachDB执行流程差不多。先解析SQL生成语法树,转换成逻辑执行计划,再转换为物理执行计划,优化后,执行物理执行计划返回查询结果。

只是CockroachDB中,物理执行计划更复杂,因为物理执行计划面对的是分布式KV存储系统,在涉及查找、聚合这类操作,可能涉及多个分片(Range)。类似Map-Reduce的逻辑,先查找元数据确定可能涉及到的分片,然后把物理执行计划转换成每个分片上的物理执行计划,在每个分片上去并行执行,最后,再对这些执行结果做汇总。

CockroachDB的ACID。RU、RC、RR和SERIALIZABLE,那CockroachDB能提供哪种隔离级别呢?四种都不是。

CockroachDB提供了另外两种隔离级别,分别是:Snapshot Isolation (SI)Serializable Snapshot Isolatin (SSI),其中SSI是CockroachDB默认的隔离级别。

这两种隔离级别和之前提到的四种隔离级别的关系:

SI这行。RR解决脏读和不可重复读,虽然可能幻读,但实际上对绝大多数事务影响不大。SI不会脏读、不可重复读,也不会发生幻读,似乎比RR好。

但这表格多列:写倾斜。RR不会写倾斜,但SI有写倾斜问题。

写倾斜

拿账户余额的例子来说明。比如说,我们的账户需要支持主副卡,主卡和副卡都分别有自己的余额,并且这个余额是可以透支的,只要满足主副卡的余额之和大于0就行了。如果我们需要给主卡支出100元:

代码语言:javascript复制
update account
-- 在主卡中扣100
set balance = balance - 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要求。

总结

CockroachDB是开源的New SQL数据库。它的存储引擎是一个分布式KV存储集群,执行器则大量借鉴了PostgreSQL的一些设计和实现,是一个集很多现有数据库和分布式存储系统技术于一身,这样的一个数据库产品。

从设计上来看,CockroachDB这类New SQL数据库,有非常大的潜质可以真正地取代MySQL这类传统的关系型数据库。但是我们也应该看到,目前这些New SQL数据库都还处于高速发展阶段,并没有被大规模地应用到生产系统中去。我也不建议你做小白鼠,在重要的系统上去使用它。

做一个日志系统,收集全公司所有系统的全量程序日志,给开发和运维人员提供日志的查询和分析服务,你会选择用什么存储系统来存储这些日志?原因是什么?

要根据业务对数据的查询方式,反推数据应该使用什么存储系统。对于日志的查询,最常用的二种方式就是按照关键字去查询或者指定一个时间和IP去浏览。

若日志量级不超过TB级,直接放到ES最省事,对于二种查询方式都可以获得还不错的查询性能。规模太大,ES也扛不住,可考虑把日志放到HDFS,对于浏览的查询需求,直接定位的具体的日志文件返回是比较快的。对于关键字查询的需求,也可以通过实现Map-Reduce任务,并行查询然后聚合的方式来实现。

0 人点赞