美文网首页already
分库分表常见中间件介绍和ShardingSphere极速认知+实

分库分表常见中间件介绍和ShardingSphere极速认知+实

作者: 谁叫我土豆了 | 来源:发表于2022-02-10 15:55 被阅读0次

    大话业界常见数据库分库分表中间件介绍

    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作用类似,需要单独的部署。

    官网地址: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等)操作数据。

    三个组件的对比

    Sharding-JDBC常见概念术语

    数据节点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

    绑定表:指的是分片规则<typo id="typo-1990" data-origin="一直" ignoretag="true">一致</typo>的主表和子表,如:product_order表和product_order_item表,均按照order_id分片,则此两张表互为绑定表关系。绑定表之间的多表关联查询不会出现笛卡尔<typo id="typo-2082" data-origin="积" ignoretag="true">积</typo><typo id="typo-2083" data-origin="关联" ignoretag="true">关联</typo>,关联查询效率将大大提升

    广播表:指所有的分片数据源中都存在的表,表结构和表中的数据在每个数据库中均完全一致,适用于数据量不大且需要与海量数据的表进行关联查询的场景。例如:字典表、配置表

    分库分表和Sharding-jdbc常见分片算法

    数据库表分片(水平库、表): 包含了分片键与分片策略

    分片键: 用于分片的数据库字段,是把数据库(表)水平拆分<typo id="typo-2264" data-origin="除了" ignoretag="true">除了</typo>对单分片字段的支持,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: 这种分片策略无需配置分片健,分片健值也不再<typo id="typo-3027" data-origin="从" ignoretag="true">从</typo> 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<ProductOrderDO> {
    
    }
    

    配置文件

    server.port=8080
    spring.application.name=xdclass-jdbc
    
    logging.level.root=INFO
    # 打印执行的数据库以及语句
    spring.shardingsphere.props.sql.show=true
    
    # 数据源 db0
    spring.shardingsphere.datasource.names=ds0
    # 第一个数据库
    spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
    spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.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=true
    spring.shardingsphere.datasource.ds0.username=root
    spring.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_id
    spring.shardingsphere.sharding.tables.product_order.table-strategy.inline.algorithm-expression=product_order_$->{user_id % 2}
    

    单元测试

    @RunWith(SpringRunner.class)  //底层用junit  SpringJUnit4ClassRunner
    @SpringBootTest(classes = DemoApplication.class)
    @Slf4j
    public 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

    作者:零零后程序员小三
    链接:https://juejin.cn/post/7061854754644688932

    相关文章

      网友评论

        本文标题:分库分表常见中间件介绍和ShardingSphere极速认知+实

        本文链接:https://www.haomeiwen.com/subject/sugnkrtx.html