什么是分库分表?
分库分表是为了解决由于库、表数据量过大,而导致数据库性能下降的问题。
然后按照一定的规则,将原本数据量大的数据库拆分成多个单独的数据库,将原本数据量大的表拆分成若干个数据表,使得单一的库、表性能达到最优的效果(响应速度快),以此提升整体数据库性能。
分库分表的核心就是对数据进行切分(sharding)及切分后如何对数据的快速定位与查询结果整合。
分库分表都可以从垂直和水平两种维度进行切分。
一、分库
1、垂直分库
垂直分库核心 就是 专库专用 。
如按照业务类型对表进行分类,将业务相关的一类表放在一个库中
但是垂直分库很大程度上取决于业务的划分,有的时候业务划分不那么清晰的时候,分库就不那么简单了。而且分库仍没有解决单表数据库量过大的问题。
2、水平分库
把同一个表按照规则拆分到不同的数据库中,每个库可以位于不同的服务器上,以此实现水平扩展。
二、分表
1、垂直分表
拆分列。基于列进行。
根据业务耦合性,将关联度低的不同表存储在不同的数据库,与微服务类似,按照业务独立划分,每个微服务使用单独的一个数据库。也可将字段较多
的表拆分新建一张扩展表,将不常用或字段较大的字段拆分出去到扩展表中。
在字段很多的情况下(例如一个大表有100多个字段),通过"大表拆小表",更便于开发与维护,也能避免跨页问题,MySQL底层是通过数据页存储的,
一条记录占用空间过大会导致跨页,造成额外的性能开销。另外数据库以行为单位将数据加载到内存中,这样表中字段长度较短且访问频率较高,内存能加
载更多的数据,命中率更高,减少了磁盘IO,从而提升了数据库性能。
优点:业务解耦清晰;高并发下,提升一定程度的IO,数据库连接数、单机硬件资源瓶颈。
缺点:部分表无法join,只能通过接口聚合,提升了开发复杂度;分布式事务处理复杂。
2、水平分表
拆分行。基于行进行。
分为库内分表,分库分表,根据表内数据内在的逻辑关系,将同一个表按条件分散到多个数据库或多个表中,每张表中包含一部分数据,从而使单张表的数
据量变小。
库内分表只解决了单一表数据量过大的问题,但没有将表分布到不同机器的库上,因此对于减轻MySQL数据库的压力来说,帮助不是很大,大家还是竞争同
一个物理机的CPU、内存、网络IO,最好通过分库分表来解决。
优点:不存在单库数据量过大、高并发的性能瓶颈,提升系统稳定性和负载能力;应用端改造较小,不需要拆分业务模块。
缺点:跨分片的事务一致性难以保证;跨库的join关联性能较差;数据不易维护
如何分库分表?
即如何切分数据,又如何整合?
对于水平拆分数据常见的有取模算法和范围限定算法。
水平拆分数据分片规则:
1、根据数值取模
一般采用hash取模mod的切分方式,如将Order表根据userId字段的某几位的值切分到N个库中(mod N,N为数据库实例数或子表数量),余数为0的放到第一个库,余数为1的放到第二个库,依此类推。
好处:这样同一个用户的数据会分散到同一个库中。
2、范围限定算法
按照 时间区间 或 ID区间 来切分。
按照时间区间或者ID区间来切分。例如:按日期将不同月甚至是日的数据分散到不同的库中;将userId为1~9999的记录分到第一个库,10000~20000的分到第二个库,以此类推。
缺点是对id有较苛刻的要求。
分库分表带来的问题
1、分布式事务
由于表分布在不同库中,会带来跨库事务问题。可以采用阿里的分布式框架Seata来做分布式事务管理
Seata:https://github.com/seata/seata
2、分页、排序、跨库联合查询
3、分布式主键:分库分表之后就不能依赖单个数据库的自增主键来实现不同数据库之间的全局唯一主键,需要一个能够生成全局唯一ID的功能,这个全局唯一ID就叫分布式ID。
4、读写分离:读库与写库都要做分库分表处理
分布分表工具
Sharding-JDBC(当当)、Cobar(阿里巴巴)、MyCAT(基于Cobar)
Sharding-JDBC中文官网:https://shardingsphere.apache.org/document/current/cn/overview/
Sharding-JDBC:轻量级Java框架,在Java的JDBC层提供额外的服务。它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。而相比之下,MyCAT是需要单独部署服务的服务端产品
参考:https://developer.aliyun.com/article/773700?utm_content=g_1000188740
END.