自从互联网进入了 web2.0 时代以来,数据库作为核心的底层基础设施软件也经历了蓬勃的发展期,从早期的单机关系型数据库到NoSQL 再到如今的 NewSQL,数据库领域不管是技术还是场景都发生了巨大的变化。在当下云原生时代,任何软件系统拥有分布式能力似乎成了标配。
特别是在目前基础软件国产化的浪潮下,国产数据库百花齐放,大有弯道超车的趋势。
在这个领域里面,分布式数据库无疑是当今最热门的赛道。
1 什么是分布式数据库
回答这个问题之前,我们暂且不去考虑各种官方定义,不妨换个思路入手把这个名词做下拆分,再看一下碰撞在一起会有什么火花。
Part 1:分布式
以大家非常熟悉的场景举例,比如完成一项软件开发工作。
小公司的做法就是招一个全栈工程师,所有任务全包,但往往这样的人虽然各方面都懂一点却没有特别精通的方向,很容易达到能力上限。
在一个大团队通常会分为多种角色(UI、前端、后端、DBA、运维等),这些人就构成了一个分布式系统,大家协调完成共同的任务,这中间的协调者就是项目经理或者部门 leader。
项目开发中的“分布式
这样的好处就是:
•职责分离:大家各司其职,各自做好擅长的事。
• 平滑扩容:哪个环节缺人就定点补充。
• 负载能力:可以应对更大更多的项目。
当然了有优点就有缺点:
• 网络通信:沟通成本增加,需要标准化工作模式。
• 调度:如何高效率协调所有人员。
• 一致性:如何保证上下游人员信息对齐。
说到分布式就不得不提与之相关的另一个概念,那就是集群,很多初学者并不能很好的理解集群和分布式的差别。
还是拿前面的例子来说,假如小公司的全栈工程师有点异常情况(请假、跑路、忙不过来等等)老板会考虑招多个这样的人,这就形成了一个集群,好处就是能干更多的活(负载分流)和互补(高可用),但本质上还是一个人做所有事。
事实上,分布式和集群是可以搭配使用的,比如上面的大团队例子,每个角色可以配置多个人,这就形成了分布式集群。
Part 2:数据库
数据库用通俗易懂的话来说就是管理数据的地方,就像生活中一个存放货物的仓库,我们要按一定的规则把物品整整齐齐的摆好(写数据),这样就方便我们去检索出货(查数据)。
在计算机世界里,通常会把数据按照二维表格组织起来,这个表格我们称之为关系模型,然后对这些数据使用结构化查询语言(SQL)做各种关系运算,就能得到我们想要的结果,这就是关系型数据库,也是目前使用最广泛的一种数据库。除此之外,相信大家也还听过其他类型的数据库,比如KV型、文档型、时序型、图数据库等等。
最常见的数据库就是每个人都用过的 Excel 文档,一个文件可以看成一个数据库,每个 sheet 就是数据表,表里的列就是字段,每一行就是存储的数据。
在我看来,“分布式”和“数据库”放在一起并不是做加法,而是做了乘法。
传统的那些分库分表以及各种 Sharding 方案可以看做是一种伪分布式(做加法),和真正的分布式数据库有着本质不同。
其中最大的区别,便体现在分布式事务上。单机数据库的事务是在一个节点上完成的,分布式数据库需要多个节点协调完成。
以经典的银行转账场景举例:
甲要给乙转100块钱,但是甲的账户信息存放在节点 A,乙的数据存放在节点 B。
单机数据库通过事务很容易就能完成。
分布式环境下的事务就需要考虑各种网络故障、数据一致性的问题,对客户端而言仍然要保证事务操作的简便性,完成整个转账操作和单机数据库体验一致,所有故障处理都要透明。
分布式数据库继承了传统单机数据库的核心特性,同时还拥有分布式系统的处理能力,理论上所有需求都能通过横向扩展解决,这是在大数据高并发场景下诞生的一种产物。虽然起步较晚,可以预见的是它将是数据库下一个发展方向。
2 为什么需要分布式数据库
首先要声明的是,分布式数据库的出现并不是要完全取代传统数据库,传统数据库在市场份额和流行度上仍然保持遥遥领先,毕竟这是过去30多年的发展沉淀,底子摆在那里。至少未来很长的一段时间内,这种领先优势会持续存在,只是差距会慢慢变小。
为什么需要分布式数据库呢?那一定为了解决传统数据库解决不了的问题,任何新技术的引进我认为就是一个目的:降本增效。
达到这个目的之前,我们都要先考虑清楚是否把这个技术用在了适合它的场景。
以我使用较多的分布式数据库 TiDB 为例:
很多刚接触到的用户都会拿它和 MySQL 做对比测试,最后得出的结论就是为什么 3 台机器的 TiDB 还没有单台机器的 MySQL 性能好?
这就是一个典型的使用场景错误案例。单机 MySQL 就能解决的问题,TiDB 是发挥不出它的优势的。
这就好比于大家上班通勤,坐出租车就能搞定的事情,你会选择坐高铁吗?你又能说出租车一定比高铁快吗?
这两样除了都是交通工具外,其实没有太多可比性,根本原因就是各自的使用场景不一样,上面 MySQL 和 TiDB 的案例也是这个道理。
下面就来看看传统数据库面临着哪些难以解决的问题。
问题一:海量数据存储
现在各种各种的终端设备每天产生着海量数据,这些数据最终都要通过数据库系统保留下来,如何才能高效地保存这么多数据是首先要面对的难题。
一般来说,传统数据库的做法就是纵向扩展(scale-up),存储不够就加磁盘,计算不够就加 CPU,内存不够就加内存,加到后面加不动了就上小型机大型机。但这种扩展方式总会达到一个极限,而且随着数据库越来越大,实际成本和收益比会越来越小。
加配置的纵向扩展
分布式数据库采用了横向扩展(scale-out)思路,也就是说遇到瓶颈通过加机器而不是加配置解决,这样就能实现无限水平扩展。再多的数据都能使用一定的分片策略分散到不同的机器,分而治之就是分布式的核心理念。
加机器的横向扩展
问题二:分库分表的痛点
在分布式数据库出来之前,针对大数据量的读写场景广泛采用分库分表方案,也由此诞生了很多分库分表、读写分离中间件。这些方案虽然能带来一定的效果,也会引发一些后遗症,比如:
• 需要提前规划好分片规则,一旦定好规则就难以移动,扩展困难
• 分得太细会浪费资源,分得太粗会导致二次拆分
• 数据迁移困难
• 运维难度高
说一个我见过的小案例:
下面这张图是 MySQL 迁移过程中发生的一个报错信息:
相信大部分人第一反应和我一样:从未见过这么长的表名,根据命名规则来看,基本能判定是为了保持分表规范才这样设计,要么是做数据拆分要么就是数据归档,这样的设计给后期数据库运维带来了很大的困难。
在分布式数据库中不用考虑单表的存储限制,几十亿上百亿行的表非常常见,它能充分利用每一个节点的计算存储资源,保证读写性能。
问题三:高可用容灾
高可用指标
说到高可用的时候我们都会提到 3个9、4个9 这样的指标,它反映了一个软件系统的可靠性。与此相关的还有两个重要指标:
• RTO-恢复服务所用的时间,越短越好
• RPO-恢复服务后丢失的数据量,越小越好
对于数据库系统来说,可靠性的最好情况就是服务永不停机,但这是不可能实现的,因为本身硬件层面就存在一定的故障率。
传统数据库的做法
传统数据库的做法是做主备架构,部署两套或多套相同的数据库系统,中间使用数据同步技术实现物理备份,当主库出现故障时切换到备库提供服务。
这种方案有以下几个缺点:
• 主备切换需要时间,RTO 难以保证
• 主备数据同步存在延时,RPO 也难以保证
• 硬件资源消耗大,运维困难
分布式数据库的做法
丢数据这种事在某些数据敏感行业是无法接受的。而绝大部分的分布式数据库自带多副本特性,并且能保证副本之间的强一致性,这就相当于天生拥有高可用能力。这种多副本同步能力不仅可以应用在多主机中,甚至能扩展到多机柜、多数据中心、以及跨区域的能力,极大地减少了硬件成本和运维成本。由于多副本的存在,它可以做到 RPO 为 0,自动故障转移可以让 RTO 在秒级。
3 有哪些分布式数据库
分布式数据库根据架构风格的不同我们可以大致分为两类。
第一种是由传统分库分表演进而来,再加上额外的调度节点实现分片路由、全局时钟实现分布式事务,基本构成了一个分布式数据库,但每一个数据节点依然是单体数据库,通过主从复制来实现高可用,我们把这一类称为 PG-XC 风格。
这一类的代表作品有:
• 中兴的 GoldenDB
• 华为的 GaussDB
• 腾讯的 TDSQL
第二种是整个体系完全重构,数据库中的每个组件都采用分布式设计,底层存储多采用键值(KV)系统,同时引入多数派选举算法实现多副本同步,存储、计算、调度完全分离,我们把这一类称为 NewSQL 风格。
这一类的代表作品有:
• 国外的 CockroachDB、YugabyteDB
• PingCAP 的 TiDB
• 蚂蚁的 OceanBase
还有一类云原生数据库也属于分布式数据库范畴,典型的产品有AWS的Aurora、微软的Cosmos DB、阿里的PolarDB 等等。
4 分布式数据库的未来
下图对比了传统关系型数据库三巨头和新型分布式数据库的流行度趋势:
这个统计数据来源于各大搜索引擎、数据库问答社区、社交媒体话题等,能够反映某一项技术的使用情况。
可以看到,分布式数据库正在以猛烈的趋势追赶,而传统数据库指数在慢慢往下降。
得益于国内互联网行业的快速发展,国外的数据库系统远远不能满足需要,由此催生了一批走在世界前沿的国产分布式数据库产品。不仅仅互联网客户在使用,越来越多的国企、政府单位、银行、证券这些传统行业也开始关注分布式数据库,去 O 道路将被加速。