张亮
- 京东数科数据研发负责人
- Apache孵化项目ShardingSphere负责人
是写第一行代码的人,可以说是创始人
- 京东数科分布式事务中间件JDTX负责人
- 技术书籍 《未来架构——从服务化到云原生》作者
在2019年用闲暇时间写的
目录简介
- 分布式数据库核心功能
做shardingshpere的指导思想
- ShardingSphere的实现与规划
目前ShardingShpere的状况,以及ShardingShpere在未来一年甚至是两年的规划
- ShardingSphere的开源与社区
ShardingShpere和公司的项目不一样,它是开源的、社区的,所有人都可以看得见摸得着,可以切实的去参与它相关的建设与规划
文章目录
- 分布式数据库核心功能
- ShardingSphere的实现与规划
- 数据分片
- 分布式事务
- 分布式事务抉择
- 两阶段事务模型的得失
- 柔性事务的得失
- 新一代事务解决方案JDTX
- JDTX的架构图
- 整合分布式事务
- 弹性伸缩
- 分布式治理
- 分布式数据库解决方案
- 未来规划
- 可插拔架构
- 云原生数据库
- 透明化去O
- 国产数据库评测
- 重新认识ShardingShpere
- ShardingShpere的开源与社区
- 多元化的共享方式
- ShardingShpere采用的公司
- Welcom on board
分布式数据库核心功能
我们知道分布式的数据库是非常非常多的,每一个分布式数据库又有自己的偏重点,ShardingShpere总结出来6项功能,是我们现在或者未来最关注的方面
- 分布式存储
我们知道随着数据的不断加大,需要扩展磁盘就能提升存储,ShardingShpere关注的就是这方面,磁盘的加大是横向扩展的,不会说数据只能存储在一台物理机上,那么这台物理机我们想扩展磁盘就必须从1T扩展到2T,甚至从10T扩展到100T,那它扩展还是有上限的。而ShardingShere只要通过不停的增加数据服务器的节点,就能让存储无限的加大。
- 计算存储分离
计算存储分离所说的事情,ShardingShpere有计算端和存储端,存储端是用来存储数据的,计算短是无状态的,所以通过无限增加计算节点就可以无限增加ShardingShpere的算力,增加存储节点就可以增加存储能力。它们两个是完全分离的不相关的。但是,由于ShardingShpere后端的存储用的是数据库,所以它会比较智能的通过把计算往下推,把能下推到数据库中的计算推到数据库中,把不能下推的计算在自己的计算节点去进行计算。
- 分布式事务
分布式事务主要解决的是可能用户看起来觉得它应该自然而然就存在,但是实际上却很复杂的东西。因为事务里的最关键的四要素就是ACID,ACID在分布式的场景下并不是很容易的能实现,它一般都会有些权衡,ShardingShpere能做的分布式事务是希望用户能像本地用户一样使用具备ACID的分布式事务
- 弹性伸缩
是说当我们的数据库在增加它的计算节点的时候,可以随时通过增加机器去增加它的计算能力,那么同时可以通过增加它的存储节点去增加它的存储能力,而这一切的过程是不需要停止服务的。我们可以举个例子:当我们不能实现弹性伸缩或者是不能实现分布式存储的时候,我们想把硬盘从1T换到2T,那么需要把电脑关掉,把磁盘换掉,去让它再让电脑重启,磁盘重新挂载上去,重新提供数据库的服务。通过弹性伸缩是可以通过增加机器,然后把数据打散到数据节点去,这样的方式是完全不需要停止服务的,也就是说用户可以随时在服务运行的过程中去增加或者减少存储的节点
- 多副本
我们现在的数据存储,我们都会担心丢了怎么办,所以说存储在一个服务器上是有问题的,ShardingShpere未来所关注的是多副本的存储,保证数据只要单点落盘以后,最终一定会以同步的方式到多副本,它的数据是不会丢的
- HTAP
当我们的OLTP和OLAP同样的方式去查询,那也在ShardingShpere里通过SQL查询在线交易的数据,以及所谓的统计数据
实现方案
我们做一个分布式数据库,其实业界有两种常见的实现方案
- 一种是NewSQL
即我们重新写一个数据库,然后它的壳是数据库,也就是说仍然用MySQL或者PostgreSQL的协议,这样让用户用起来是感知的,但是存储端是完全重写的
- 用上中间件
也就是说我们去写一个透明化的中间件,这个透明化的中间件伪装成MySQL或者PostgreSQL,但是它仍然使用MySQL或者PostgreSQL作为存储,它用于接收的SQL由于会由中间件去重新解释发到存储端中去
这两种实现方式实际上各有优劣:
- NewSQL我们可以把它归结为进取型的解决方案,也就是说它的存储引擎是完全重做的
- 优点 它的性能是有保证的,因为它的架构也是完全面向分布式存储的,所以说当使用NewSQL的数据库的时候,它是一个完全面向分布式的一体化的东西。
- 缺点 它的存储引擎是完全重写的,它的存储引擎并不像我们常用的关系型数据库一样,经过了千锤百炼,经过了10年20年30年这样的时间的积累。也许NewSQL会在未来的10年去成熟,但是现在我们常用的还是像Oracle呀mySQL呀这样的关系型数据库。
- 中间件类型我们就叫稳定型,是因为我们的底层存储仍然是关系型数据库,但是关系型数据库只会化为存储,不会实现分布式相关的东西,这相关的东西都由中间件去做。
- 缺点 不是天然面向分布式设计的,尤其是它的底层存储,那么它的SQL其实会解析两遍,我说中间件会解析一遍SQL,我们通过它的语义把它发到哪个数据节点,那么这个数据节点其实仍然是一个数据库的存储端。那么这个存储端仍然要再去解析一遍SQL,所以说SQL是解析两遍,而NewSQL解析一遍
- 优点 数据库存储仍然是我们常见的数据库,那么对于DBA来说,对与开发工程师来说,它们其实是没有任何的陌生感,它仍然可以沿用这一套跟DBA相关的运维手册做事情。而NewSQL是一套完全全新的运维,我们之前的知识点可能是不能完全的复用到NewSQL当中去。
以NewSQL数据库和用上中间件两种实现方案,是不是两个完全对立的东西呢?其实并不是这样的,
首先,在16年时候发表了一篇论文,这篇论文翻译过来就是“我们真正看到的NewSQL是什么东西”
把NewSQL分成了3种类型:
- 新架构
我们国产数据库的翘楚,比如说TiBD,国外的CockroachDB
- 透明化分片中间件
ShardingShpere
- 云数据库
亚马逊提供的Aurora
这3种类型都是NewSQL,而不是NewSQL是新架构的,透明化的就不叫NewSQL,它们都是一个大类NewSQL,只是不同的实现方案而已
ShardingSphere的实现与规划
分布式存储的核心思想,也是ShardingShpere所关注的核心目标,有些目标已经实现了,有些目标未来一到两年会去实现的东西。
ShardingShpere的核心功能分为四块:
数据分片
ShardingShpere最原始的功能就是数据库的分库分表,那么它提炼出来就叫做数据分片
ShardingShpere的整体架构是上图的样子,分为运行和管理端两个方面。ShardingShpere其实是由两个子项目所组成的:
- Sharding-JDBC
就是说用JDBC的方式去连接数据库,Java开发肯定对JDBC不陌生,它是Java语音中访问数据库的统一的标准接口
- Sharding-Proxy
模拟了一个关系型数据库,让所有的连接Sharding-Proxy的程序以为它们连接的就是数据库,而Sharding-Proxy再自己去连接数据库。所以Sharding-Proxy是面向异构语言去使用的,也就是无论我们使用Java语言使用PHP语言使用Go使用Python以及使用MySQL的client的官方的命令行,以及使用任何数据库的GUI工具,都是可以像去连接MySQL,或者连接PostGreSQL一样,去连接Sharding-Proxy提供的功能,或者说样子是一样的
Sharding-JDBC和Sharding-Proxy其实是各有优缺点,不能说哪一个比哪一个更好,它们是在不同的场景下会有更好的适用的方式。上面的架构图,其实举了一个常见的场景:
我们把应用程序分成运行派和管理派的应用程序:
- 运行派 假设我们的应用程序是用Java开发的,那么它们使用Sharding-JDBC连接数据库。
这样做有什么好处呢?
Sharding-JDBC其实只是一个Jar包,这个Jar包对于用户来说是无感知的,Java的工程师应该都知道,我们用一个数据库连接池是什么样子,引入一个Jar包,用户爱怎么编程怎么编程,没有影响,Sharding-JDBC也是这样的,就是会让大家认为它是一个数据库的连接池,它不会有任何影响,只不过是数据库连接池的作用是让我们的连接被缓存,然后去提速,连接复用,Sharding-JDBC这套应用事让我们运行向多个数据库的访问或者说是面向单个数据库的访问,被Sharding-JDBC打散到库里去,去管理
- 管理派 是说由用户直接去连接Proxy,再由Proxy去连接数据库
上图也可以看到,它们两个的部署架构上的区别,
- Sharding-JDBC是无状态的,无中心化的,和业务应用部署在一起的
也就是说业务应用如果挂掉了,Sharding-JDBC也就挂掉了;用户应用如果起来了,Sharding-JDBC就起来了,它其实是一个没有中心化的,所以说它非常适合像k8s呀这样的东西去做服务化的治理框架,跟springCloud或dubbo一起去使用,因为它会随着服务化框架去做动态的负载均衡
- Sharding-Proxy 比Sharding-JDBC还多一跳
看到上面的架构图里,看到当用户去访问Sharding-Proxy时候是一次网络的请求,Sharding-Proxy再去连接数据库又是一次网络请求。而用Sharding-JDBC可以看到它是直接去连数据库。
所以比较建议在运行态如果是java的应用程序,用Sharding-JDBC去处理,如果不是java的程序或者运维的同事想去看一下我们的数据是什么样子、管理下数据库,用Sharding-Proxy会非常合适。
最后,看到上图最左边有一个叫注册中心橘黄色的部分,我们存储分片配置及原始数据的地方。当我们的分片配置进行了修改后,其实是由注册中心推到我们的Proxy和JDBC的实例中的,也就是说Sharding-JDBC和Sharding-Proxy连一个注册中心,它们的分片策略都是一样的,它们的核心功能都是一样的,它们不一样的只是接入端,这个接入端是为了不同的用户场景使用去适配的,所以ShardingShpere是由它的核心功能,加上接入端去组成的。
核心流程
ShardingShpere其实是由它的核心的部分和不同的接入端去组成的,那么它的核心流程是非常像一个数据库的核心流程,通过上图我们也可以看到核心流程:
-
SQL解析
因为SQL是用户传过来的一个字符串,这个字符串表示了什么,我们到底去怎么理解它,怎么去解析它,这是用经典的编译原理去做。看一个select * from table
,我们就去搜from后面是什么,是一个表名,如果是的话结束了这就是表名,SQL解析是不是这样的呢?当然不是,一定要通过词法分析器、语法分析器,然后把它组成一个抽象语法树,也就是说SQL因为是一个编程语言,它不是很简单的一个from
后面一定要跟表名,也很有可能是一个子查询,子查询里面很可能还是子查询,所以它其实是一个无限递归的抽象语法树。
那么ShardingShpere也是通过编译原理的原理,通过词法分析器加上语法分析器,将它组成一个抽象语法树,然后供我们后面去理解。
-
SQL的路由
当我们理解了SQL之后,我们就会知道这个SQL它应该被路由到何处去,因为我们ShardingShpere的目标是向一个数据库一样去使用分布式的数据库,所以我们举个例子:
假设我们的数据是按照奇偶去分片,id是奇数的放在第一片,id是偶数的放在第二片,那么用户其实不需要知道什么是第一片什么是第二片,由ShardingShpere自动去给他们路由到第一片或者第二片
这个就是SQL路由的功能,它自动识别出来sql里面的分片键,并且根据分片策略去指配,并且如果分片是1,就应该根据用户提供的分片策略去路由到第一分片去。
这就是ShardingShpere的路由模块,是支持:
- 分片路由(分库+分表)
- 指定支持分片和广播路由
假设我们是根据ID来分片的,但是这次查询时根据用户的年龄或生日去查询,它一定是一个全查询,没有分片键,它会打到所有的数据片,然后把数据进行聚合。另外有些sql是不可能带分片键的,比如建表语句,它一定是广播建表
-
SQL改写
我们知道这个SQL应该路由到那个库和那个表的时候,就可以进行SQL的改写。
因为我们知道当ShardingShpere
- 路由到一个库的时候,其实是不需要改SQL的,因为我们只需要改下路由的数据源就可以。
- 如果路由到表,这就需要改SQL,我们面向逻辑表开发,假设这个表叫t_user,如果奇偶分片,第一个叫t_user0,第二个叫t_user1 ,这就需要去改SQL。这个是SQL改写的最基本的能力,我们将它正确性保证,就是把表名改对。
后面还会有些SQL改写,SQL优化相关的东西,我们可以叫它自动补列,还有很多很多的东西。可举个例子,比如说当我们去进行,order by
查询的时候,我们的select projection
(即select后面的item)如果不包含后面的order by
的item,对于数据库来说,是没有问题的,因为数据库是有源数据的,虽然select projection里并没有这些东西,但是数据库里能找到,它去排序就好了。但是对于ShardingShpere来说,它不知道,因为它是需要把数据从数据库里取出来,然后再进行排列,如果是数据打成两片,打中一片就不需要排序了,因为直接返回就好了,或两片以上是需要由ShardingShpere进行重排序,因为它的数据本身有序,但是合在一起是不一定有序的,所以说这就需要重新去排序,那么如果我们的select projection里并没有写这个字段的话,我们要根据这个字段排序,一定是排不了的,因为我们这个字段没有从数据库里取出来。那么这样怎么要求用户去写sql,是不是要求用户因为你的order by的排序用到了shardingshpere,所以你必须在select projection里把这个排序列写上,不写就报错,这种其实对于用户来说不愿意理解和接受这样的改动,因为本身sql是能用的。ShardingShpere做的就是发现order by 的item里面的column是select projection里没有的,它会自动去补列,补在后面,并且把resultSet的metadata改掉,返回的时候对于用户来说不可见,这是其中的一个补列。
补列的东西有很多,sql改写的部分也有很多。
-
SQL执行
SQL改写结束之后,后面可以开始SQL的执行,也就是我们常说的执行引擎,而SQL的执行引擎其实是在ShardingShpere中是比较复杂的一个部分,也就是说我们SQL可能会打到多片并且执行。假设我们是一个互联网公司,我们有海量的数据,假设我们分了6400片,这在京东不是一个很不常见的事,是非常常见的,一个数据库分成几千片是非常常见的,如果我们真的想执行一次全查询,我们怎么查,
- 我们是不是创建6400个线程,并且创建6400个数据库的连接发到数据库去,然后把数据并行的取出来做归并。
- 还是6400个一个个去拿
第一种一下数据库的资源就耗尽了,然后系统的资源也由于创建很多的线程也耗尽了。
第二种就是太慢了,6400片实在接受不了。
所以说ShardingShpere的SQL执行器是可以在资源和性能之间去做平衡的,它可以让用户去配,比如打到一个数据库里最大消耗的链接数是多少,那ShardingShpere就会通过那么多的链接去合理疏导它的节点。比如说一个数据库分了1000片,然后这个用户允许一个数据库只能用10个链接,那么ShardingShpere会把这个数据是1000片的链接打成每个链接是100个表,然后去执行。如果用户配置成一个数据库只能有5个链接,ShardingShpere会把链接分配成每次查询有200个表,它是一个可以去控制资源的智能化。
另外执行引擎是ShardingShpere和数据库打交道的最关键的地方,所以说我们和事务相关的东西是在执行引擎里做的,事务之下的多副本也是在执行引擎里做的
-
结果归并
当sql执行完了之后,它如果打到一片当然没有问题,直接返回结果就好。如果打到多于一片其实做结果归并,就是如何能让打到多片的数据像打到一片的数据一样返回回来,那么归并会通过叫流式归并、内存归并、装饰器归并去归并
分片策略定制化
上图可以看到ShardingShpere的分片策略是什么样子的,这可能跟数据库产品的不太一样,就是说数据库的分片策略一定是定死的,要不然就是范围分片要不然就是哈希分片,因为没有让用户可编程的接口,而ShardingShpere是一个数据库中间层,它有用户可编程的接口,从上图也可以看到我们可以写一个Java类,这个class就是一个分片策略,然后里面想怎么写都是没有问题的。第二种是行表达式,上图中的行表达式t_order_$->{uid % 8}
是什么意思呢?就是说前面的t_order是这个表的名字,那么$->是inline表达式开始的标记,然后会被两个{}包围,大括号里uid % 8 ,到这里就看的比较清晰了,这个行表达式的意思我们拿uid这个字段去分成8片,假设uid=1,分片结果就是t_order_1,如果uid是8,分片结果就是t_order_0,这个相信大家都能看的懂。
对于上图的哈希、范围、标签、时间、复合的分片策略,在未来ShardingShpere都会提供这些策略的定制化方式,让用户可以非常方便的去配置,而现在用户可以配置的方式就Java类、行表达式两种。
ShardingShpere其实还开放了复合分片,比如我想用户Id去分库,order_id去分表,或者用户Id去分库,orderId和时间范围去分表,这些都是可以的。再举个例子,我想用id的后四位拿出来用加密算法算出来,然后再%8去分片,这些都是可以的,当时就可以做的。
分布式事务
其实对于数据库来说,最主要的两个功能,
- 查询
查询要能支持多维度查询,就是通过sql,还有就是能查的快,我们常说的查询优化器
- 存储
要保证数据也是能存的快,还有就是数据不丢,数据不丢和一般的文件系统存的不丢稍微有些不一样,就是数据库所谓的事务,是事务ACID中的D持久性
事务更加复杂,有原子性、隔离性、一致性、持久性,对于一个数据库来说,事务是很关键的一点,那么ShardingShpere在分布式事务里面是如何处理?
分布式事务抉择
首先,分布式事务都有一个抉择,就是如果稍微了解分布式事务,都会知道数据库MySQL也好或者各种的原来的数据库解决方案也好,都会提供一个标准的解决方案:
- XA
我们常见的两阶段提交,它其实是不用用户做任何改动的分布式事务解决方案,其实有很多XA的成熟的框架ATomikos、narayana
- 柔性事务
最近10年应该也会被洗过脑,XA有很多的问题,比如事务我们并需要ACID,可能我们只要它的最终一致性,最终一致性一定就是牺牲了A或者C,反正我们要分布式,这样的话会有各种柔性事务,比如TCC,比较常见的像Apache的项目Saga,另外阿里去开源的柔性事务叫SEATA,它是一个自动补偿的机制
这两种方式,其实我们没有更好的抉择,如果非要抉择,那应该就是上图的一句话“外柔内刚”,就是我们系统之间的调用时是外部调用用柔性事务,事务内部的调用时使用刚性事务。当然这只是一个使用场景,具体还要根据大家的业务来说。
ShardingShpere在这方面是怎么做的呢?它是用的多个数据库,但是它并不希望用户指定打到了多个数据库,它只希望用户像用一个数据库样去用,所以ShardingShpere提供了本地事务的API,也就是只用本地事务的API commit
、rollback
去管理事务,而实际上ShardingShpere有一个事务管理器,会有各种各样的接口,有一个事务管理器实现了XA的事务管理器
- 看上图紫色的就是ShardingShpere提供的XA的事务的提供者,包括了刚才说的Atomikos、Narayana,然后如果还有XA的事务解决方案,只要实现了ShardingShpere的API就可以引过来,这个也是在刚才去和大家介绍注册中心的时候说过的,在ShardingShpere里面一切实现都是SPI,所有的东西都可以由用户自己来去写,它只要满足了ShardingShpere的SPI的接口,它就可以融进来。
- 另一条线就是ShardingShpere的柔性事务,我们叫它BASE,柔性事务目前就支持了两块Servicecomb和Seata,Servicecomb目前因为还没有整合的很完整,不过却是可以支持可以用;Seata的话因为整合的还比较完整,所以目前用在ShardingShpere的主干项目中。
两阶段事务模型的得失
事务是需要权衡的,为什么需要权衡呢?就是它没有一个正式的大家都满意的解决方案,如果有的话就不需要权衡了。所以说我们看一下,两阶段的事务是不是有得有失,
柔性事务的得失
首先柔性事务也是支持分布式的,要不然就没有必要提了,它的并发性能其实是比XA或者两阶段的提交会有提升,但是我们去看柔性事务的损失也不少
- 损失了四要素的两个要素
一致性和隔离性,因为追求的是最终一致,它的隔离性也不支持事务所有的该有的隔离级别。
- 业务侵入
如果大家见过TCC的方案可能就会知道,TCC里的T叫try,第一个C是confirm,第二个C是cancel,就是说如果你想实现隔离性就需要写try层的,如果想实现回滚需要写cancel方法,只有confirm不用写,但是confirm其实是用的业务逻辑,所以TCC三点都要用户去写,这个对于一个数据库来说,应该是不能接受的,对于服务框架可以理解,因为它是一个用户编程的接口,对于数据库来说,我们不可能在里面写一些业务逻辑放在数据库中,所以说TCC其实是不太适合数据库事务。当然我们对接的Seata和Servicecomb,其实Seata的compensation用户去做,因为Seata也有SQL的控制能力,可以把用户的insert自动转成delete,可以把用户的update 快照记下来自己返回回去,但是这种方式是可以去满足最终一致性,但是不能保证强一致和隔离性。当然至少可以不让用户去通过编程去开发了。
新一代事务解决方案JDTX
所以说ShardingShpere其实一直在致力于做一个新一代事务的解决方案,这个事务的解决方案希望它能少一些权衡,多给大家带来一些收益,ShardingShpere新一代的事务解决方案叫JDTX
- 分布式 & 1PC
1阶段提交的分布式事务,它完全不用两阶段提交的方案,那么它就屏蔽了两阶段提交方案的很多缺点,比如说可能并发性能低,可能在提交时候如果出了问题会有不一致这些档期
- 事务愿义支持
ACID在JDTX里都支持了,这样其实就是去屏蔽掉了柔性事务的一些缺点,因为柔性事务是不能完全支持ACID的,它毕竟是最终一致性,或者说它应该不能支持所有的隔离级别。
- 高性能
JDTX的设计理念,如果讲明白,大家应就能明白它其实插入性能比不开事务还要高,然后它的查询性能会略低于查询事务,但是会比分布式事务要高,会比XA要高
- 高可用
XA没有高可用,但是JDTX因为是自己做的,它会有高可用,它会弥补掉互联网中高可用这个不足的缺点
- 跨多元数据库
它是一个跨多元数据库的方案,也就是说如果现在的数据库,如果自己是分布式的,它能保证自己的数据库里边的事务是一致的,那么ShardingShpere其实它的定位不是一个分布式数据库,它是一个分布式数据库之上的调度管理层。也就是说被ShardingShpere所管理的事务的数据库是可以跨多元数据库,去写这个事务的。这个怎么理解?举个例子,我的第一个事物写在了mysql中,第二个事务写在了PostgreSQL中,它们两个可以保证一个事务。或者说甚至未来可以做到第一个事物写在mysql,第二个事务写在了redis中,它们仍然可以保证一个事务
JDTX的架构图
上图也没有全部展示JDTX的架构,因为毕竟确实很复杂,我们大致看下
- MVCC引擎
在上图最大的中间的一块,所有的现代的数据库的事务都是由MVCC的方式去做的,那么JDTX是完全重新的实现了一个MVCC的引擎,通过这个引擎去管理我们的事务,我们的活跃事务。
- WAL
图中在MVCC引擎的上面,其实是事务的预写日志,就是我们先把数据以顺序的方式写到WAL中去,那么就不会丢了,然后在MVCC引擎中,通过我们正确的mvcc本身所具备的隔离性去做查询,去保证事务。真正的业务数据其实是在业务数据库中,是通过WAL写进去的。而WAL写业务数据库是完全异步的,是不需要占用事务的提交时间的,这也就是说事务为什么会快,为什么比不开事务还要快。就是因为它只要落到WAL里就结束了,不用真的去写到数据库里,数据是不会丢的
JDTX的亮点:
- 没有undo日志
我们看到事务其实是写到了mvcc引擎中,那么当事务去回滚的时候,其实是MVCC引擎把这个数据删掉了就可以了,它其实并不需要说还有个undo日志,然后再把WAL中的数据再删,因为事务在没有提交的时候,会进MVCC引擎,不会进WAL。所以说它没有提交的话,只要把内存中的数据删除,只有提交的时候才会真正的去进WAL,然后真正的去进MVCC引擎
- 异步刷盘
这个刚才聊过了,就是事务数据只要进了WAL,就存储成功了不会丢的,它不会真正进到数据库,因为WAL要比写数据库要快,因为WAL是一个无索引的顺序去写的,有点像kafka那种东西,一行一行顺序的。写到数据库里就不一样,首先要建索引,然后索引又是一个Btree,它本来就是比顺序写要复杂的多。所以它的性能会很高,它是写到WAL就结束了,然后异步刷盘就好了
- 无损的事务方案
因为JDTX是我们自己写的,所以MVCC引擎本身就支持事务的四种级别
- 活动事务与数据存储分离
凡是在事务中的数据,我们就叫它活动数据,这个是放在MVCC引擎中的,那么不在事务中的数据其实就是冷数据,它不在MVCC引擎中,已经存到了数据库里
- 开发成本最小化
像MVCC这块,有论文,我们有很多相关的实现,比如WAL、MVCC中的一些内存数据的存储 也都是有开源的方式去做的
整合分布式事务
可以看到,右边绿色的JDTX和别的Servicecomb等提供事务的解决方案是一致的,都是通过ShardingShpere的SPI加载的,对于ShardingShpere来说,对于用户来说,它不需要感知,JDTX也可以完美的放到ShardingShpere的整个的体系中去
弹性伸缩
目前还在孵化中,但是起始alpha版已经可用了,但是我们想最终提供给大家的应该是稳定版,肯定不是alpha版,或者beat版,所以说为了谨慎起见,还是说是在“孵化中”这三个字
弹性伸缩是什么意思呢?ShardingShpere的弹性伸缩是指做数据的迁移,它的数据迁移的能力,是当我们想去进行数据迁移的时候,是不需要停止服务的。
弹性迁移
ShardingShpere做数据迁移,旧的库仍然去提供服务,新的库只供迁移去使用。所以说在ShardingShpere中存量数据是通过历史数据迁移到新的库中,而我们业务的应用仍然不停的往旧的库中去写东西这样的过程。所以说在迁移的过程中,业务应用是不需要去感知新的数据库的,它仍然向旧数据库里写,而我们的存量数据一致在迁移,它们会通过ShardingShpere新的分片规则去写到新的库中去,这个库比如说原来是两个库,现在分成了四个库,没有问题的。再比如原来由4个库,现在没有那么多数据,合并成一个库也是没有问题的。
当历史数据迁移完了之后,由于旧的数据库一直在提供服务,所以说还是有增量的数据,这增量的数据通过binlog的方式,去订阅。也即是说ShardingShpere有一个模块叫ShardingScaling,它是伪装成一个MySQL的从库,那么通过这个从库去向旧的库中订阅数据,订阅完了数据,再通过ShardingShpere去写到新的库中去。
当我们认为增量数据已经追上了位点的时候,我们只要把旧的数据库设置成readonly,这时可能这一瞬间前端用户在更新的时候,会显示什么数据库xxxx,请再试一次。这个时候其实数据就已经完全追上了。那么ShardingShpere就会把数据源切回去,用户再刷新一次,它马上就能去做写入。但是查询时不能受任何影响的,这个是弹性迁移的能力。
硬性迁移
如果数据的分片使用哈希分片的话,那数据扩容也好必须要迁移,比如说就500片,500万写到0片,500万01写到了新的片去,那其实是不需要迁移的,它只要有个范围巡检、一个调度模块,到了预值以后,直接去建一个新的片。
范围扩容其实会涉及到一个垃圾回收,就是数据的删除,比如原来有1到20片,现在删了400万数据,它会有一个涉及到压缩的过程
分布式治理
ShardingShpere其实是由大量的东西跟分布式治理相关的,很多其实单拿出来是一个独立的。不过相对来说比较小,就都放在分布式治理里面
- 服务治理
是数据库中间件吗,数据库相对于ShardingShpere来说就是服务,还有ShardingShpere本身,比如Sharding-Proxy其实也是服务,服务治理就是包含数据库和Sharding-Proxy本身的高可用,本身的配置、本身的熔断、禁用相关事情
- 数据治理
存在数据库里面的数据,然后可以为它进行治理,这个包括数据的脱敏,也就是说用户可以不改一行SQL,然后把它们想去加密的一列,比如这一列是密码,然后去加密,通过它们配置的算法去加密。还有一些权限相关的东西,比如这个数据库只有这个租户有权限去看。还有未来要去做的一些SQL的审计,黑白名单都是可以在数据治理里面去做的,因为一切都是SPI
- 可观察性
ShardingShpere因为本身不是做这个的,它本身没有必要完全再写一套可观察的平台,所以ShardingShpere所选择的是使用了OpenTracing协议,因为OpenTracing协议是可视化里面的一个标准协议,协议的对接方可以是Skywalking这些opentracing支持的开源产品,ShardingShpere可以把性能监控的这些东西通过OpenTracing协议发出去,那么可以通过这样的工具去探讨流程或者叫拓扑图、调用链以及性能分析相关的事情
分布式数据库解决方案
SharingShpere作为分布式数据库解决方案的样子是什么呢?
这张图其实有点像MySQL,
- 最上面是所有的接入端,这个是完全从MySQL上面copy出来的,因为ShardingShpere完全支持MySQL协议,当然同时也支持PostgreSQL协议,那用户通过MySQL或者PostgreSQL的任何客户端或者任何开发语言,都可以去连ShardingShpere。ShardingShpere最上层其实是一层数据库的协议,和MySQL返回的标准是一样的
- 下面那个紫色的东西是介绍的核心
- 再下一层是JDTX,跟事务相关的东西,JDTX包含的LSN是事务的ID
- 最下面一层是数据库 可以是MysQL,可以是PostgreSQL,可以是任何东西,未来甚至是Mongodb都没问题。对于DBA来说如果是MySQL,完全可以用以前的监控治理工具去继续做MySQL的运维
未来规划
可插拔架构
可以看到ShardingShpere的架构左边是技术架构层,分为四层,
- 最上面ShardingShpere能让它们像用原来的东西一样去用,接入层其实就是三个端
- 驱动端 如果用户的程序是Java程序,用JDBC就可以去连,未来会支持Redis呀Mongo呀这样的驱动端
- 代理端 用户是不是Java的开发人员没有关系,哪怕dba也行,通过MySQL协议、PostgreSQL协议都可以去连。目前虽是关系型数据库,未来可定会向其它的数据库去接入进来,因为原理都一样,相对来说关系型数据库更麻烦,会接入Redis、Mongodb
- Mesh端 这个其实也在规划中,因为ShardingShpere是一个开源的东西,要做的东西实在是太多了,规划出来不一定有时间做。Mesh端就是ShardingShpere会做一个Sidecar会做一个Operator,会以后和k8s一起愉快的玩耍
- 第二层就是SQL解析层 ,可以看到目前已经支持了4种关系型数据库的SQL解析器,但是说实话MySQL做的最好,其它三种PostgreSQL次一点,Oracle、SQLServer本来就非常难。未来也会做一些NoSQL的命令解析,比如说Redis、Mongo这样的命令
- 第三层内核层,会分成查询引擎、事务引擎(更新引擎),查询引擎是今后一年要去规划的重要的事情,包含SQL查询优化、kv查询优化
- 最后一层是存储访问层,就是我们最终的数据库,分为两种
- 驱动 通过驱动去连数据库
- 协议 我们通过PostgreSQL的协议,然后用NIO的方式去存储
右边是功能架构层,分为
- 数据分片 分库分表是分片,其实也没有那么简单,读写分离也算是分片,只不过是读放到一片,写放到一片,多副本也是分片,只不过是放到多副本。所有这些东西是插拔上去的,也就是说数据分片这个能力,可以像大家用操作系统一样,装个软件装进去了,不用删掉没有问题
- 分布式治理 也是可以插拔的
云原生数据库
分布式数据库和云原生数据库还稍微有些分别,云原生数据库是跑在k8s之上的,ShardingShpere会有一个Sidecar,如果大家了解k8s、isto这样Service Mesh大家会对着个架构不是非常陌生,就是服务之间的访问通过Service sidecar去访问,数据库之间的访问通过Sharding-Sidecar
透明化去O
ShardingShpere其实可以做到,前端是Oracle的协议,后端是以分片的方式存到MySQL,这相信大家都能理解,因为就是中间做一个转换,如果我们直接把Oracle的程序写到MySQL里肯定有问题,因为MySQL可能没有那么大的承载量,那么ShardingShpere只要开好分片策略就可以,让oracle的数据进到MySQL里去,并且分好片,并支持分布式事务。
国产数据库评测
因为ShardingShpere在未来可以支持多写,也就是说我们可以写一份数据到我们的Oracle或者MySQL实现上的数据库,然后还可以支持一份国产的数据库,因为现在大家都是用国产数据库的需求,但是它是不是真的能承载业务,可能是不是还要看看,所以可以同步多副本去写国产数据库,去进行数据的比对,比如跑了一个月,觉着差不多了,可以切过去了,然后MySQL就变成了副本的存一份,国产数据库就变成数据,再过一个月可能MySQL就可能觉着MySQL不要了,过1个月不够就跑一年,只要有钱有机器都可以
重新认识ShardingShpere
ShardingShpere已经开源4年了,这4年中可能有不同的人在不同的阶段去看过ShardingShpere,然后在那个阶段可能会给他们留下一个印象,觉着ShardingShpere就是这个东西,但是实际上ShardingShpere可能有点不一样了
分库分表的中间件
以分布式为核心的可插拔方案
Java开发框架
因为它确实有个Sharding-JDBC的接入端,大家就以为是个Java的框架,但是ShardingShpere是有Sharding-Proxy,将来也会有Sharding-Sidecar。Sharding-JDBC是java开发框架,但是整个ShardingShpere是多形态多接入端的东西
NewSQL的竞品
其实我们的定位是数据库之上的解决方案,数据库是ShardingShpere的子部分,ShardingShpere会提供存储端之上的治理的能力
All in One的解决方案
比如说所有的都想通过ShardingShpere去实现,没问题是可以的,但是ShardingShpere本身是一个开源项目,是不会把公司的业务信息弄过来放上面,比如说ShardingShpere能不能对接你们公司的工单系统,可以但是绝对不能放到开源里面去。所以说ShardingShpere是提供的一个微内核 开放平台,像对接工单也没问题,实现ShardingShpere的SPI就可以
ShardingShpere的开源与社区
ShardingShpere其实不是个人的或者团队自己的,它是一个apache基金会的项目,也就是说它希望更多的人去参与开发,因为光靠一个团队一个人是不能承担ShardingShpere这么大的工作量的,比如我们公司可能用MySQL的多,然后我们可能会把精力放到MySQL,有的公司可能用PostgreSQL的多,那他们要是加入ShardingShpere社区把精力放在PostgreSQL,这样才可以做,因为只靠我们做完了MysqL,再做PostgreSQL,也许可能是两三年后的事情。
所以说ShardingShpere的生态其实是很广大的,那就希望大家能参与到开源社区一起去做,能给你带来更大的收益,最直接的收益可能是你们公司会用到了,对个人的收益来说
- 给你带来更好的职业生涯
- 喜欢做技术人员,它会带来更大的乐趣
像公司里的项目,我不做了,项目的pr再好我都不看了,你的努力都没有价值。ShardingShpere是Apache基金会的项目,除非哪天apache不玩了,但是这个可能性微乎其微,因为apache到现在已经有了21年,是从99年开始的。ShardingShpere不会因为个人的喜好、社区个人的喜好,让大家的努力化为乌有。
ShardingShpere其实是社区由于代码,更愿意维护一个active很高,社区里总有热心的人去维护去改进,比总盯着代码要好,因为只要有人在代码可以重构可以重写,完美的代码没有人其实也就离它的最终的退休不远了。
我们去信任我们的合作伙伴,比如apache的pr有bug,这可定不是他故意写出来的,没有人会这么做的,但是会有一个完整的自动化测试流程,这样只要你写的代码过了我们的自动化测试,不会对我们的项目产生重大的bug的影响,当然自动化测试也没有做的特别好,也需要社区的同学一起完善自动化测试。
社区也有高级的用户、低级的用户,初始的用户就是刚接触的,那刚接触的用户所有的问题直接去问,核心开发者或者社区的几个人可能也忙不过来,因为大家毕竟是还要写代码,还要生活,所以说会创建自助的渠道,所有的问题都可以通过自助的渠道去探讨,比如说文档、微信群,在微信群里问问题可能会有其他热心的人会帮助
所有的开发是公开的,所有的issue、所有的代码、所有的讨论都是能在github上看到,能在邮件列表里看到。我们的工作模式是远程的,我们不会说今天要写这个代码,然后一个小时后,你要把代码提上去,因为它很有可能会没有时差,我们用远程的方式去工作,所以这就要求我们的沟通是远程的沟通,不是交互式的沟通,像我们是使用微信那样的沟通,有时我问一个很短的话,然后另一个人去回复,我再问一个很短的话,通过不断的交流才能get到相互的意思,这样的话,这种远程的工作模式其实是低效的,因为你问我“会做这一块吗”我可能第二天才能回复,因为我可能有8小时的时差,这种来回三四次也就断掉了。你要想到的是你所发的邮件是不会在马上实时的去回复,那你的邮件会写的更精准更详细的去描述你要描述的事情,这些邮件累积下来是财富,因为所有的讨论回复就跟代码一样是就会留存到apache的邮件列表里了
多元化的共享方式
这些是我们能够对ShardingShpere贡献的方式,
有很多种方式,代码只是其中一种。其它的比如说去分享,去把首页写的更好,把文档写的更好,把文档去翻译去帮助社区都是可以的,贡献方式是不拘一格的
ShardingShpere采用的公司
官方登记的有120家公司在采用,当然这个远远没有get到所有的采用的公司。
Welcom on board
https://shardingshpere.apache.org
https://github.com/apache/incubator-shardingsphere
mailto:[email protected]
官方公众号