<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Sharding-JDBC基本使用,整合Springboot實現(xiàn)分庫分表,讀寫分離

          共 9585字,需瀏覽 20分鐘

           ·

          2021-11-11 21:42

          點擊上方藍色字體,選擇“標(biāo)星公眾號”

          優(yōu)質(zhì)文章,第一時間送達

          一、Sharding-JDBC介紹

          1、這里引用官網(wǎng)上的介紹:

          ??定位為輕量級Java框架,在Java的JDBC層提供的額外服務(wù)。它使用客戶端直連數(shù)據(jù)庫,以jar包形式提供服務(wù),無需額外部署和依賴,可理解為增強版的JDBC驅(qū)動,完全兼容JDBC和各種ORM框架。

          ??適用于任何基于JDBC的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
          ??支持任何第三方的數(shù)據(jù)庫連接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。
          ??支持任意實現(xiàn)JDBC規(guī)范的數(shù)據(jù)庫。目前支持MySQL,Oracle,SQLServer,PostgreSQL以及任何遵循SQL92標(biāo)準(zhǔn)的數(shù)據(jù)庫。

          2、自己的理解:
          ??增強版的JDBC驅(qū)動,客戶端使用的時候,就像正常使用JDBC驅(qū)動一樣, 引入Sharding-JDBC依賴包,連接好數(shù)據(jù)庫,配置好分庫分表規(guī)則,讀寫分離配置,然后客戶端的sql 操作 Sharding-JDBC會自動根據(jù)配置完成 分庫分表和讀寫分離操作。


          二、實現(xiàn)效果

          1、下圖展示了我們通過Sharding-JDBC實現(xiàn)的分庫分表及讀寫分離效果圖

          ??分庫分表:結(jié)合上一篇的主從,這里我們使用上次搭建的主從數(shù)據(jù)庫,3307的app1是主數(shù)據(jù)庫,3308的app1是對應(yīng)的從數(shù)據(jù)庫。同時,我們在3307新建app2庫和user2表,這里的app2庫需要和app1庫一樣,user2表和user1表結(jié)構(gòu)一樣,主從會自動幫我們建表同步到3308,然后我們在項目中使用Sharding-JDBC 配置響應(yīng)的分庫分表策略,使得插入數(shù)據(jù)的時候 根據(jù)配置字段的分片規(guī)則將數(shù)據(jù)打入對應(yīng)的庫和表。在我們這里主要是 根據(jù)分庫的分片規(guī)則決定數(shù)據(jù)進入3307的app1庫還是app2庫,然后再根據(jù)分表的分片規(guī)則決定進入user1表還是user2表。
          ??讀寫分離:讀寫分離 在我們這里主要指的是 我們項目DQL會根據(jù)Sharding-JDBC配置的master-slave-rule走的3308的數(shù)據(jù)源,而項目的DML會根據(jù)master-slave-rule走3307的數(shù)據(jù)源

          三、Spring-Boot項目整合Sharding-JDBC實現(xiàn)分庫分表、讀寫分離

          1、這里創(chuàng)建一個maven項目,首先引入依賴,pom.xml文件如下。

          "1.0"?encoding="UTF-8"?>
          "http://maven.apache.org/POM/4.0.0"
          ?????????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          ?????????xsi:schemaLocation="http://maven.apache.org/POM/4.0.0?http://maven.apache.org/xsd/maven-4.0.0.xsd">
          ????4.0.0
          ????
          ????????org.springframework.boot
          ????????spring-boot-starter-parent
          ????????2.3.3.RELEASE
          ????


          ????com.cgg
          ????sharding-jdbc-test
          ????1.0-SNAPSHOT

          ????
          ????????1.8
          ????


          ????
          ????????
          ????????????org.springframework.boot
          ????????????spring-boot-starter-web
          ????????


          ????????
          ????????????org.springframework.boot
          ????????????spring-boot-starter-test
          ????????


          ????????
          ????????????mysql
          ????????????mysql-connector-java
          ????????????8.0.15
          ????????


          ????????
          ????????????com.alibaba
          ????????????druid
          ????????????1.1.21
          ????????


          ????????
          ????????????com.baomidou
          ????????????mybatis-plus-boot-starter
          ????????????3.1.1
          ????????


          ????????
          ????????????com.baomidou
          ????????????mybatis-plus-extension
          ????????????3.1.1
          ????????


          ????????
          ????????????org.apache.shardingsphere
          ????????????sharding-jdbc-spring-boot-starter
          ????????????4.0.0-RC1
          ????????


          ????????
          ????????????org.projectlombok
          ????????????lombok
          ????????


          ????


          ????
          ????????
          ????????????
          ????????????????org.springframework.boot
          ????????????????spring-boot-maven-plugin
          ????????????

          ????????

          ????



          注意:這里使用的是4.0的sharding-jdbc,spring-boot的版本是2.x的,在整合過程中遇見了許多問題,后面會有錯誤的解決步驟。
          2、application.yml文件如下

          spring:
          ??jpa:
          ????properties:
          ??????hibernate:
          ????????hbm2ddl:
          ??????????auto:?create
          ????????dialect:?org.hibernate.dialect.MySQL5Dialect
          ????????show_sql:?true
          ??shardingsphere:
          ????props:
          ??????sql:
          ????????show:?true
          ????datasource:
          ??????names:?master0,master0slave0,master1,master1slave0
          ??????master0:
          ????????type:?com.alibaba.druid.pool.DruidDataSource
          ????????driver-class-name:?com.mysql.cj.jdbc.Driver
          ????????url:?jdbc:mysql://127.0.0.1:3307/app1?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMT
          ????????username:?root
          ????????password:?654321
          ??????master1:
          ????????type:?com.alibaba.druid.pool.DruidDataSource
          ????????driver-class-name:?com.mysql.cj.jdbc.Driver
          ????????url:?jdbc:mysql://127.0.0.1:3307/app2?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMT
          ????????username:?root
          ????????password:?654321
          ??????master0slave0:
          ????????type:?com.alibaba.druid.pool.DruidDataSource
          ????????driver-class-name:?com.mysql.cj.jdbc.Driver
          ????????url:?jdbc:mysql://127.0.0.1:3308/app1?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT
          ????????username:?root
          ????????password:?654321
          ??????master1slave0:
          ????????type:?com.alibaba.druid.pool.DruidDataSource
          ????????driver-class-name:?com.mysql.cj.jdbc.Driver
          ????????url:?jdbc:mysql://127.0.0.1:3308/app2?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT
          ????????username:?root
          ????????password:?654321
          ????sharding:
          ??????default-database-strategy:
          ????????inline:
          ??????????sharding-column:?id
          ??????????algorithm-expression:?app$->{(id?%?2)+1}
          ??????tables:
          ????????user:
          ??????????actual-data-nodes:?app$->{1..2}.user$->{1..2}
          ??????????table-strategy:
          ????????????inline:
          ??????????????sharding-column:?id
          ??????????????algorithm-expression:?user$->{((""+id)[2..10].toInteger()?%?2)+1}
          ??????????key-generator:
          ????????????column:?id
          ????????????type:?SNOWFLAKE
          ??????master-slave-rules:
          ????????app1:
          ??????????master-data-source-name:?master0
          ??????????slave-data-source-names:?master0slave0
          ????????app2:
          ??????????master-data-source-name:?master1
          ??????????slave-data-source-names:?master1slave0
          sharding:
          ??jdbc:
          ????config:
          ??????masterslave:
          ????????load-balance-algorithm-type:?random

          3、application.properties文件

          spring.main.allow-bean-definition-overriding=true

          mybatis-plus.mapper-locations=?classpath:/mapper/*.xml

          mybatis-plus.configuration.log-impl=?org.apache.ibatis.logging.stdout.StdOutImpl

          4、分庫分表實現(xiàn)

          ?4.1、先說下數(shù)據(jù)源,結(jié)合之前mysql主從的文章,我本地127.0.0.1:3307端口是主,127.0.0.1:3308端口是從。

          ???在3307下建立兩個庫app1和app2,同時每個庫里面建立兩張表user1和user2表,用來完成分庫分表。

          ???下面是app1庫SQL語句:

          SET?NAMES?utf8mb4;
          SET?FOREIGN_KEY_CHECKS?=?0;

          --?----------------------------
          --?Table?structure?for?user1
          --?----------------------------
          DROP?TABLE?IF?EXISTS?`user1`;
          CREATE?TABLE?`user1`??(
          ??`id`?bigint(11)?NOT?NULL?COMMENT?'主鍵id',
          ??`name`?varchar(255)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL,
          ??PRIMARY?KEY?(`id`)?USING?BTREE
          )?ENGINE?=?InnoDB?CHARACTER?SET?=?utf8mb4?COLLATE?=?utf8mb4_general_ci?ROW_FORMAT?=?Dynamic;

          --?----------------------------
          --?Table?structure?for?user2
          --?----------------------------
          DROP?TABLE?IF?EXISTS?`user2`;
          CREATE?TABLE?`user2`??(
          ??`id`?bigint(11)?NOT?NULL?COMMENT?'主鍵id',
          ??`name`?varchar(255)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL,
          ??PRIMARY?KEY?(`id`)?USING?BTREE
          )?ENGINE?=?InnoDB?CHARACTER?SET?=?utf8mb4?COLLATE?=?utf8mb4_general_ci?ROW_FORMAT?=?DYNAMIC;

          SET?FOREIGN_KEY_CHECKS?=?1;

          ???下面是app2庫SQL語句:

          SET?NAMES?utf8mb4;
          SET?FOREIGN_KEY_CHECKS?=?0;

          --?----------------------------
          --?Table?structure?for?user1
          --?----------------------------
          DROP?TABLE?IF?EXISTS?`user1`;
          CREATE?TABLE?`user1`??(
          ??`id`?bigint(11)?NOT?NULL?COMMENT?'主鍵id',
          ??`name`?varchar(255)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL,
          ??PRIMARY?KEY?(`id`)?USING?BTREE
          )?ENGINE?=?InnoDB?CHARACTER?SET?=?utf8mb4?COLLATE?=?utf8mb4_general_ci?ROW_FORMAT?=?DYNAMIC;

          --?----------------------------
          --?Table?structure?for?user2
          --?----------------------------
          DROP?TABLE?IF?EXISTS?`user2`;
          CREATE?TABLE?`user2`??(
          ??`id`?bigint(11)?NOT?NULL?COMMENT?'主鍵id',
          ??`name`?varchar(255)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL,
          ??PRIMARY?KEY?(`id`)?USING?BTREE
          )?ENGINE?=?InnoDB?CHARACTER?SET?=?utf8mb4?COLLATE?=?utf8mb4_general_ci?ROW_FORMAT?=?Dynamic;

          SET?FOREIGN_KEY_CHECKS?=?1;

          ?4.2、這里我們解釋一下配置的分庫分表規(guī)則實現(xiàn)將數(shù)據(jù)插入到app1和app2庫,user1和user2表

          ????sharding:
          ??????default-database-strategy:
          ????????inline:
          ??????????sharding-column:?id?#分片的字段是id主鍵
          ??????????algorithm-expression:?app$->{(id?%?2)+1}?#分片的算法是?id對2求余然后加1
          ??????tables:
          ????????user:
          ??????????actual-data-nodes:?app$->{1..2}.user$->{1..2}??#實際的數(shù)據(jù)節(jié)點是(app1/app2).(user1/user2)
          ??????????table-strategy:
          ????????????inline:
          ??????????????sharding-column:?id?#分表的分片字段是主鍵id
          ??????????????algorithm-expression:?user$->{((""+id)[2..10].toInteger()?%?2)+1}?#分表的算法是取id的2-10位對2求余然后加1
          ??????????key-generator:
          ????????????column:?id?#?自動生成主鍵
          ????????????type:?SNOWFLAKE?#?生成主鍵的規(guī)則是雪花算法

          ???上面配置的規(guī)則指的是,當(dāng)有數(shù)據(jù)要插入數(shù)據(jù)庫,或者進行查詢時,sharding-jdbc通過分片配置的字段id的值,去根據(jù)配置的算法 進行運算,得到結(jié)果,例如上述分庫規(guī)則,拿到id值 對2求余加1,那么不管id怎么變化算法返回的值永遠是1和2,即app$->{(id % 2)+1} 對應(yīng)的就是app1和app2庫,分表的規(guī)則是同樣道理。
          ???說明:這里只是配置了簡單的分片規(guī)則來演示sharding-jdbc如何完成分庫分表,我們也可以使用代碼重寫
          方法來實現(xiàn)更復(fù)雜的分片策略。最后,這里的$->{(id % 2)+1} 的{}中實際上是一個Groovy語法的表達式,sharding-jdbc是通過Groovy語法糖來解析分片策略的。所以想要配置更為復(fù)雜的策略,建議學(xué)一下Groovy語法。

          ?4.3、接下來我們介紹配置的讀寫分離規(guī)則,如何實現(xiàn)讀寫分離

          ??????master-slave-rules:
          ????????app1:?#分區(qū)?app1
          ??????????master-data-source-name:?master0?#分區(qū)?app1的主數(shù)據(jù)源
          ??????????slave-data-source-names:?master0slave0?#分區(qū)?app1的從數(shù)據(jù)源
          ????????app2:?#分區(qū)?app2
          ??????????master-data-source-name:?master1?#分區(qū)?app2的主數(shù)據(jù)源
          ??????????slave-data-source-names:?master1slave0?#分區(qū)?app2的從數(shù)據(jù)源

          ???上面讀寫分離的規(guī)則指的是,分區(qū)app1的主從數(shù)據(jù)源,分區(qū)app2的主從數(shù)據(jù)源。至于這里的分區(qū)為什么是app1和app2?這里說明一下,我自己配置的時候,配置了幾次都沒有成功,一開始參照官網(wǎng)手冊配置,以為分區(qū)名稱可以自定義,于是配置的是ds0和ds1,但是項目啟動報錯了。報錯信息是:
          Cannot find data source in sharding rule, invalid actual data node is: 'app1.user1'

          開始以為是使用的sharding-jdbc版本問題,但是換了版本還是有問題,于是開始調(diào)試了一下源碼:

          ???

          ??? 從上面的截圖中很明顯就能發(fā)現(xiàn),這里是要判斷我們配置的分區(qū)集合也就是ds0和ds1是否包含 實際節(jié)點的數(shù)據(jù)源名稱,也就是數(shù)據(jù)庫名稱。所以這里的分區(qū)名稱是和我們上面配置的分片策略的數(shù)據(jù)庫名稱有關(guān)系的。

          ?4.4、驗證
          ??? 接下來我們驗證實際的效果。這里貼一下單元測試的代碼。

          /**
          ?*?@author?cgg
          ?*?@version?1.0.0
          ?*?@date?2021/10/25
          ?*/
          @SpringBootTest(classes?=?ShardingJdbcApp.class)
          @RunWith(SpringRunner.class)
          public?class?AppTest?{

          ????@Resource
          ????private?IUserService?userService;


          ????/**
          ?????*?測試sharding-jdbc添加數(shù)據(jù)
          ?????*/
          ????@Test
          ????public?void?testShardingJdbcInsert()?{

          ????????userService.InsertUser();
          ????}

          ????/**
          ?????*?測試sharding-jdbc查詢數(shù)據(jù)
          ?????*/
          ????@Test
          ????public?void?testShardingJdbcQuery()?{

          ????????//全部查詢
          ????????userService.queryUserList();

          ????????//根據(jù)指定條件查詢
          ????????userService.queryUserById(1452619866473324545L);

          ????}

          }

          /**
          ?*?@author?cgg
          ?*?@version?1.0.0
          ?*?@date?2021/10/25
          ?*/
          @Service
          @Slf4j
          public?class?UserServiceImpl?implements?IUserService?{

          ????@Resource
          ????private?UserMapper?userMapper;

          ????@Resource
          ????private?DataSource?dataSource;

          ????@Override
          ????public?List?queryUserList()?{
          ????????List?userList?=?userMapper.queryUserList();
          ????????userList.forEach(user?->?System.out.println(user.toString()));
          ????????return?userList;
          ????}

          ????@Override
          ????public?User?queryUserById(Long?id)?{
          ????????User?user?=?userMapper.selectOne(Wrappers.lambdaQuery().eq(User::getId,?id));
          ????????System.out.println(user.toString());
          ????????return?user;
          ????}

          ????@Override
          ????public?void?InsertUser()?{
          ????????for?(int?i?=?20;?i?????????????User?user?=?new?User();
          ????????????user.setName("XX-"?+?i);
          ????????????int?count?=?userMapper.insert(user);
          ????????????System.out.println(count);
          ????????}
          ????}


          }

          ????4.4.1、首先看全部查詢的結(jié)果

          ????4.4.2、再看下單條查詢的結(jié)果

          ????4.4.3、再看下新增結(jié)果(實際插入到了主數(shù)據(jù)源的app1庫user1表,并且后續(xù)每條插入都是走的主數(shù)據(jù)源,沒有slave的操作)




          ??作者?|??coffeebabe

          來源 |??cnblogs.com/wa1l-E/p/15465884.html


          加鋒哥微信:?java1239??
          圍觀鋒哥朋友圈,每天推送Java干貨!

          瀏覽 92
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  全国色综合 | 日韩毛片儿| 青青草香蕉网 | 免费观看黄色一级视频 | 久久成人音影 |