Oracle 12C正式发布前,我曾经参加过一个中国企业用户与Oracle研发副总裁的圆桌会议,主要是提出国内企业级用户对Oracle数据库的一些需求,供Oracle下一个版本增加功能时参考。当时会上提出的很多需求后来在19c/20c里都看到了响应,不过这些还不是让我印象最深的,印象最深的是针对Oracle 12C SHARDING功能的讨论。
当时我问Oracle 12C的MPP功能发展的方向是什么,当时与会的Oracle研发部门的人首先纠正了我的问题,Oracle 12C推出的只是SHARDING数据库,而不是MPP数据库。SHARDING主要面向的是高并发写入,业务逻辑相对简单的应用类型,而不是面向复杂的数据仓库计算的,因此这个功能不能被称为MPP。我继续追问Oracle今后是否会把目前的SHARDING升级为完全意义上的MPP,Oracle方面的回答让我有点意外,他们认为对于一般的OLTP,Oracle RAC已经完全能胜任,在12C中推出的in memory db特性可以解决以前Oracle在OLAP方面的不足,SHARDING只是用于解决未来物联网等应用的需求。Oracle不会推出新的MPP数据库,因为这意味着重新写一个新的ORACLE出来,而Oracle的技术储备并不足够。
虽然Oracle的技术储备并不足够,这并不能阻止大量的分布式数据库蜂拥而出。目前市场上的分布式数据库已经有上百个了,在这些产品之间做选型确实是一个十分具有挑战的工作。更可怕的是,几乎所有的数据库厂商都告诉你,他们的数据库是最优秀的,最符合你需求的。这让你无从拒绝,因为在分布式关系型数据库领域,没有一个真正科学的普适性的标准,可以评判某个数据库的好坏。虽然如此,我们还是可以从较为理性的角度来分析某个分布式数据库的好坏。实际上我们不需要去分辨RAFT还是PASOX哪个共优秀更高效,而需要从数据库的最为基本的原理去分析就可以了。
首先我们要考虑的是存储引擎。存储引擎是数据库娘胎里就带出来的基本属性,一旦存储引擎确定了,那么数据库的一些特性基本上也就确定了。2017年在贵阳数博会上,我遇到了时任易鲸捷CTO的丁洪先生,他负责易鲸捷硅谷的数据库核心研发团队。当时他们的研发团队的一个负责人和我们为了一个电力应用场景上易鲸捷的优化已经一起工作了两个多月了。谈到这个项目,丁洪深有感触,他以前觉得易鲸捷已经能够支撑各种复杂的应用场景了,通过这两个月的测试他们发现以前他们在美国遇到的场景都是大并发量写入后的延时分析,而这种高并发写入后的准实时分析场景,他们的基于HBASE的存储引擎已经难以支撑了。通过这个项目他认识到,要想真正实现HTAP,必须重写存储引擎。通过这个例子,我想要表达的意思是,我们想选择适合于我们应用场景的分布式数据库,必须首先了解这个分布式数据库的存储引擎,以及存储引擎的特点是什么。基于HEAP存储的、B-TREE存储的和LSM-TREE存储的引擎其优点和缺点都十分明显。有一句话说的很清楚:天底下没有免费的午餐。在某个地方特别优秀的存储引擎,可能就会在另外一个地方差的一塌糊涂,这一点一定要做好思想准备。堆表高并发下的热块冲突会十分严重,B-TREE存储批量装载性能受到影响,LSM-TREE在比较合并时的开销过大,这些都是从娘胎里带出来的缺陷,你很难说可以轻松消解的。PingCap的架构师是一个具有整体思维的好架构师,在TiDB上的一些设计都是在弥补LSM-TREE上的不足。使用SSD盘、每个节点不超过16TB的存储容量、使用TiSPARK引擎来处理一些复杂的分析场景等,无不是对LSM-TREE的优缺点十分了解后的弥补措施。特别是TiFlash副本的推出,让TiDB向HATP走出了十分坚实的一步。不过这种架构也不是完美的,很多功能的代价是成本,这种架构决定了,TiDB对硬件的要求极高。
其次我们要考虑分布式事务的实现方式,因为没有一个分布式数据库厂商会主动和你深入探讨这方面的问题。无论厂家如何说自己的分布式事务如何完美,如何高性能,有一个事实是必须接受的,基于网络通讯的分布式事务,其效率比起内存中实现的事务锁的效率肯定是低了不止一个数量级的。因此分布式数据库必须通过一定的算法来解决这个问题。实际上可用的方法也不多,最常用的分布式事务的解决方案就是全局事务号和两阶段提交。很多分布式数据库的高性能指标都是在基于2PC的“乐观锁”场景下获得的。乐观锁可以解决分布式事务中的强一致性要求所带来的性能损失,不过乐观锁对于用惯了集中式通用数据库的我们会有些不习惯。因为在修改数据时,是不需要进行锁冲突的检验的,只有在数据提交的时候,才会进行锁冲突检查,如果存在冲突,则先提交的成功,后提交的失败。现在很多分布式数据库在早期都只是提供乐观锁的,随后才逐步发展出了普通的行锁“悲观锁”(这个概念似乎并不存在,只是与乐观锁相对应而已)。实际上选择分布式数据库的时候,我们并不一定非要要求数据库的悲观锁性能达到集中式数据库的水平,这个实际上也是做不到的。更重要的是我们的应用必须适应乐观锁,只有我们的应用能够很好的支持乐观锁,才能在今后的应用中少出现因为锁引擎的问题。如果做不到这一点,那么我们就必须要能够忍受今后高并发下的分布式悲观锁带来的负面影响。在分布式数据库应用场景下,乐观锁是最好的选择,在选择分布式数据库的时候,你一定要先相信这一点。
第三是分布式执行计划的优化,前几天我写过一篇关于国产数据库的文章,谈到优化器是所有国产数据库的痛,那还仅仅是针对集中式数据库的,对于分布式数据库,分布式计算、并行计算的环境更为复杂,因此如何优化分布式执行计划十分关键。这一点上,各个互联网公司都有十分丰富的经验,分布式协同,执行计划的优化,以及消除长尾作业是优化分布式执行计划优化中的关键点,也是难点。现在的很多分布式数据库都有执行计划预览器,这一点十分好,可以让我们可以找到某个SQL语句执行效率不佳的原因。
最后一点是你的应用场景是不是真的需要分布式数据库。每个用户选择分布式数据库的理由各不相同,我认为很多理由其实并不合理。有个用户和我说,他们的数据库运维水平太低,因此他们希望选择一款分布式数据库做云数据库来使用,这样他们就不需要去运维上百套小数据库,而只需要运维一套云数据库了。这个理由十分牵强,普通的小数据库都运维不好,那么运维一个复杂的分布式云数据库,最后能有什么效果就可想而知了。实际上这种场景,选择云平台的RDS服务可能是更好的选择。还有的用户说他们的业务量特别大,以前是跑在一台IBM P780上的,怕迁移到X86服务器上后,服务器性能不行,所以想迁移到分布式数据库上。我就告诉他,他多虑了,十多年前的IBM P780的性能,比一台8路的X86服务器差了不是一点半点,如果他们把系统从小机上迁移下来,只会跑的更快。在和我交流过的客户中,绝大多数客户的分布式数据库的选型需求其实并不充分,他们完全可以再仔细思考一下,是不是必须使用分布式数据库。
当然,分布式数据库对于某些场景还是十分适合的,比如大型金融交易系统,互联网秒杀系统、物联网采集系统等。分布式数据库可以让这些应用的逻辑得以简化,不需要手工去处理分库分表的问题。不过哪怕是这些系统,在使用分布式数据库的时候,也是需要对应用开发做一定的规范的。