导图社区 数据库分库分表
关系型数据库本身比较容易成为系统瓶颈,单机存储容量、连接数、处理能力都有限,下图介绍了关系型数据库、非关系型数据库、数据拆分、分库分表中间件、分库分表面临的问题。
编辑于2021-09-20 04:04:56数据库
类型
关系型数据库
数据关系模型基于关系模型,结构化存储,完整性约束 -基于二维表及其之间的联系,需要连接、并、交、差、除 等数据操作 -采用结构化的查询语言(SQL)做数据读写 -操作需要数据的一致性,需要事务甚至是强一致性
优点
保持数据一致性
可以进行join等复杂查询
通用化,技术成熟
缺点
读写经过Sql解析,大数据量、高并发下读写性能不足
对数据读写或修改数据结构时需要加锁,影响并发操作
无法适应非结构化存储
扩展困难
非关系型数据库
- 非结构化的存储 - 基于多维关系模型 - 具有特有的使用场景
优点
高并发,在大数据下读写能力较强
基本支持分布式,易于扩展,可伸缩
缺点
join等复杂操作功能较弱
事务支持较弱
通用性差
无完整约束,复杂场景支持较差
数据拆分
经测试在单表1000万条记录一下,写入读取性能是比较好的. 这样在留点buffer,那么单表全是数据字型的保持在800万条记录以下, 有字符型的单表保持在500万以下.
拆分模式
水平拆分
当一个表中的数据量过大时,我们可以把该表的数据按照某种规则,例如userID散列、按性别、按省,进行划分,然后存储到多个结构相同的表,和不同的库上。 根据数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多个数据库上
典型分片规则
1. 按用户ID求模,将数据分散到不同数据库中, 具有相同数据用户的数据都被分散到一个库中
2. 按照日期,将不同月甚至日的数据分散到不同库中
3. 按照某个特定的字段求模,或者根据特定范围段分散到不同的库中
优点
拆分规则抽象化
不存在单库大数据、高并发的性能瓶颈
应用端改造较少
提高了系统的稳定性及负载能力
缺点
拆分规则难以抽象
分片事务一致性难以解决
数据多次扩展维度及维护量极大
垮库join性能较差
垂直拆分
将不同的表拆分到不同的数据库中
优点
系统之间整合或扩展容易
业务清晰,拆分规则明确
数据维护简单
缺点
由于垂直切分是按照业务的分类将表分散到不同的库,所以有些业务表会过于庞大,存在单库读写与存储瓶颈,所以就需要水平拆分来做解决
部分业务表无法join,只能通过接口方式解决,提高了系统复杂度
受业务限制存在单库性能瓶颈,不易数据扩展及性能提高
事务处理复杂
拆分规则
能不拆分尽量不拆分
如果拆分则要选择好合适的拆分规则,提前规划好
数据拆分尽量通过数据冗余和表分组来降低跨库join的可能
表分组(Table Group)是解决跨分片数据 join 的一种很好的思路,也是数据切分规划的重要一条规则
由于数据库中间件对数据join实现的优劣难以把握,而且实现高性能难度极大,业务读取尽量少用多表join
分库分表中间件
cobar
阿里 b2b 团队开发和开源的,属于 proxy 层方案,就是介于应用服务器和数据库服务器之间。应用程序通过 JDBC 驱动访问 cobar 集群,cobar 根据 SQL 和分库规则对 SQL 做分解,然后分发到 MySQL 集群不同的数据库实例上执行。早些年还可以用,但是最近几年都没更新了,基本没啥人用,差不多算是被抛弃的状态吧。而且不支持读写分离、存储过程、跨库 join 和分页等操作。
不支持
存储过程
读写分离
垮库join
分页
atlas
360 开源的,属于 proxy 层方案,以前是有一些公司在用的,但是确实有一个很大的问题就是社区最新的维护都在 5 年前了。所以,现在用的公司基本也很少了。
mycat
基于 cobar 改造的,属于 proxy 层方案,支持的功能非常完善,而且目前应该是非常火的而且不断流行的数据库中间件,社区很活跃,也有一些公司开始在用了。但是确实相比于 sharding jdbc 来说,年轻一些,经历的锤炼少一些。
优点
对于各个项目透明,无耦合
缺点
需要独立部署,保证高可用
proxy层
sharding-jdbc
当当开源的,属于 client 层方案。确实之前用的还比较多一些,因为 SQL 语法支持也比较多,没有太多限制,而且目前推出到了 2.0 版本,支持分库分表、读写分离、分布式 id 生成、柔性事务(最大努力送达型事务、TCC 事务)。而且确实之前使用的公司会比较多一些(这个在官网有登记使用的公司,可以看到从 2017 年一直到现在,是有不少公司在用的),目前社区也还一直在开发和维护,还算是比较活跃,个人认为算是一个现在也可以选择的方案。
优点
不用部署,运维成本低,不需要 代理层的二次转发请求,性能较高
缺点
遇到升级需要各个系统都重新升级版本再发布, 各个系统都需要耦合 sharding-jdbc 的依赖
client层
分库分表面临的问题
垮库join
事务
跨节点分组、排序及聚合
数据迁移及扩容
分页查询
如果是在前台应用提供分页,则限定用户只能看前面n页,这个限制在业务上也是合理的,一般看后面的分页意义不大(如果一定要看,可以要求用户缩小范围重新查询)
如果是后台批处理任务要求分批获取数据,则可以加大page size,比如每次 获取5000条记录,有效减少分页数(当然离线访问一般走备库,避免冲击主库)。
使用nosql的原因
子主题 1
在超大规模和高并发的SNS(社交网络) 类型的web2.0纯动态网站面临的问题
1. High performance - 对数据库高并发读写的需求
web2.0网站要根据用户个性化信息来实时生成动态页面和提供动态信息,所以基本上无法使用动态页面静态化技术,因此数据库并发负载非常高,往往要达到每秒上万次读写请求。关系数据库应付上万次SQL查询还勉强顶得住,但是应付上万次SQL写数据请求,硬盘IO就已经无法承受了。其实对于普通的BBS网站,往往也存在对高并发写请求的需求,例如像JavaEye网站的实时统计在线用户状态,记录热门帖子的点击次数,投票计数等,因此这是一个相当普遍的需求。
2. Huge Storage - 对海量数据的高效率存储和访问的需求
类似Facebook,twitter,Friendfeed这样的SNS网站,每天用户产生海量的用户动态,以Friendfeed为例,一个月就达到了2.5亿条用户动态,对于关系数据库来说,在一张2.5亿条记录的表里面进行SQL查询,效率是极其低下乃至不可忍受的。再例如大型web网站的用户登录系统,例如腾讯,盛大,动辄数以亿计的帐号,关系数据库也很难应付。
3. High Scalability && High Availability- 对数据库的高可扩展性和高可用性的需求
在基于web的架构当中,数据库是最难进行横向扩展的,当一个应用系统的用户量和访问量与日俱增的时候,你的数据库却没有办法像web server和app server那样简单的通过添加更多的硬件和服务节点来扩展性能和负载能力。对于很多需要提供24小时不间断服务的网站来说,对数据库系统进行升级和扩展是非常痛苦的事情,往往需要停机维护和数据迁移,为什么数据库不能通过不断的添加服务器节点来实现扩展呢?