数据库分库分表策略的具体实现方案

数据分库分表策略的具体实现⽅案
相关⽂章:
1、
2、
3、
4、
5、
⼀、MySQL扩展具体的实现⽅式
随着业务规模的不断扩⼤,需要选择合适的⽅案去应对数据规模的增长,以应对逐渐增长的访问压⼒和数据量。
关于数据库的扩展主要包括:业务拆分、主从复制,数据库分库与分表。这篇⽂章主要讲述数据库分库与分表
1.1、业务拆分
在 ⼀篇⽂章中也具体讲述了为什么要对业务进⾏拆分。
业务起步初始,为了加快应⽤上线和快速迭代,很多应⽤都采⽤集中式的架构。随着业务系统的扩⼤,系统变得越来越复杂,越来越难以维护,开发效率变得越来越低,并且对资源的消耗也变得越来越⼤,通过硬件提⾼系统性能的⽅式带来的成本也越来越⾼。
因此,在选型初期,⼀个优良的架构设计是后期系统进⾏扩展的重要保障。
例如:电商平台,包含了⽤户、商品、评价、订单等⼏⼤模块,最简单的做法就是在⼀个数据库中分别创建users、shops、comment、order四张表。
拉丝钢板但是,随着业务规模的增⼤,访问量的增⼤,我们不得不对业务进⾏拆分。每⼀个模块都使⽤单独的数据库来进⾏存储,不同的业务访问不同的数据库,将原本对⼀个数据库的依赖拆分为对4个数据库的依赖,这样的话就变成了4个数据库同时承担压⼒,系统的吞吐量⾃然就提⾼了。
1.2、主从复制
1、
2、
3、
上述三篇⽂章中,讲述了如何配置主从数据库,以及如何实现数据库的读写分离,这⾥不再赘述,有需要的选择性点击查看。
上图是⽹上的⼀张关于MySQL的Master和Slave之间数据同步的过程图。
主要讲述了MySQL主从复制的原理:数据复制的实际就是Slave从Master获取Binary log⽂件,然后再
本地镜像的执⾏⽇志中记录的操作。由于主从复制的过程是异步的,因此Slave和Master之间的数据有可能存在延迟的现象,此时只能保证数据最终的⼀致性。
1.3、数据库分库与分表
我们知道每台机器⽆论配置多么好它都有⾃⾝的物理上限,所以当我们应⽤已经能触及或远远超出单台机器的某个上限的时候,我们惟有寻别的机器的帮助或者继续升级的我们的硬件,但常见的⽅案还是通过添加更多的机器来共同承担压⼒。
我们还得考虑当我们的业务逻辑不断增长,我们的机器能不能通过线性增长就能满⾜需求?因此,使⽤数据库的分库分表,能够⽴竿见影的提升系统的性能,关于为什么要使⽤数据库的分库分表的其他原因这⾥不再赘述,主要讲具体的实现策略。请看下边章节。
⼆、分表实现策略
关键字:⽤户ID、表容量
对于⼤部分数据库的设计和业务的操作基本都与⽤户的ID相关,因此使⽤⽤户ID是最常⽤的分库的路由策略。⽤户的ID可以作为贯穿整个系统⽤的重要字段。因此,使⽤⽤户的ID我们不仅可以⽅便我们的查询,还可以将数据平均的分配到不同的数据库中。(当然,还可以根据类别等进⾏分表操作,分
表的路由策略还有很多⽅式)
接着上述电商平台假设,订单表order存放⽤户的订单数据,sql脚本如下(只是为了演⽰,省略部分细节):
CREATE TABLE `order` (
`order_id` bigint(32) primary key auto_increment,
`user_id` bigint(32),
...
)
当数据⽐较⼤的时候,对数据进⾏分表操作,⾸先要确定需要将数据平均分配到多少张表中,也就是:表容量。
这⾥假设有100张表进⾏存储,则我们在进⾏存储数据的时候,⾸先对⽤户ID进⾏取模操作,根据 user_id%100 获取对应的表进⾏存储查询操作,⽰意图如下:
例如,user_id = 101 那么,我们在获取值的时候的操作,可以通过下边的sql语句:
select * from order_1 where user_id= 101
其中,order_1是根据 101%100 计算所得,表⽰分表之后的第⼀章order表。
注意:
在实际的开发中,如果你使⽤MyBatis做持久层的话,MyBatis已经提供了很好得⽀持数据库分表的功能,例如上述sql⽤MyBatis实现的话应该是:
接⼝定义:
/**
* 获取⽤户相关的订单详细信息
* @param tableNum 具体某⼀个表的编号
* @param userId ⽤户ID
* @return 订单列表
*/
public List<Order> getOrder(@Param("tableNum") int tableNum,@Param("userId") int userId);
xml配置映射⽂件:跌落实验台
受体激动剂
<select id="getOrder" resultMap="BaseResultMap">
select * from order_${tableNum}
where user_id = #{userId}
</select>
其中${tableNum} 含义是直接让参数加⼊到sql中,这是MyBatis⽀持的特性。
注意:
另外,在实际的开发中,我们的⽤户ID更多的可能是通过UUID⽣成的,这样的话,我们可以⾸先将UUID进⾏hash获取到整数值,然后在进⾏取模操作。三、分库实现策略
数据库分表能够解决单表数据量很⼤的时候数据查询的效率问题,但是⽆法给数据库的并发操作带来效率上的提⾼,因为分表的实质还是在⼀个数据库上进⾏的操作,很容易受数据库IO性能的限制。
因此,如何将数据库IO性能的问题平均分配出来,很显然将数据进⾏分库操作可以很好地解决单台数据库的性能问题。
分库策略与分表策略的实现很相似,最简单的都是可以通过***取模***的⽅式进⾏路由。
双接头还是上例,将⽤户ID进⾏取模操作,这样的话获取到具体的某⼀个数据库,同样关键字有:
⽤户ID、库容量
路由的⽰意图如下:
上图中库容量为100。
同样,如果⽤户ID为UUID请先hash然后在进⾏取模。
四、分库与分表实现策略
上述的配置中,数据库分表可以解决单表海量数据的查询性能问题,分库可以解决单台数据库的并发访问压⼒问题。
有时候,我们需要同时考虑这两个问题,因此,我们既需要对单表进⾏分表操作,还需要进⾏分库操作,以便同时扩展系统的并发处理能⼒和提升单表的查询性能,就是我们使⽤到的分库分表。
分库分表的策略相对于前边两种复杂⼀些,⼀种常见的路由策略如下:
1、中间变量 = user_id%(库数量*每个库的表数量);
2、库序号 = 取整(中间变量/每个库的表数量);
3、表序号 = 中间变量%每个库的表数量;
例如:数据库有256 个,每⼀个库中有1024个数据表,⽤户的user_id=262145,按照上述的路由策略,可得:
1、中间变量 = 262145%(256*1024)= 1;
2、库序号 = 取整(1/1024)= 0;
3、表序号 = 1%1024 = 1;
这样的话,对于user_id=262145,将被路由到第0个数据库的第1个表中。
⽰意图如下:
五、分库分表总结
关于分库分表策略的选择有很多种,上⽂中根据⽤户ID应该是⽐较简单的⼀种。其他⽅式⽐如使⽤号段进⾏分区或者直接使⽤hash进⾏路由等。有兴趣的可以⾃⾏查学习。
关于上⽂中提到的,如果⽤户的ID是通过UUID的⽅式⽣成的话,我们需要单独的进⾏⼀次hash操作,然后在进⾏取模操作等,其实hash本⾝就是⼀种分库分表的策略,使⽤hash进⾏路由策略的时候,我们需要知道的是,也就是hash路由策略的优缺点,优点是:数据分布均匀;缺点是:数据迁移的时候⿇烦,不能按照机器性能分摊数据。
温度远程监控上述的分库和分表操作,查询性能和并发能⼒都得到了提⾼,但是还有⼀些需要注意的就是,例如:原本跨表的事物变成了分布式事物;由于记录被切分到不同的数据库和不同的数据表中,难以进⾏多表关联查询,并且不能不指定路由字段对数据进⾏查询。分库分表之后,如果我们需要对系统进⾏进⼀步的扩阵容(路由策略变更),将变得⾮常不⽅便,需要我们重新进⾏数据迁移。
最后需要指出的是,分库分表⽬前有很多的中间件可供选择,最常见的是使⽤淘宝的中间件Cobar。
关于淘宝的中间件Cobar本篇内容不具体介绍,会在后边的学习中在做介绍。
另外Spring也可以实现数据库的读写分离操作,后边的⽂章,会进⼀步学习。
六、总结
上述中,我们学到了如何进⾏数据库的读写分离和分库分表,那么,是不是可以实现⼀个可扩展、⾼性能、⾼并发的⽹站那?很显然还不可以!⼀个⼤型的⽹站使⽤到的技术远不⽌这些,可以说,这些都是其中的最基础的⼀个环节,因为还有很多具体的细节我们没有掌握到,⽐如:数据库的集控制,集的负载均衡,灾难恢复,故障⾃动切换,事务管理等等技术。因此,还有很多需要去学习去研究的地⽅。
总之:
路漫漫其修远兮,吾将上下⽽求索。
pet铝膜前⽅道路美好⽽光明,2017年新征程,不泄步!
个⼈,欢迎订阅:

本文发布于:2024-09-21 22:39:27,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/2/133397.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:数据库   分表   分库   数据   策略   操作
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议