大话业界常见数据库分库分表中间件介绍 博客主页:作者主页
觉得文章不错的朋友可以点点赞和关注
粉丝福利:学习资料、简历模板统统都有点击领取
Cobar(已经被淘汰)
TDDL: 淘宝根据自己的业务特点开发了TDDL(Taobao Distributed Data Layer),它是基于JDBC规范,没有Server,以client-jar的形式存储,引入项目即可使用。开源的功能比较少,阿里内部使用为主。
MyCat: Java语言编写的Mysql数据网络协议开源的中间件,它的前身是Cobar,遵守Mysql原生的协议,跨语言,跨平台,跨数据库的通用中间件代理。Mycat是基于Proxy,它腹泻了MySQL协议,将Mycat Server伪装成一个MySQL数据库,它和ShardingShere下的Sharding-proxy作用类似,需要单独的部署。
官网地址:http://www.mycat.org.cn/
Sharding-JDBC: 基于jdbc驱动,不用额外的proxy,支持任意实现JDBC规范的数据库,它使用客户端直连数据库,以jar包形式提供服务,无需额外的部署和依赖。可以理解为加强版的JDBC驱动,兼容JDBC和各类ORM框架
面试官最爱问的Mycat与ShardingJdbc区别1、两者的设计理念是相同的,主流程都是SQL解析->SQL路由->SQL改写->结果并归
2、sharding-jdbc是基于jdbc驱动,不用额外的proxy,在本地应用层重写Jdbc原生的方法,实现数据库分片形式。sharding-jdbc是基于JDBC接口的扩展,是以jar包的形式提供轻量级服务的,性能高,代码有入侵性。
3、Mycat是基于Proxy,它复写了MySQL协议,将Mycat Server伪装成一个MySQL数据库,客户端所有的jdbc请求都必须要先交给MyCat,再有MyCat转发到具体的真实服务器,缺点效率偏低,中间包装类一层,代码无侵入性。
ShardingSphere的三大构成ShardingSphere-Sidecar(规划中): 定位为Kubernetes的云原生数据库代理,以Sidecar的形式代理所有对数据库的访问,通过无中心、零侵入的方案提供与数据库交互的啮合层,就是Database Mesh,又被称为数据库网格。
ShardingSphere-JDBC: 它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可以理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。适用于任何基础JDBC的ORM框架,比如JPA,Hibernate,Mybatis或者直接使用JDBC。支持任何第三方的数据库俩啮齿,比如DBCP,C3P0,BoneCP,HikariCP等等。还支持任意实现JDBC规范的数据库,目前支持MySQL、PostgreSQL、Oracle、SQLServer以及任何可使用 JDBC访问的数据库。采用无中心化架构,与应用程序共享资源,适用于Java开发的高性能轻量级OLTP应用。
ShardingSphere-Proxy: 数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持,向应用程序完全透明,可以直接当做MySQL/PostgreSQL。它可以使用任何兼容MySQL/PostgreSQL协议的访问客户端(比如像:MySQL Command Client,MySQL Workbench,Navicat等)操作数据。
三个组件的对比数据节点Node:数据分片的最小单元,由数据源名称和数据表组成,如:ds_0.product_order_0
真实表:在分片的数据库中真实存在的物理表,比如订单表:product_order_0、product_order_1、product_order_2。
逻辑表:水平拆分的数据库(表)的相同逻辑和数据结构表的总称,如:订单表 product_order_0、product_order_1、product_order_2,逻辑表就是product_order
绑定表:指的是分片规则一直的主表和子表,如:product_order表和product_order_item表,均按照order_id分片,则此两张表互为绑定表关系。绑定表之间的多表关联查询不会出现笛卡尔积关联,关联查询效率将大大提升
广播表:指所有的分片数据源中都存在的表,表结构和表中的数据在每个数据库中均完全一致,适用于数据量不大且需要与海量数据的表进行关联查询的场景。例如:字典表、配置表
分库分表和Sharding-jdbc常见分片算法数据库表分片(水平库、表): 包含了分片键与分片策略
分片键: 用于分片的数据库字段,是把数据库(表)水平拆分除了对单分片字段的支持,ShardingSphere也支持根据多个字段进行分片的关键字段,如prouduct_order订单表,根据订单号 out_trade_no做哈希取模,则out_trade_no是分片键.。
分片策略行表达式分片策略InlineShardingStrategy(必备): 只支持【单片分键】使用的Groovy的表达式,提供SQL语句中的=和IN的分片操作支持,可以通过简单的配置使用,无需自定义分片算法,从而避免繁琐的Java代码开发。
prouduct_order_$->{user_id % 8}` 表示订单表根据user_id模8,而分成8张表,表名称为`prouduct_order_0`到`prouduct_order_7
标准分片策略StandardShardingStrategy: 只支持【单分片键】,提供PreciseShardingAlgorithm和RangeShardingAlgorithm两个分片算法,PreciseShardingAlgorithm 精准分片 是必选的,用于处理=和IN的分片而RangeShardingAlgorithm 范围分配 是可选的,用于处理BETWEEN AND分片,如果不配置RangeShardingAlgorithm,如果SQL中用了BETWEEN AND语法,则将按照全库路由处理,性能下降。
复合分片策略ComplexShardingStrategy: 支持【多分片键】,多分片键之间的关系复杂,由开发者自己实现,提供最大的灵活度,提供对SQL语句中的=, IN和BETWEEN AND的分片操作支持。
Hint分片策略HintShardingStrategy: 这种分片策略无需配置分片健,分片健值也不再从 SQL中解析,外部手动指定分片健或分片库,让 SQL在指定的分库、分表中执行,用于处理使用Hint行分片的场景,通过Hint而非SQL解析的方式分片的策略,Hint策略会绕过SQL解析的,对于这些比较复杂的需要分片的查询,Hint分片策略性能可能会更好。
ShardingSphere实战SQL脚本
CREATE TABLE `product_order_0` ( `id` bigint NOT NULL AUTO_INCREMENT, `out_trade_no` varchar(64) DEFAULT NULL COMMENT '订单唯一标识', `state` varchar(11) DEFAULT NULL COMMENT 'NEW 未支付订单,PAY已经支付订单,CANCEL超时取消订单', `create_time` datetime DEFAULT NULL COMMENT '订单生成时间', `pay_amount` decimal(16,2) DEFAULT NULL COMMENT '订单实际支付价格', `nickname` varchar(64) DEFAULT NULL COMMENT '昵称', `user_id` bigint DEFAULT NULL COMMENT '用户id', PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
实体类(用的mybatiplus)
@Data@EqualsAndHashCode(callSuper = false)@TableName("product_order")public class ProductOrderDO { @TableId(value = "id", type = IdType.AUTO) private Long id; private String outTradeNo; private String state; private Date createTime; private Double payAmount; private String nickname; private Long userId;}//数据库实体类public interface ProductOrderMapper extends baseMapper
配置文件
server.port=8080spring.application.name=xdclass-jdbclogging.level.root=INFO# 打印执行的数据库以及语句spring.shardingsphere.props.sql.show=true# 数据源 db0spring.shardingsphere.datasource.names=ds0# 第一个数据库spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSourcespring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.cj.jdbc.Driverspring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://120.25.217.15:3306/shop_order_0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=truespring.shardingsphere.datasource.ds0.username=rootspring.shardingsphere.datasource.ds0.password=xdclass.net168# 指定product_order表的数据分布情况,配置数据节点,行表达式标识符使用 ${...} 或 $->{...},但前者与 Spring 本身的文件占位符冲突,所以在 Spring 环境中建议使用 $->{...}spring.shardingsphere.sharding.tables.product_order.actual-data-nodes=ds0.product_order_$->{0..1}# 指定product_order表的分片策略,分片策略包括【分片键和分片算法】 spring.shardingsphere.sharding.tables.product_order.table-strategy.inline.sharding-column=user_idspring.shardingsphere.sharding.tables.product_order.table-strategy.inline.algorithm-expression=product_order_$->{user_id % 2}
单元测试
@RunWith(SpringRunner.class) //底层用junit SpringJUnit4ClassRunner@SpringBootTest(classes = DemoApplication.class)@Slf4jpublic class DbTest { @Autowired private ProductOrderMapper productOrderMapper; @Test public void testSaveProductOrder(){ for(int i=0;i<10;i++){ ProductOrder productOrder = new ProductOrder(); productOrder.setCreateTime(new Date()); productOrder.setNickname("程序员小三i="+i); productOrder.setOutTradeNo(UUID.randomUUID().toString().substring(0,32)); productOrder.setPayAmount(100.00); productOrder.setState("PAY"); productOrder.setUserId(Long.valueOf(i+"")); productOrderMapper.insert(productOrder); } }}
控制台SQL
Login SQL:逻辑SQL,没具体到哪一个数据节点
Actual SQL:真实SQL,具体到每一个数据节点的SQL
爛作者小三是刚刚毕业不久全栈工程师,写的技术文章基本上是学习过程中笔记整理而来,大家看了之后如果喜欢可以给小弟点点赞哦。
粉丝福利:学习资料、简历模板统统都有点击领取