輕量級的資料庫中介軟體解決了SpringBoot中分庫分表問題
阿新 • • 發佈:2020-09-22
一、 Sharding-jdbc簡介
Sharding-jdbc是開源的資料庫操作中介軟體;定位為輕量級Java框架,在Java的JDBC層提供的額外服務。它使用客戶端直連資料庫,以jar包形式提供服務,無需額外部署和依賴,可理解為增強版的JDBC驅動,完全相容JDBC和各種ORM框架。
官方文件地址:
https://shardingsphere.apache.org/document/current/cn/overview/
本文demo實現了分庫分表功能。
作者能力有限,如有錯誤,歡迎各位在評論中指出。不勝感激!
二、專案結構
首先建立一個一般的Spring boot專案,專案採用三層架構,結構圖如下:
POM.xml檔案如下:
<?xmlversion="1.0"encoding="UTF-8"?> <projectxmlns="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.0http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/><!--lookupparentfromrepository--> </parent> <groupId>com.macky</groupId> <artifactId>spring-boot-shardingjdbc</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring-boot-shardingjdbc</name> <description>Demoprojectforspring-boot-shardingjdbc</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!--Mybatis-Plus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.1.1</version> </dependency> <!--shardingspherestart--> <!--forspringboot--> <dependency> <groupId>io.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>3.1.0</version> </dependency> <!--forspringnamespace--> <dependency> <groupId>io.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-namespace</artifactId> <version>3.1.0</version> </dependency> <!--shardingsphereend--> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
實體類以書本為例
packagecom.macky.springbootshardingjdbc.entity; importcom.baomidou.mybatisplus.annotation.TableName; importcom.baomidou.mybatisplus.extension.activerecord.Model; importgroovy.transform.EqualsAndHashCode; importlombok.Data; importlombok.experimental.Accessors; /** *@authorMacky *@TitleclassBook *@Description:書籍是實體類 */ @Data @EqualsAndHashCode(callSuper=true) @Accessors(chain=true) @TableName("book") publicclassBookextendsModel<Book>{ privateintid; privateStringname; privateintcount; }
開放儲存和查詢兩個介面,程式碼如下:
packagecom.macky.springbootshardingjdbc.controller; importcom.macky.springbootshardingjdbc.entity.Book; importcom.macky.springbootshardingjdbc.service.BookService; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.web.bind.annotation.*; importjava.util.List; /** *@authorMacky *@TitleclassBookController *@Description:TODO */ @RestController publicclassBookController{ @Autowired BookServicebookService; @RequestMapping(value="/book",method=RequestMethod.GET) publicList<Book>getItems(){ returnbookService.getBookList(); } @RequestMapping(value="/book",method=RequestMethod.POST) publicBooleansaveItem(Bookbook){ returnbookService.save(book); } }
BookServiceImpl.java
packagecom.macky.springbootshardingjdbc.service.impl; importcom.baomidou.mybatisplus.core.toolkit.Wrappers; importcom.baomidou.mybatisplus.extension.service.impl.ServiceImpl; importcom.macky.springbootshardingjdbc.entity.Book; importcom.macky.springbootshardingjdbc.mapper.BookMapper; importcom.macky.springbootshardingjdbc.service.BookService; importorg.springframework.stereotype.Service; importjava.util.List; /** *@authorMacky *@TitleclassBookServiceImpl *@Description:TODO *@date2019/7/1220:47 */ @Service publicclassBookServiceImplextendsServiceImpl<BookMapper,Book>implementsBookService{ @Override publicList<Book>getBookList(){ returnbaseMapper.selectList(Wrappers.<Book>lambdaQuery()); } @Override publicbooleansave(Bookbook){ returnsuper.save(book); } }
BookMapper.java
packagecom.macky.springbootshardingjdbc.mapper; importcom.baomidou.mybatisplus.core.mapper.BaseMapper; importcom.macky.springbootshardingjdbc.entity.Book; /** *@authorMacky *@TitleclassBookMapper *@Description:TODO *@date2019/7/1220:46 */ publicinterfaceBookMapperextendsBaseMapper<Book>{ }
建立資料庫表,DDL語句如下
#建立資料庫表資料 CREATEDATABASEIFNOTEXISTS`db0`; USE`db0`; DROPTABLEIFEXISTS`book_0`; CREATETABLE`book_0`( `id`INT(11)NOTNULL, `name`VARCHAR(255)DEFAULTNULL, `count`INT(11)DEFAULTNULL, PRIMARYKEY(`id`) )ENGINE=INNODBDEFAULTCHARSET=utf8mb4; DROPTABLEIFEXISTS`book_1`; CREATETABLE`book_1`( `id`INT(11)NOTNULL, `name`VARCHAR(255)DEFAULTNULL, `count`INT(11)DEFAULTNULL, PRIMARYKEY(`id`) )ENGINE=INNODBDEFAULTCHARSET=utf8mb4; CREATEDATABASEIFNOTEXISTS`db1`; USE`db1`; DROPTABLEIFEXISTS`book_0`; CREATETABLE`book_0`( `id`INT(11)NOTNULL, `name`VARCHAR(255)DEFAULTNULL, `count`INT(11)DEFAULTNULL, PRIMARYKEY(`id`) )ENGINE=INNODBDEFAULTCHARSET=utf8mb4; DROPTABLEIFEXISTS`book_1`; CREATETABLE`book_1`( `id`INT(11)NOTNULL, `name`VARCHAR(255)DEFAULTNULL, `count`INT(11)DEFAULTNULL, PRIMARYKEY(`id`) )ENGINE=INNODBDEFAULTCHARSET=utf8mb4; CREATEDATABASEIFNOTEXISTS`db2`; USE`db2`; DROPTABLEIFEXISTS`book_0`; CREATETABLE`book_0`( `id`INT(11)NOTNULL, `name`VARCHAR(255)DEFAULTNULL, `count`INT(11)DEFAULTNULL, PRIMARYKEY(`id`) )ENGINE=INNODBDEFAULTCHARSET=utf8mb4; DROPTABLEIFEXISTS`book_1`; CREATETABLE`book_1`( `id`INT(11)NOTNULL, `name`VARCHAR(255)DEFAULTNULL, `count`INT(11)DEFAULTNULL, PRIMARYKEY(`id`) )ENGINE=INNODBDEFAULTCHARSET=utf8mb4;
配置分庫分表策略application.properties:
#資料來源db0,db1,db2 sharding.jdbc.datasource.names=db0,db1,db2 #第一個資料庫 sharding.jdbc.datasource.db0.type=com.zaxxer.hikari.HikariDataSource sharding.jdbc.datasource.db0.driver-class-name=com.mysql.cj.jdbc.Driver sharding.jdbc.datasource.db0.jdbc-url=jdbc:mysql://localhost:3306/db0?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC sharding.jdbc.datasource.db0.username=root sharding.jdbc.datasource.db0.password=Aa123456 #第二個資料庫 sharding.jdbc.datasource.db1.type=com.zaxxer.hikari.HikariDataSource sharding.jdbc.datasource.db1.driver-class-name=com.mysql.cj.jdbc.Driver sharding.jdbc.datasource.db1.jdbc-url=jdbc:mysql://localhost:3306/db1?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC sharding.jdbc.datasource.db1.username=root sharding.jdbc.datasource.db1.password=Aa123456 #第三個資料庫 sharding.jdbc.datasource.db2.type=com.zaxxer.hikari.HikariDataSource sharding.jdbc.datasource.db2.driver-class-name=com.mysql.cj.jdbc.Driver sharding.jdbc.datasource.db2.jdbc-url=jdbc:mysql://localhost:3306/db2?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC sharding.jdbc.datasource.db2.username=root sharding.jdbc.datasource.db2.password=Aa123456 #水平拆分的資料庫(表)配置分庫+分表策略行表示式分片策略 #分庫策略 sharding.jdbc.config.sharding.default-database-strategy.inline.sharding-column=id sharding.jdbc.config.sharding.default-database-strategy.inline.algorithm-expression=db$->{id%3} #分表策略其中book為邏輯表分表主要取決於id行 sharding.jdbc.config.sharding.tables.book.actual-data-nodes=db$->{0..2}.book_$->{0..1} sharding.jdbc.config.sharding.tables.book.table-strategy.inline.sharding-column=count #分片演算法表示式 sharding.jdbc.config.sharding.tables.book.table-strategy.inline.algorithm-expression=book_$->{count%2} #主鍵UUID18位數如果是分散式還要進行一個設定防止主鍵重複 #sharding.jdbc.config.sharding.tables.user.key-generator-column-name=id #列印執行的資料庫以及語句 sharding.jdbc.config.props..sql.show=true spring.main.allow-bean-definition-overriding=true #讀寫分離 sharding.jdbc.datasource.dsmaster=
介面測試使用postman
示例:
GET請求------>http://localhost:8080/book
POST請求:------->http://localhost:8080/book?id=1&name=java程式設計思想&count=8
demo的github地址:
https://github.com/Macky-He/spring-boot–shardingsphere-examples
如各位覺得有幫助的話,還請給個star鼓勵鼓勵博主,謝謝!
三、總結
分庫分表實現按照官方文件做一個demo是第一步,如需深入還需要研究原始碼,研究架構,研究思想;此文僅作為入門demo搭建指南,如需深入理解,還請移步至官方文件。