因此Spring的单体服务就是凭借着部署简单、适应敏捷、人性化等特质,打败了EJB,分布式系统第一次完败。但是为什么最终依然演化出了微服务架构呢?而且热度不减当年,其实我认为就是曾经EJB热度的又一次轮回,SpringCloud也开始了当年EJB之路。微服务在架构拆解之路上,甚至开始了数据库和微服务打包独立的情况,下面是微服务的架构模样:
上图是API网关进行多个微服务的调度,微服务之间互相调度,每个微服务拥有自己的独立数据库,都是从一个传统Master单库切分而来,Master库也逐渐成为数据中心库,提供基础数据交换和数据分析(OLAP)
我们看看微服务的架构和上面的EJB分布式架构多么的像,其实都是一个血脉遗传下来的,那就是分布式系统。但是微服务演化到拆库就真的好吗?我不敢苟同,咱们可以把数据库的不同数据表比喻成一个家庭的多个成员,难道把家庭成员强行拆开就一定好吗?家里原来公用一台电视机,现在拆分一个成员,就要配一台电视,难道看电视还要跑回来看吗?这就是类比了数据字段到底是冗余,还是走接口调用?这个会让设计者太痛苦的,本质是反人性的。
为什么非要这样做呢?说到底就是想让关系型数据库实现垂直切分,形成更好的性能水平提升,也就是说,问题根子出在关系型数据库身上了,关系型数据库天然就不支持分布式化,无法更好的实现数据库级的水平伸缩,所以将来一定是分布式数据存储系统替代关系型数据库的时代。因为我们如果有了一个廉价且性能强大的数据库系统,通过水平伸缩解决性能问题,我们又何必费劲的搞业务数据的垂直切分呢!这就是下来说分布式存储的关键作用。
分布式数据存储数据的分布式存储具体表现形式也就是分布式数据库,分布式数据库不同于分布式应用服务,不存在开发测试阶段费劲的发布重启,所以并不影响敏捷性;另外数据调用都集中在一个访问代理上,因此不需要像分布式应用服务那么反人性的考虑接口管理,分布式数据库的水平伸缩力,恰恰解决了微服务必须分库的尴尬问题,可以让程序员专注于数据访问的业务问题上。既然这么多好处,为什么不能大规模应用呢?问题的根源就出在事务上了!
为什么关系型数据库就具备ACID的事务的优势呢?先简单点说说事务的原理,事务就是对数据的加锁解锁,给数据行集加锁,我(事务)要处理一行数据,我(事务)就申请一把钥匙,给数据行上个锁,其他人(事务)等着我解锁了,其他人才能访问。这个操作放到以单机设计为主的关系型数据库上好解决,但是放到如今的分布式数据库环境,这就特别麻烦了,因为数据被分成片,分布在不同的机器节点库中,事务加锁就要定位到所有相关的节点,事务问题就淋漓尽致地体现出了分布式系统在网络环境中多节点协作的复杂性,协作越紧密的事情,分布式系统干起来越吃力,为什么Key/Value数据库,例如Redis用起来最舒服,也很流行,就是数据相互之间没什么协作关系。
分布式数据库事务这个够呛的问题,也没有难住伟大的计算机科学家们,例如:TIDB继承自Google Percolator,使用 Percolator 事务模型,实现了分布式事务。也就是现在又出现的一个新名词:NewSQL,传统关系型数据库ACID特性+NoSQL。
我们先说说分布式数据库的关键是什么?就是对一大块数据进行分片(分块/分区),平平整整地放到不同的物理节点上,保持每个节点的数据量差不多是最佳的,这样吞吐性能最好,若节点有的多,有的少,这就是出现倾斜了,那么数据多的节点就会承载更大的数据访问压力。
不同的数据节点有管理者进行管理,有的管理者是集中式任命的,例如HDFS的namenode,有的管理者是被推举的,例如Elasticsearch master node。总之分布式数据库就有管理节点负责调度数据节点,也有数据节点服务数据读写。就是这么一回事儿。
上图就是两种不同的数据管理方式,第一个是主从模型,例如HDFS的分块,由namenode统一负责数据块节点的分配调度;第二个是对等模型,例如GlusterFS,也就是每个节点即是主又是从,关键看自己节点的数据是否匹配请求。
我们再看看分布式事务的架构有多么复杂,就看看TIDB的架构吧!