垂直切分的缺点:
水平切分
前边说了垂直切分还是会存在单库、表数据量过大的问题,当我们的应用已经无法在细粒度的垂直切分时, 依旧存在单库读写、存储性能瓶颈,这时就要配合水平切分一起了,水平切分能大幅提升数据库性能。
1、水平分库
水平分库是把同一个表按一定规则拆分到不同的数据库中,每个库可以位于不同的服务器上,以此实现水平扩展,是一种常见的提升数据库性能的方式。
这种方案往往能解决单库存储量及性能瓶颈问题,但由于同一个表被分配在不同的数据库中,数据的访问需要额外的路由工作,因此系统的复杂度也被提升了。
例如下图,订单DB_1
、订单DB_1
、订单DB_3
三个数据库内有完全相同的表 order
,我们在访问某一笔订单时可以通过对订单的订单编号取模的方式 订单编号 mod 3 (数据库实例数)
,指定该订单应该在哪个数据库中操作。
2、水平分表
水平分表是在同一个数据库内,把一张大数据量的表按一定规则,切分成多个结构完全相同表,而每个表只存原表的一部分数据。
例如:一张 order
订单表有 900万数据,经过水平拆分出来三个表,order_1
、order_2
、order_3
,每张表存有数据 300万,以此类推。
水平分表尽管拆分了表,但子表都还是在同一个数据库实例中,只是解决了单一表数据量过大的问题,并没有将拆分后的表分散到不同的机器上,还在竞争同一个物理机的CPU、内存、网络IO等。要想进一步提升性能,就需要将拆分后的表分散到不同的数据库中,达到分布式的效果。
水平切分的优点:
水平切分的缺点:
一定规则是什么
我们上边提到过很多次 一定规则
,这个规则其实是一种路由算法,就是决定一条数据具体应该存在哪个数据库的哪张表里。
常见的有 取模算法
和 范围限定算法
1、取模算法
按字段取模(对hash结果取余数 (hash() mod N),N为数据库实例数或子表数量)是最为常见的一种切分方式。
还拿 order
订单表举例,先对数据库从 0 到 N-1进行编号,对 order
订单表中 work_no
订单编号字段进行取模,得到余数 i
,i=0
存第一个库,i=1
存第二个库,i=2
存第三个库....以此类推。
这样同一笔订单的数据都会存在同一个库、表里,查询时用相同的规则,用 work_no
订单编号作为查询条件,就能快速的定位到数据。
优点:
缺点:
2、范围限定算法
按照 时间区间
或 ID区间
来切分,比如:我们切分的是用户表,可以定义每个库的 User
表里只存10000条数据,第一个库只存 userId
从1 ~ 9999的数据,第二个库存 userId
为10000 ~ 20000,第三个库存 userId
为 20001~ 30000......以此类推,按时间范围也是同理。
优点:
缺点:
分库分表的难点
1、分布式事务
由于表分布在不同库中,不可避免会带来跨库事务问题。一般可使用 "三阶段提交
"和 "两阶段提交
" 处理,但是这种方式性能较差,代码开发量也比较大。通常做法是做到最终一致性的方案,如果不苛求系统的实时一致性,只要在允许的时间段内达到最终一致性即可,采用事务补偿的方式。
这里我应用阿里的分布式事务框架Seata
来做分布式事务的管理,后边会结合实际案例。
2、分页、排序、跨库联合查询
分页、排序、联合查询是开发中使用频率非常高的功能,但在分库分表后,这些看似普通的操作却是让人非常头疼的问题。将分散在不同库中表的数据查询出来,再将所有结果进行汇总整理后提供给用户。
3、分布式主键
分库分表后数据库的自增主键意义就不大了,因为我们不能依靠单个数据库实例上的自增主键来实现不同数据库之间的全局唯一主键,此时一个能够生成全局唯一ID的系统是非常必要的,那么这个全局唯一ID就叫 分布式ID
。
4、读写分离
不难发现大部分主流的关系型数据库都提供了主从架构的高可用方案,而我们需要实现 读写分离
+ 分库分表
,读库与写库都要做分库分表处理,后边会有具体实战案例。
5、数据脱敏
数据脱敏,是指对某些敏感信息通过脱敏规则进行数据转换,从而实现敏感隐私数据的可靠保护,如身份证号、手机号、卡号、账号密码等个人信息,一般这些都需要进行做脱敏处理。
分库分表工具
我还是那句话,尽量不要自己造轮子,因为自己造的轮子可能不那么圆,业界已经有了很多比较成熟的分库分表中间件,我们根据自身的业务需求挑选,将更多的精力放在业务实现上。
为什么选 sharding-jdbc
sharding-jdbc
是一款轻量级 Java
框架,以 jar
包形式提供服务,是属于客户端产品不需要额外部署,它相当于是个增强版的 JDBC
驱动;相比之下像 Mycat
这类需要单独的部署服务的服务端产品,就稍显复杂了。况且我想把更多精力放在实现业务,不想做额外的运维工作。
不难发现确实是比较强大的一款工具,而且它对项目的侵入性很小,几乎不用做任何代码层的修改,也无需修改 SQL
语句,只需配置待分库分表的数据表即可。
总结
简单的回顾一下分库分表的基础知识,接下来的文章会配合实战项目介绍 sharding-jdbc
在分库分表中的各个功能点。
本文分享自微信公众号 - 程序员内点事(chengxy-nds)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。