1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        實戰(zhàn):Shardingsphere分庫分表

        共 7172字,需瀏覽 15分鐘

         ·

        2020-07-30 18:23

        前言

        由于關系型數(shù)據(jù)庫大多采用B+樹類型的索引,在數(shù)據(jù)量超過閾值的情況下,索引深度的增加也將使得磁盤訪問的IO次數(shù)增加,進而導致查詢性能的下降;同時,高并發(fā)訪問請求也使得集中式數(shù)據(jù)庫成為系統(tǒng)的最大瓶頸。

        項目介紹

        Apache ShardingSphere 是一套開源的分布式數(shù)據(jù)庫中間件解決方案組成的生態(tài)圈,它由 JDBC、Proxy 和 Sidecar(規(guī)劃中)這 3 款相互獨立,卻又能夠混合部署配合使用的產品組成。它們均提供標準化的數(shù)據(jù)分片、分布式事務和數(shù)據(jù)庫治理功能,可適用于如 Java 同構、異構語言、云原生等各種多樣化的應用場景。

        Apache ShardingSphere 定位為關系型數(shù)據(jù)庫中間件,旨在充分合理地在分布式的場景下利用關系型數(shù)據(jù)庫的計算和存儲能力,而并非實現(xiàn)一個全新的關系型數(shù)據(jù)庫。它通過關注不變,進而抓住事物本質。

        官方地址:http://shardingsphere.apache.org

        本文目標

        本文將以springboot進行集成演示,以訂單表為例,演示shardingsphere分庫分表的基本原理及配置。

        項目產生的demo地址見尾部。

        實戰(zhàn)

        數(shù)據(jù)庫腳本

        id主鍵不設置為自增,分別在db0和db1創(chuàng)建t_order_2019、t_order_2020三個表

         CREATE TABLE `t_order` (
        `id` bigint(20) NOT NULL,
        `order_sn` varchar(255) DEFAULT NULL COMMENT '訂單編號',
        `member_id` varchar(255) DEFAULT NULL COMMENT '用戶id',
        `create_time` datetime DEFAULT NULL COMMENT '創(chuàng)建時間',
        `status` int(11) DEFAULT NULL COMMENT '訂單狀態(tài)',
        PRIMARY KEY (`id`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

        maven依賴

        ????<properties>
        ?????????<sharding-sphere.version>4.0.0-RC2sharding-sphere.version>
        ????properties>
        ?<dependency>
        ?????????<groupId>org.apache.shardingspheregroupId>
        ?????????<artifactId>sharding-jdbc-spring-boot-starterartifactId>
        ?????????<version>${sharding-sphere.version}version>
        ????dependency>

        配置文件

        配置db0和db1兩個數(shù)據(jù)庫,定義數(shù)據(jù)庫路由規(guī)則為member_id除以2取余。

        每個數(shù)據(jù)庫創(chuàng)建t_order_0、t_order_1、t_order_2三張表,定義表的路由規(guī)則為member_id除以3取余。

        mybatis.mapper-locations=classpath:mybatis/*Mapper.xml
        logging.level.com.lzn.shardingsphere.dao=debug

        spring.shardingsphere.datasource.names = db0,db1

        spring.shardingsphere.datasource.db0.type = com.zaxxer.hikari.HikariDataSource
        spring.shardingsphere.datasource.db0.driver-class-name = com.mysql.cj.jdbc.Driver
        spring.shardingsphere.datasource.db0.jdbc-url = jdbc:mysql://192.168.202.128:3306/sharding?characterEncoding=utf8&useSSL=false
        spring.shardingsphere.datasource.db0.username = root
        spring.shardingsphere.datasource.db0.password = 123qwe

        spring.shardingsphere.datasource.db1.type = com.zaxxer.hikari.HikariDataSource
        spring.shardingsphere.datasource.db1.driver-class-name = com.mysql.cj.jdbc.Driver
        spring.shardingsphere.datasource.db1.jdbc-url = jdbc:mysql://192.168.202.128:3307/sharding?characterEncoding=utf8&useSSL=false
        spring.shardingsphere.datasource.db1.username = root
        spring.shardingsphere.datasource.db1.password = 123qwe

        # 分庫策略 根據(jù)id取模確定數(shù)據(jù)進哪個數(shù)據(jù)庫
        spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column = member_id
        spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression = db$->{member_id % 2}

        # 分表策略
        # 節(jié)點 db0.t_order_0,db0.t_order_1,db0.t_order_2,db1.t_order_0,db1.t_order_1,db1.t_order_2
        spring.shardingsphere.sharding.tables.t_order.actual-data-nodes = db$->{0..1}.t_order_$->{0..2}
        # 分表字段member_id
        spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column = member_id
        # 分表策略 根據(jù)member_id取模,確定數(shù)據(jù)最終落在那個表中
        spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression = t_order_$->{member_id % 3}

        # 使用SNOWFLAKE算法生成主鍵
        spring.shardingsphere.sharding.tables.t_order.key-generator.column = id
        spring.shardingsphere.sharding.tables.t_order.key-generator.type = SNOWFLAKE

        數(shù)據(jù)庫持久層

        使用mybatis-generator生成

        實體類

        image-20200615171558278

        Dao接口

        image-20200615171449030

        sql文件

        image-20200615172144593

        啟動項目

        image-20200615152237950

        測試驗證

        插入測試:準備member_id分別為 100,101,102,103的

        預期結果:依次在db0.t_order_1、db1.t_order_2、db0.t_order_0、db1.order_1

        單元測試類

        @Test
        ????void?TestInsertOrder(){
        ????????List?orderList?=?new?ArrayList<>();
        ????????orderList.add(new?Order("111111",100L,new?Date(),1));
        ????????orderList.add(new?Order("222222",101L,new?Date(),1));
        ????????orderList.add(new?Order("333333",102L,new?Date(),1));
        ????????orderList.add(new?Order("444444",103L,new?Date(),1));
        ????????for(Order?order:orderList){
        ????????????orderService.createOrder(order);
        ????????}
        ????}

        ![image-20200615171235787](http://lznqn.cxylt.cn/picGO/image-20200615171235787.png

        image-20200615172440925

        插入驗證

        member_id = 100 路由到db0.t_order_1

        image-20200615173904768
        image-20200615172702673

        member_id = 101 路由到 db1.t_order_2

        image-20200615174037627
        image-20200615172833384

        member_id = 102 路由到 db0.t_order_0

        image-20200615174754591
        image-20200615172639393

        member_id = 103 路由到 db1.t_order_1

        image-20200615175039272
        image-20200615172746566

        查詢驗證

        不帶分片鍵的查詢

        @Test
        ????void?TestListOrder(){
        ????????OrderExample?orderExample?=?new?OrderExample();
        ????????List?orderList=?orderService.listOrder(orderExample);
        ????????for?(Order?o:orderList){
        ????????????System.out.println(o.toString());
        ????????}
        ????}

        此時會全庫全表查詢,并將結果匯總

        2020-06-15 18:00:59.099  INFO 948 --- [           main] ShardingSphere-SQL                       : Actual SQL: db0 ::: select
        id, order_sn, member_id, create_time, status
        from t_order_0
        2020-06-15 18:00:59.099 INFO 948 --- [ main] ShardingSphere-SQL : Actual SQL: db0 ::: select
        id, order_sn, member_id, create_time, status
        from t_order_1
        2020-06-15 18:00:59.099 INFO 948 --- [ main] ShardingSphere-SQL : Actual SQL: db0 ::: select
        id, order_sn, member_id, create_time, status
        from t_order_2
        2020-06-15 18:00:59.099 INFO 948 --- [ main] ShardingSphere-SQL : Actual SQL: db1 ::: select
        id, order_sn, member_id, create_time, status
        from t_order_0
        2020-06-15 18:00:59.099 INFO 948 --- [ main] ShardingSphere-SQL : Actual SQL: db1 ::: select
        id, order_sn, member_id, create_time, status
        from t_order_1
        2020-06-15 18:00:59.100 INFO 948 --- [ main] ShardingSphere-SQL : Actual SQL: db1 ::: select
        id, order_sn, member_id, create_time, status
        from t_order_2
        Order(id=479339444940308481, orderSn=333333, memberId=102, createTime=Mon Jun 15 17:23:47 CST 2020, status=1)
        Order(id=479339438946648065, orderSn=111111, memberId=100, createTime=Mon Jun 15 17:23:45 CST 2020, status=1)
        Order(id=479339445393293312, orderSn=444444, memberId=103, createTime=Mon Jun 15 17:23:47 CST 2020, status=1)
        Order(id=479339444424409088, orderSn=222222, memberId=101, createTime=Mon Jun 15 17:23:47 CST 2020, status=1)

        帶有member_id的分片條件

         @Test
        void TestListOrder2(){
        OrderExample orderExample = new OrderExample();
        OrderExample.Criteria criteria = orderExample.createCriteria();
        criteria.andMemberIdEqualTo(101L);
        List orderList= orderService.listOrder(orderExample);
        for (Order o:orderList){
        System.out.println(o.toString());
        }
        }

        會自動路由到對應表

        2020-06-15 18:06:18.346  INFO 19768 --- [           main] ShardingSphere-SQL                       : Actual SQL: db1 ::: select


        id, order_sn, member_id, create_time, status

        from t_order_2


        WHERE ( member_id = ? ) ::: [101]
        Order(id=479339444424409088, orderSn=222222, memberId=101, createTime=Mon Jun 15 17:23:47 CST 2020, status=1)

        總結

        shardingsphere分庫分表可以解決單庫單表的數(shù)據(jù)庫的性能瓶頸問題,開發(fā)者使用起來也比較簡單,只需定義好分片的規(guī)則和算法,shardingsphere會自動路由、改寫sql、將結果合并返回。但分庫分表也會增加系統(tǒng)的復雜度,例如跨庫的join問題,事務問題,成本問題等,需要綜合考慮是否有分庫分表的必要。

        項目demo地址

        https://github.com/pengziliu/GitHub-code-practice


        END


        有熱門推薦?

        1.?MyBatis動態(tài)SQL(認真看看, 以后寫SQL就爽多了)

        2.?兩難!到底用Apache BeanUtils還是Spring BeanUtils?

        3.?天天在用 Stream,那你知道如此強大的 Stream 的實現(xiàn)原理嗎?

        4.?kill -9 進程殺不掉,怎么辦?

        最近面試BAT,整理一份面試資料Java面試BATJ通關手冊,覆蓋了Java核心技術、JVM、Java并發(fā)、SSM、微服務、數(shù)據(jù)庫、數(shù)據(jù)結構等等。

        獲取方式:點“在看”,關注公眾號并回復?Java?領取,更多內容陸續(xù)奉上。

        文章有幫助的話,在看,轉發(fā)吧。

        謝謝支持喲 (*^__^*)

        瀏覽 70
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            国产日视频 | 好大好粗好爽视频 | 国产美女拍的操逼视频 | 久久久久久秸品 | 伊人青青草视频 | 羞羞视频最新地址发布页 | 我被男人cao了一夜 | 欧美激情婬乱一区二区三区老牛 | 色色热| 男人插女人逼动态图 |