本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
什么是分库分表
把原来存储在一个库表中的数据拆分到不同的库/表中。
为什么分库分表
业务的不断发展和数据的不断递增,未来场景下可能出现瓶颈。
分布式部署、单机服务性能瓶颈、数据处理能力瓶颈、数据存储瓶颈等
众所周知,数据库往往最容易成为应用系统的瓶颈,而数据库本身属于“有状态”的,相对于Web和应用服务器来讲,是比较难实现“横向扩展”的。数据库的连接资源比较宝贵且单机处理能力也有限,在高并发场景下,分库一定程度上能够突破IO、连接数及单机硬件资源的瓶颈,是大型分布式系统中优化数据库架构的重要手段。
分库分表的实施策略
分库分表有垂直切分和水平切分两种。
垂直拆分——主要是字段的拆分;
水平拆分——表结构不变,数据分表;
垂直切分
按照功能模块、关系密切程度将不同的业务表划分出来,部署到不同的库上。例如,我们的采购工作台,不同的业务表存储在不同的数据库中。系统层面的“服务化”拆分操作,能够解决业务系统层面的耦合和性能瓶颈,有利于系统的扩展维护。而数据库层面的拆分,道理也是相通的。与服务的“治理”和“降级”机制类似,我们也能对不同业务类型的数据进行“分级”管理、维护、监控、扩展等。
水平切分
按照某种规则把一张表的数据拆分成多个结构相同的表。
常用拆分规则:
-
范围法:以用户的uid主键为范围规则划分
•user-db0:存储0到1千万的uid数据
•user-db1:存储1到2千万的uid数据 -
范围法的优点
•切分简单,根据uid,按照范围,很快能够定位到数据在哪个库上
•扩容简单,如果容量不够,只要增加user-db2即可 -
范围法的不足
•uid必须要满足递增的特性
•数据量不均,新增的user-db2,在初期的数据会比较少
•请求量不均,一般来说,新注册的用户活跃度会比较高,故user-db1往往会比user-db0负载要高,导致服务器利用率不平衡 -
哈希法:以用户的uid进行划分
•user-db0:uid %2=0 的数据保存在db0库上
•user-db1:uid %2=1 的数据保存在db1库上 -
哈希法的优点:
•切分策略简单,根据uid取模,根据取模结果很快能够定位到数据在哪个库上
•数据量均衡,只要uid是均匀的,数据在各个库上的分布一定是均衡的
•请求量均衡,只要uid是均匀的,负载在各个库上的分布一定是均衡的 -
哈希法的不足:
•扩容麻烦,如果容量不够,要增加一个库,重新hash可能会导致数据迁移,如何平滑的进行数据迁移,是一个需要解决的问题 -
城市/租户-有明显业务特征的分表
-
根据不同的城市、租户、供应商进行分库
-
user-db3201:3201南京的数据保存在db0库上
-
user-db3202:3202无锡的数据保存在db1库上
-
优点:根据不同的业务特征进行拆分,按照不同的租户直接分离数据,数据独立
-
缺点:单个租户数据量快速增大后依旧是瓶颈
拆分带来的问题
应该使用哪一种方式来实施数据库分库分表,这要看数据库中数据量的瓶颈所在,并综合项目的业务类型进行考虑。
拆分带来的问题?www.cnblogs.com/wade-luffy/…
-
垂直分库带来的问题和解决思路
跨库join的问题:全局表、字段冗余、数据同步、系统层组装
跨库事务(分布式事务)的问题:分布式事务 -
水平分库带来的问题和解决思路
分布式全局唯一ID:id生成规则不再依赖于数据库
分片字段该如何选择:片键 ,表中最频繁被使用,或者最重要的字段来作为分片字段
数据迁移,容量规划,扩容等问题:历史数据、扩容
跨分片的排序分页 :业务处理
跨分片的函数处理 :业务处理
跨分片join : 全局表、ER分片、内存计算
我们的系统真的需要分库分表吗?
Sharding-sphere
Sharding-Sphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar这3款相互独立的产品组成。他们均提供标准化的数据分片、读写分离、柔性事务和数据治理功能,可适用于如Java同构、异构语言、容器、云原生等各种多样化的应用场景。
Sharding-JDBC
定位为轻量级Java框架,在Java的JDBC层提供的额外服务。 它使用客户端直连数据库,以jar包形式提供服务
,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。
1、适用于任何基于JDBC的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
2、支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。
3、支持任意实现JDBC规范的数据库。目前支持MySQL,Oracle,SQLServer,PostgreSQL以及任何遵循SQL92标准的数据库。
优点:
1、性能很好的
2、支持跨数据库jdbc
缺点:
1、增加了开发难度
2、不支持跨语言(java)
Sharding-Proxy
定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。 目前
先提供MySQL版本,它可以使用任何兼容MySQL协议的访问客户端(如:MySQL Command Client, MySQL
Workbench等)操作数据,对DBA更加友好。
sharding-proxy是一种数据库中间件,从数据库层面解决分库分表问题,应用与sharding-proxy交互,sharding-proxy与实际分库分表数据库交互,sharding-proxy需要配置分库分表策略
优点:
- 向应用程序完全透明,可直接当做MySQL使用。
- 适用于任何兼容MySQL协议的的客户端。
- sharding-ui,直接的管理sharding-proxy,在上面动态修改配置等信息。
缺点:
性能,作为数据库的代理层,使用java与阻塞式的驱动,这样,在高并发的场景下,sharding-proxy自身的性能就会变的很低了。因为会有大量内核态线程阻塞。做为代理层,我的理解,他应该是不阻塞线程的模型,来让代理层可以做更多的事情。比如,我以前需要5台集群代理支持的并发,现在可能通过1台能做当时5台所做的事情。
拆分带来的问题?www.cnblogs.com/wade-luffy/…
Sharding-Sidecar
定位为Kubernetes或Mesos的云原生数据库代理,以DaemonSet的形式代理所有对数据库的访问。 通过无中心、
零侵入的方案提供与数据库交互的的啮合层,即Database Mesh,又可称数据网格。
MyCat和Sharding-jdbc的区别
Mycat(proxy中间件层):
Sharding-jdbc(TDDL为代表的应用层):
sharding-jdbc和mycat使用不同的理念,sharding-jdbc目前是基于jdbc驱动,无需额外的proxy,因此也无需关注proxy本身的高可用。Mycat 是基于 Proxy,它复写了 MySQL 协议,将 Mycat Server 伪装成一个 MySQL 数据库,而 Sharding-JDBC 是基于 JDBC 接口的扩展,是以 jar 包的形式提供轻量级服务的