传统客户调研国产分布式数据库过程中,POC(Proof Of Conception的简称)环节必不可少。数据库POC是否顺利,是否卓有成效,技术方面通常跟下面几点有关系:

  • + 测试需求
  • + 测试环境
  • + 测试方案


参与测试的数据库厂商如果有一份完整的功能说明文档,同时客户又能定义一份确切的POC验收标准文档,这是最理想的。然而现实跟理想总是有很大距离。


国产分布式数据库POC验收通常首先包含对传统数据类型、SQL的兼容性,然后就是分布式数据库的性能、运维。分布式数据库通常都可以在线扩容(加机器),这个运维需要关注。加了机器后,应用性能不一定能成倍增长,这个开发需要关注。(1)


分布式产品有个特点,当请求跨节点调用时,性能会比节点内部调用要慢一些。分布式数据库里,不是所有的表都能做水平拆分,如一些基础信息表、配置表等。当非拆分表跟拆分表做表连接时,会有很多跨节点请求,性能会慢下来。分库分表类数据库给出的方案是小表广播功能,广播表的多个副本内容同步由数据库内部组件完成。分库分表还有个困难是全局索引,所以有异构索引表这个功能。当事务涉及到多个节点时,分布式数据库可能还需要分布式事务中间件配合完成。有些功能比较完善的,直接把分布式事务能力做到数据库内部。传统的分布式事务理论有可用性问题和性能问题,互联网场景里的分布式事务多是以最终一致(TCC模型)取代强一致(XA模型)


如果调研的数据库都使用了分库分表这个中间件解决方案,这些功能都是需求的标配。但面临一些原生的分布式数据库时,这些需求就不太准确。(2)

比如说在TiDB里,所有表都是按块大小切分的,切分细节跟业务无关,没有分实例分库的概念。在OceanBase里,表定义为分区表时才具备水平拆分能力,分表对应的是分区,没有分库或者多个实例的概念。所以OceanBase没有那种跨分库或跨实例的分布式事务,但有跨节点的分布式事务。这个OceanBase内部支持,并且效果是强一致。其代价就是性能比单节点内事务要慢一些,实际场景要看业务能否接受。(6)


在传统数据库里,数据写性能和数据安全可以彼此妥协。为了主库写性能更高,默认情况下ORACLE使用最大性能同步模式做主备同步,MySQL使用异步同步并且Binlog和Redolog都不落盘的策略。分库分表架构的分布式数据库的底层存储依然是传统数据库,在追求性能的同时需要分析付出的代价是什么。在原生的分布式数据库OceanBase里事务日志至少是三副本,强制落盘,同步协议不是异步、半同步之类,而是Paxos协议,这是同步性能和数据安全之间的平衡选择,也不可修改。


还有一类数据安全跟事务隔离级别有关。传统数据库里ORACLE和MySQL的事务隔离级别特性并不完全一致,不同分布式数据库分别跟进了ORACLE或MySQL的事务隔离级别。加上乐观锁技术也用在事务里,所以想用一条需求标准评估所有分布式数据库的事务特性还是有点难操作的。(7)


使用分布式数据库后,机器规模可能增长非常快。而分布式数据库所用的硬件都是普通的x86服务器、SSD硬盘,可靠性都低于传统的小机(以IBM的小机为代表)和存储(以EMC存储为代表),加上分布式数据库对网络也要求很高,软硬件故障次数可能会高于传统数据库架构。如果数据库机器规模很大,对运维人员压力也很大。所以分布式数据库都会有个自动化运维平台(PaaS),同时对于节点故障要有自动切换能力。衡量切换能力的两个指标是RPO和RTO。自动切换要考察其切换原理,是否能规避脑裂。还有客户端路由如何切换。(3)分布式数据库高可用有个新的特点,节点的故障只会影响局部数据的读写。通过巧妙的水平拆分设计可以从一开始就将节点故障的影响比例控制在业务可接受的范围内。


性能验证也是POC一个重要事情,常用来做不同数据库产品之间的性能对比。性能测试场景选择很重要。
最常见的做法是选择sysbench测试数据库的oltp性能,这个比较常用,可以模拟纯insert、纯写(insert\update\delete)、纯读、读写混合场景。使用中有几个注意点。一是insert时如果有自增列是选择sysbench产生还是选择数据库产生。如果想验证数据库自增列能力就用数据库产生。MySQL数据库支持自增列,基于MySQL的分布式数据库也自己实现了自增列。不过在全局层面一个分表的自增列的值并不连续也不单调递增,而是分为多个区间段在,每个段内是单调递增。OceanBase的MySQL租户也支持自增列,分区表的自增列的值也不是连续和单调递增的。所以业务不能依赖自增列的值去判断记录产生先后顺序。ORACLE没有自增列,而是使用sequence产生。OceanBase的ORACLE租户支持sequence功能,其产生的值是连续和递增的。二是表的数据量要够大,测试的时间要够长。传统数据库ORACLE/MySQL/DB2的架构里都有Buffer Pool(简称BP)这个模块,当读写的数据不再BP里会从磁盘读入(随机物理读IO)。基于MySQL的分布数据库底层读写这个特点也是不变,OceanBase的读也有这个特点。真实业务场景会有一定比例的随机物理读IO。压测时如果数据量很小或者时间很短,这个比例几乎为0,测试结果的参考意义就要打折扣。对于数据写,传统数据库BP由于脏块产生速度很快,所以会有多个机制将脏块刷写(Checkpoint)到磁盘上(随机物理写IO)。OceanBase的读写模型是基于LSM-Tree,脏块产生速度很慢,所以脏块在内存中待的时间会更久,刷脏事件会非常少(有,叫转储,频率很低)。转储并不包含全部数据,也不改变磁盘数据文件版本,只有合并才会将内存增量和磁盘上基线数据进行合并生成新的全局一致性的版本(这个版本也方便了备份)。合并是OceanBase特有的逻辑,POC时需要额外考虑。(4)三是sysbench的lua脚本。这个可以根据实际需求修改,细微修改可能导致性能的大幅变化。lua脚本里的随机数生成器比较耗CPU,所以设置合理的并发数。如果单个客户端出现瓶颈时可以使用多个客户端同时跑。


sysbench的功能还是很丰富的,入门也容易。它的缺点就是业务模型太简单。复杂一点的测试标准有TPCC,可以使用Benchmarksql。其业务模型考虑数据量、SQL和事务,可以更能评估数据库的综合能力。不过这个Bencharmksql跟TPC委员会定义的TPC-C还不完全相同,后者还要模拟业务用户的思考时间(thinktime)和输入时间(keytime)。这块经验还不多,以后再补充。(5)


不管是哪种标准,客户自己的业务场景才是最重要的。所以客户可以从自己业务中取出最关键的逻辑,开发测试程序去评估数据库的综合能力。这个对开发的要求有点多,需要跟数据库厂商了解数据库架构特点和性能优化原理。
客户开发业务场景案例会面临一个选择:不同的分布式数据库除了有共同的原理外,都有其独特的功能。如果利用那些独特的功能,就可以将那个数据库性能发挥到极致。有些客户可能会将这种特殊操作理解为被数据库绑架,不够通用,将来想迁移到其他数据库上会非常难。不过看看ORACLE,DB2和SQLServer,彼此都有特有的功能并且互不兼容,ORACLE在这方面能力更为突出,经常有不符合SQL标准的功能。对于ORACLE来说功能好用推广开来,它就是标准。要把ORACLE数据库发挥到极致,可能绕不过这些特殊功能。对于分布式数据库也一样,不同产品之间大同小异,都会有自己的最佳实践。而性能优化的根本原理就是设计数据的分布式特点,并针对性优化SQL访问路径。在定制场景时还有一种情形是曾经遇到某类性能问题(比如说外在因素导致的抖动),在选型国产数据库或者分布式数据库时担心有类似的问题,这个也有道理。不过更建议对目标数据库原理进行更多了解,以分析是否可能引入新的特有问题。这类问题通常是因为原理了解的不深入,应对准备不充分。一旦问题发生了,应用和数据库产品之间总能找到解决方案。
国产分布式数据库产品太多,还有些原理和实践经验我也不了解。个人观点难免有误,欢迎指正。总体上来说,对客户而言,分布式数据库选型测试需求的制定就是一个很重要很费精力的事情。