最近学习了数据库中间件mycat和sharding jdbc,它们都是用来解决读写分离和数据量过大情况下分库分表的中间件,区别在于mycat是服务器端,sharding jdbc是客户端使用的,需要导入jar包,相当于增强的jdbc;在此之前个人是从来没接触过分库分表和读写分离的,包括目前从业的公司业务也是没有用到这些技术的。公司开发的系统是一个票务结算系统,属于单体部署,数据量和并发量达不到外界互联网公司那种量;目前了解到系统中最大的数据表也仅仅是千万级的,更何况在我们的开发环境更是没有这么大数据量的。
目前公司的大数据表按我的理解也是有使用分库分表的方案的,确切的说是分表;其中一张表是ticket表,它对应的还有两张表:archive表和history表。间隔一定时间段(1年或者两三年)将数据从ticket表移到archive表,之后再移到history表。这种分表的访问完全是通过业务代码来决定的,它并不透明,仅再指定到额业务下才回去访问archive表和history表。而数据库中间件所达到的效果在开发人员看来更多的是透明的,我们并不知道分表的存在,我们依然是正常的去访问数据库。下面来主要介绍下mycat并参照我们公司的表来模拟一下选取分片规则的过程:
mycat
mycat:以服务端方式提供服务,客户端连接的是mycat,类似于代理;可以将mycat看作为数据库,它实现了数据库的访问协议,以便为客户端提供服务,需要额外部署,支持主流数据库和nosql数据库。
分库分表的一些概念
- 逻辑库,与MySQL中的Database(数据库)对应,一个逻辑库中定义了所包括的Table。
- 逻辑表,即物理数据库中存储的某一张表,与传统数据库不同,这里的表格需要声明其所存储的逻辑数据节点DataNode。在此可以指定表的分片规则。
- DataNode数据节点:MyCAT的逻辑数据节点,是存放table的具体物理节点,也称之为分片节点,通过DataSource来关联到后端某个具体数据库上
- DataSource数据源:定义某个物理库的访问地址,用于捆绑到Datanode上
- 分片规则:对表进行水平拆分和垂直拆分的规则。
分表的概念
其实并不是说所有的表都需要做拆分,简单按照数据量来说的话,一般800W以上的表最好考虑进行分库分表,mycat中的表可以分为以下几类:
分片表:数据量过大,需要根据分片规则进行拆分
非分片表:不需要拆分的表
ER表:其实ER表更多的是为了提醒我们在做分表的时候要尽量保证可能会join的表尽量保存在同一个数据分片上,减少跨库join。
全局表:即保存一些常量的表,在sharding jdbc中叫做广播表;这种表在每一个数据节点都会保存一份,这样不会产生跨库join的问题
mycat分片规则
mycat内置的分票规则包括:
分片枚举:根据特定字段,自己实现分区存储的规则;比如ticket表中如果按照订票的人的归属地来区分;
按日期范围分片:字面意思理解就很明白,这更类似于我们当前系统内的逻辑,当然我们公司的ticket标志是简单做了archive和history实际是没有按照精确时间范围分片的。
范围取模分片:先进行范围分片计算出分片组,组内再求模。
一致性hash:一致性hash 算法有效解决了分布式数据的扩容问题,在此之前对一致性hash算法也进行过学习和了解,在增加节点的时候它也能够保证我们的误差在小范围内,而不会导致大范围的分片错误。
应用指定:此规则是在运行阶段有应用自主决定路由到那个分片。这个规则字面上看好像是我们公司ticket表的最匹配的应用,可实际上包括它以及上面介绍的几个分片规则,大体上采用的都是取模之后决定分片的原理。
这里仅列举了部分分票规则,他们都和我们公司目前的分表规则比较接近,
使用mycat对ticket表进行分库分表:
我们公司的ticket表如果要采用mycat进行分库分表的话,我觉得最匹配当前业务分配的规则就是按日期范围分片。
<tableRule name="sharding-by-date">
<rule>
<columns>date</columns>
<algorithm>sharding-by-date</algorithm>
</rule>
</tableRule>
<function name="sharding-by-date"
class="io.mycat.route.function.PartitionByDate">
<property name="dateFormat">yyyy-MM-dd</property>
<property name="sBeginDate">2018-01-01</property>
<property name="sEndDate">2019-01-02</property>
<property name="sPartionDay">10</property>
</function>
配置说明:
columns :标识将要分片的表字段
algorithm :分片函数
dateFormat :日期格式
sBeginDate :开始日期
sEndDate:结束日期
sPartionDay :分区天数,即默认从开始日期算起,分隔10 天一个分区
当然对于我们系统业务规则已经确定的情况下再去分表是不现实的,这样的话系统的需求就要重新进行修改。在此只做探讨可行性。
上面的配置说明中分区天数按照我们业务的数据增长量来说,10天肯定是不行的,因为公司业务数据增长并不大,实际上1年一个分区更适合我们公司的实际情况。
全局表
我们公司内部也是存在全局表的,因为有一些信息是全球性的,而且数据量并不大,所以我想这部分表如果系统需要做分库分表,就完全可以作为全局表来处理。
<table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3"
/>
对于数据库中间件的分库分表实际工作中几乎没有过什么接触,所以学习了这门课程,可是考虑实践过程中还是只能想到一些简单的使用,以上只是针对目前我所接触到的地方做一些自己的理解,内容有限。