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

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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容