之前调研形成一篇文章《MySQL 分表方案及中间件介绍》,主要说明了分库分表的技术及主流的中间件,本文主要讨论下分库分表的技术选型及在项目中的具体应用。
随着业务的发展,数据库成为瓶颈,这时候我们需要将每个服务相关的表拆出来单独建立一个数据库,这其实就是“分库”。目前流行的微服务架构也是分库概念在数据库方面的一种实现,比如用户应用对应用户表,订单应用对应订单表。
分表分为水平切分和垂直切分,垂直切分主要是对表进行切分,把常用的和不常用字段的分开,比如用户表中的姓名、工号、年龄放在基本表,学历、工作经历放在另一张表。水平切分是指对表的数据量进行切分,比如按时间,hash等进行区分。
总结如下:
垂直切分:基于表或字段划分,表结构不同。
水平切分:基于数据划分,表结构相同,数据不同。
由于分库分表技术的实施,原来的单库单表操作的纯粹性就不存在了,需要考虑这种技术带来的技术复杂性。所以在应用分库分表时,不可盲目使用,需充分考虑到系统的瓶颈。那技术复杂度有哪些呢?
多个数据库中数据操作,比如分库后,多个数据库关联查询、汇总等;多个数据库的管理问题等。
同一库也要考虑分表查询join。
单表的id 自增主键不能用了,会出现id 重复。
单表事务不可用了,需考虑分布式事务进行处理了。
即然增加了分库分表,变复杂了,有什么中间件可以使用吗?各大厂商都存在着相应的解决方案,我们从项目应用的角度去选择。
Client模式:在连接池上增加一层封装。和系统的紧密性较高。
Proxy模式:独立成服务,接收Sql作处理。
两种模式的代表产品及优缺点如下所示:
这里我们只考虑用户量高的产品并作对比。
作为Apache的顶级项目,其官网定义为:将任何数据库转换为分布式数据库系统的生态系统,并通过分片、弹性伸缩、加密等功能对其进行增强。
其官网讲的很详细,了解使用、原理等可参考官网。官网是学习的最佳方式。
其发展历程为:
其关键特性为:
它包含两大产品:
ShardingSphere-Proxy:被定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。
ShardingSphere Proxy提供了一个封装数据库二进制协议以支持异构语言的数据库服务器。目前提供MySQL和PostgreSQL协议。它可以使用任何一种与MySQL或PostgreSQL协议兼容的终端来操作数据,这对DBA更友好。其特性为:
ShardingSphere-JDBC:一个轻量级Java框架,在Java的JDBC层提供额外的服务。
ShardingSphereJDBC通过客户端直接连接到数据库,它以jar的形式提供服务,不需要额外的部署和依赖。它可以被认为是JDBC驱动程序的增强版,与JDBC和各种ORM框架完全兼容。其特性为:
sharding-jdbc本质上实现 JDBC 的核心接口。
两者对比为:
mycat是Java语言开发的目前比较主流的数据库中间件之一,是mycat团队在阿里开源的 Cobar 产品基础上而研发的,也一直在维护。mycat实现了 MySQL 协议的服务器,前端用户可以把它看作是一个数据库代理,用 MySQL 客户端工具和命令行访问,而其后端可以用 MySQL 原生协议与多个 MySQL 服务器通信,也可以用 JDBC 协议与大多数主流数据库服务器通信。
两者对比如下:
其中Sharding-jdbc的分布式事务已经有一定粒度的实现。
由于我们技术平台中数据量大主要集中在物联网数据这块,所以我们只需考虑物联网的实时数据和历史数据,以及分库分表所带来的技术问题,中间件是否能够解决。
因为实现简单及考虑到我们团队的结构,我们考虑的是ShardingSphere-JDBC。分库分表带来技术问题sharding-jdbc基本都能够解决。
数据库表我们按日期进行划分,例如:
一般分库分表原则:
根据容量(当前容量和增长量)评估分库或分表个数 -> 选key(均匀)-> 分表规则(hash或range等)-> 执行(一般双写)-> 扩容问题(尽量减少数据的移动)。
sharding-jdbc 的原理:
org.apache.shardingsphere
sharding-jdbc-core
4.1.1
目前最新版本的5.3.2。
在application-druid.yml添加分库分表数据源,位置和主数据源同级位置。
# 数据源配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
# 主库数据源
master:
url: jdbc:mysql://localhost:3306/ry473?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: password
# 订单库1
shardsource:
enabled: true
url: jdbc:mysql://localhost:3306/ry473?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: password
@Bean(name = "dynamicDataSource")
@Primary
public DynamicDataSource dataSource(DataSource masterDataSource)
{
Map
设置分库、分表配置,主键规则,指定需使用的策略等。
通过注解@DataSource(DataSourceType.SHARDING),框架判断对应的操作需要使用分表的数据库连接。
类似 TiDB、OceanBase 这样纯粹的分布式数据库完全可以兼容分库分表,也就是说,原来分库分表相关的技术,你现在换个兼容的存储就行了。
但是用分布式数据库也许会更复杂,对于目前我们业务来说的话,分库分表还是适用的,也许未来的天下都是分布式数据库天下,但至少此刻,分库分表能解决我的问题。
页面更新:2024-05-07
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号