最近在整理一个系统的分布式架构扩展方案,经过了多次的迭代,总算让项目走上了正轨。
对于单机MySQL来说,水平扩展实在有限,从系统架构的角度来说,是一种纯复制的方案,也就意味着Master是5T, Slave也爱莫能助,所以这就是一个瓶颈。为了能够保证系统的弹性或者可扩展性,就需要考虑到分布式方案。
显然对于一个业务存在存储过程,业务的耦合度较高的情况下,我们要拆分为分布式架构是很困难的,主要体现在三个地方:
研发和运维对于分布式架构的理解有限,认为要改造可行,但是改动量极大,基本会在做和不做之间摇摆。
对于上层来说,希望达到的效果是一种透明平移的状态,即原来的存储过程我们都无缝的平移过来,显然在MySQL分布式的架构下,这种方案是不可行的,而且如果硬着头皮做完,那么效果也肯定不好。
对于分布式的理解,不是仅仅把业务拆开那么简答,我们始终要找到一个平衡点,不是所有业务都需要拆分做成分布式。分布式能带来好处,但是同时分布式也会带来维护的复杂成本。
为了迭代这个过程,我们首先做的事情就是把源端已有的存储过程转义为MySQL的,源端可能是SQL Server或者Oracle,表达的意思是和MySQL异构的源数据库。
开始的测试环境,我们就搭建了一套:上面有两个数据库 App和AppLog
在已有的方案里面,App上的存储过程会关联调用到AppLog的存储过程。其实这种情况下还是存在耦合的。
这个过程做好之后,大家一看业务还能够正常跑,那好,这个事情还有得干。
我们需要继续拆分,就是把有的业务App和AppLog分离开,怎么分离开彻底一些呢,就重新搭建了两套环境,一套是App,一套是AppLog,端口完全不同。
架构分离后的测试环境
5717 App
5718 AppLog
这个阶段也需要做一些改造,但是有了迭代的思想之后,难度和进度也会可控。接下来我们要进入分布式集群环境的部署。这个时候就需要考虑业务拆分和扩展的需要了。首先对于App业务来说,上面存在大量的事务,而且交易相对来说会很频繁。而另外的AppLog库来说,上面的操作相对很简单,只有数据写入和查询。这种场景下就很适合做分布式方案了,我们就可以引入中间件了。
这样我们就需要使用5个实例来模拟这个情况,其中App还是一个独立的实例,AppLog会有4个实例。
分布式集群测试环境
AppDB
5720
AppLog
5721
5722
5723
5724
架构类似于下面的这种形式:
在这里我们要引入中间件,很多同学会问我用哪个好一些,其实我的建议很简单,我们使用中间件,还是希望做得弱关联,能够满足我们的基本需求,比如是读写分离或者sharing,不要过度的耦合和依赖。
在这里因为之前也用过一些MyCAT的方案,也有一些实际的经验,所以就先拿来用了。
MyCAT中间件
8066
我们接下来说下分片逻辑,分片逻辑我们可以考虑后续的扩展性,比如我们只有4台服务器,但是完全可以模拟一个更大的集群,比如我们在此就模拟一个16个逻辑分片的集群。
对于业务来说,希望能够做到透明和统一,我们有两类业务表,那么就可能是这样的情况:
dbo_Acc_App1
dbo_Acc_App2
使用如下的方式来连接MyCAT,其实这个时候不一定真的连接到实例,但是可以做一个基本的验证。
mysql -uuser -pxxx -P8066 -h127.0.0.1
对于分布式方案来说,比如我们有16个逻辑分片,那就可能对应16个数据库,分布于4个物理节点上。但是应用连接之后,看到的数据库只有一个。
初步设计的分布式方案
>>show databases;
+-----------+
| DATABASE |
+-----------+
| AppLog |
+-----------+
1 row in set (0.00 sec)
这里我们继续做一个改进,那就是基于时间维度的分片,比如我们按照日表的维度来生成数据,那么16个逻辑分片,一年同样的逻辑的表底层会有365*16=5840个物理表来承载。这个分片的粒度和逻辑绝对杠杠的。
>>show tables;
+----------------------------+
| Tables in AppLog |
+----------------------------+
| dbo_acc_App2_20180723 |
| dbo_acc_App2_20180724 |
| dbo_acc_App2_20180725 |
| dbo_acc_App2_20180726 |
。。。。
| dbo_acc_App1_20180723 |
| dbo_acc_App1_20180724 |
| dbo_acc_App1_20180725 |
| dbo_acc_App1_20180726 |
| dbo_acc_App1_20180727 |
。。。。
+----------------------------+
52 rows in set (0.00 sec)
单独登录到一台服务器,可以看到每个库下面有两类表。
比如我们随机登录到一个sharding分片上,可以看到对应的物理表
>>show tables;
+----------------------------+
| Tables_in_AppLog01 |
+----------------------------+
| dbo_Acc_App2_20180723 |
| dbo_Acc_App1_20180723 |
。。。。
+----------------------------+
接下来说下MyCAT层面看到的几个问题:
MyCAT对于表名的大小写支持存在歧义
Show tables的表名是dbo_acc_userscore_20180803
其实表名是 dbo_Acc_UserScore_20180803才是正确的。
对于MyCAT的配置支持,有时候重启服务就能够解决
后续对于这些功能和改进,完全可以通过修改源代码来改进和完善。