一 数据库分库分表的原因
- 从访问速度来看:一个数据库正常是每秒2000请求,如果超过这个请求,就需要把数据分摊到多个数据,来提高并发处理;
- 从数据库数据容量看:一个数据库单表超过500万行,或者数据库文件超过2G,那对于读写也是瓶颈,也需要进行分库分表,来提高处理效率;
二 数据库分库分表的定义
- 分库:指的是一个库分成多个库,这些库内的表结构,表名称都是一样的,原来一个库的数据按照一定规则分在不同的数据上;
- 分表:指的是一个表分成多个表,这些表的结构一样,但是表名称不一样;
三 数据分片寻址
一个数据要插入/查询数据库,需要知道这个数据应该存到哪个库的哪个表中,需要按照一定的规则,这个规则就是寻址规则,一般有hash和时间分片两种:
- hash规则:就是用数据ID对数据库节点进行HASH取模,得到所在数据库,然后再根据库中的分表数量取模,从而得到确切的表位置。举例:订单表分成三个库,然后每个库里的表分成四个不同的表,当来了一个id是25的订单,先对3个库取模,得到1,然后25再对4取模,得到1,因此就知道这个订单应该在1号数据库的1号表;
- 时间分片规则:就是按照时间分片来规划数据库,比如一个季度一个数据库,那么一年就四个数据库,然后每个数据库的每张表是一个月数据。
优缺点:
- hash寻址,数据分布比较均匀,对于请求的处理也平衡,不会出现热点数据攻击一个库的情况。但是缺点就是扩容很麻烦,每次扩容,都需要重新计算数据位置并进行复杂的数据迁移操作;
- 时间分片寻址:优点是扩容非常简单,只要直接加入机器就可以了。缺点是数据分布不均匀,可能热点数据都是近期时间的数据,请求会大量访问同一个数据库,而其他数据库很少访问。
四 数据库中间件和分布式数据库
- 数据库中间件分为两种:proxy型和client型。
proxy型就是中间件独立部署在服务器,然后各个业务程序连接中间件来处理数据库数据;
client型就是一个第三方包,与业务程序部署在一起,直接引用;
*具体可用的数据库中间件有:
sharding-jdbc: 当当开源的数据库中间件,属于client型;支持分库分表,读写分离,分布式id生成;社区活跃,柔性事务(最大送达型事务,tcc事务)国内应用公司较多,属于可选方案;
优点:不需要单独部署代理层,维护成本低,不需要额外人手。适合中小型公司。
缺点:与项目耦合,当项目升级时,需要重新处理耦合关系;
mycat:阿里开源的中间件,支持多租户,分库分表,支持弱xa分布式事务。运维难度大。
优点:单独部署,与项目开发解耦,升级方便。
缺点:维护难度大,需要单独维护。适合大型公司。
- 分布式数据库(本身支持水平扩展的数据库):
Greenplum:是一个面向数据仓库应用的关系型数据库,它基于流行的PostgreSQL开发的支持分库分表的分布式数据库;
CitusData:citus,是PostgreSQL数据库中的一种轻量级的分库分表解决方案。
五 由单库单表向分库分表迁移方案
- 停机迁移:停机,写一个独立程序,从老库中读取数据写入到新库中;
优点:不改动现有业务代码;
缺点:数据量很大导致时间会比较长;需要停止服务;
- 停机迁移:停机,写一个独立程序,从老库中读取数据写入到新库中;
- 在线迁移:不停机,修改业务程序,一边写老库一边写新库。同时后台起一个新程序从老库老数据迁移到新库中,并且判断数据是否存在。如果数据已存在,则迁移完成。
优点:不需要停止服务;
缺点:需要修改代码;
- 在线迁移:不停机,修改业务程序,一边写老库一边写新库。同时后台起一个新程序从老库老数据迁移到新库中,并且判断数据是否存在。如果数据已存在,则迁移完成。
五 分库分表扩容方案
-
停机迁移:停机,写一个独立程序,从老库中读取数据写入到新库中;
缺点:如果已经在分库分表的基础上,说明现有数据已经非常非常巨大,因此基于这么巨大的数据进行工具导出再导入到新扩容库,是非常不靠谱的,因为时间会非常非常久,而且容易出错。 -
预先设定逻辑库:先预定好一定数量的库和一定数量的表,然后数据寻址到具体的表。后续当物理资源不够时,只要把库给迁移到不同的机器上即可。举例:
一开始定好 32 个数据库实例,每个实例表分成 32 个表;
(多个数据库实例可以在一个数据库机器上)。
从并发量上看:假设 1000/秒的写,则一共是 32000/秒 的写并发;
从容量上看:假设 500万/表 的容量,则一共是 5003232 的表容量;
这个并发量和容量,已能够满足几乎所有当前的并发量和容量要求;
网友评论