SpringBoot+MybatisPlus+Mysql+Sharding-JDBC分庫分表
一、序言
在實際業務中,單表數據增長較快,很容易達到數據瓶頸,比如單表百萬級別數據量。當數據量繼續增長時,數據的查詢性能
即使有索引的幫助下也不盡如意,這時可以引入數據分庫分表
技術。
本文將基於SpringBoot
+MybatisPlus
+Sharding-JDBC
+Mysql
實現企業級分庫分表。
1、組件及版本選擇
- SpringBoot 2.6.x
- MybatisPlus 3.5.0
- Sharding-JDBC 4.1.1
- Mysql 5.7.35
2、預期目標
- 使用上述組件實現分庫分表,簡化起見隻討論分表技術
- 完成分表後的邏輯表與物理表間的增刪查改
- 引入邏輯刪除和使用MybatisPlus內置分頁技術
完整項目源碼訪問地址。
二、代碼實現
為瞭簡化分表復雜性,專註於分表整體實現,簡化分表邏輯:按照UserId
的奇偶屬性分別進行分表。以訂單表這一典型場景為例,一般來說有關訂單表,通常具有如下共性行為:
- 創建訂單記錄
- 查詢XX用戶的訂單列表
- 查詢XX用戶的訂單列表(分頁)
- 查詢XX訂單詳情
- 修改訂單狀態
- 刪除訂單(邏輯刪除)
接下來通過代碼實現上述目標。
(一)素材準備
1、實體類
@Data @TableName("bu_order") public class Order { @TableId private Long orderId; private Integer orderType; private Long userId; private Double amount; private Integer orderStatus; @TableLogic @JsonIgnore private Boolean deleted; }
2、Mapper類
@Mapper public interface OrderMapper extends BaseMapper<Order> { }
3、全局配置文件
spring: config: use-legacy-processing: true shardingsphere: datasource: ds1: driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource url: jdbc:mysql://127.0.0.1:3306/sharding-jdbc2?serverTimezone=UTC username: root password: 123456 names: ds1 props: sql: show: true sharding: tables: bu_order: actual-data-nodes: ds1.bu_order_$->{0..1} key-generator: column: order_id type: SNOWFLAKE table-strategy: inline: algorithm-expression: bu_order_${user_id%2} sharding-column: user_id
(二)增刪查改
1、保存數據
由於依據主鍵的奇偶屬性對原表分表,分表後每張表的數據量是分表前的二分之一。根據需要也可以自定義分表數量(比如10張),新分表後的數據量是不分表前的十分之一。
@Test public void addOrders() { for (long i = 1; i <= 10; i++) { Order order = new Order(); order.setOrderId(i); order.setOrderType(RandomUtil.randomEle(Arrays.asList(1, 2))); order.setUserId(RandomUtil.randomEle(Arrays.asList(101L, 102L, 103L))); order.setAmount(1000.0 * i); orderMapper.insert(order); } }
2、查詢列表數據
查詢指定用戶的訂單列表。
@GetMapping("/list") public AjaxResult list(Order order) { LambdaQueryWrapper<Order> wrapper = Wrappers.lambdaQuery(order); return AjaxResult.success(orderMapper.selectList(wrapper)); }
3、分頁查詢數據
分頁查詢指定用戶的訂單列表
@GetMapping("/page") public AjaxResult page(Page<Order> page, Order order) { return AjaxResult.success(orderMapper.selectPage(page, Wrappers.lambdaQuery(order))); }
4、查詢詳情
通過訂單ID查詢訂單詳情。
@GetMapping("/detail/{orderId}") public AjaxResult detail(@PathVariable Long orderId) { return AjaxResult.success(orderMapper.selectById(orderId)); }
5、刪除數據
通過訂單ID刪除訂單(邏輯刪除)
@DeleteMapping("/delete/{orderId}") public AjaxResult delete(@PathVariable Long orderId) { return AjaxResult.success(orderMapper.deleteById(orderId)); }
6、修改數據
修改數據一般涉及部分列,比如修改訂單表的訂單狀態等。
@PutMapping("/edit") public AjaxResult edit(@RequestBody Order order) { return AjaxResult.success(orderMapper.updateById(order)); }
三、理論分析
1、選擇分片列
選擇分片列是經過精心對比後確定的,對於訂單類場景,需要頻繁以用戶ID為查詢條件篩選數據,因此將同一個用戶的訂單數據存放在一起有利於提高查詢效率。
2、擴容
當分表後的表數據快速增長,可以預見即將達到瓶頸時,需要對分表進行擴容,擴容以2倍
的速率進行,擴容期間需要遷移數據,工作量相對可控。
到此這篇關於SpringBoot+MybatisPlus+Mysql+Sharding-JDBC分庫分表 的文章就介紹到這瞭,更多相關SpringBoot分庫分表 內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- ShardingSphere jdbc實現分庫分表核心概念詳解
- SpringBoot整合Sharding-JDBC實現MySQL8讀寫分離
- 一文搞懂Java的SPI機制(推薦)
- Java ShardingJDBC實戰演練
- 基於 SpringBoot 實現 MySQL 讀寫分離的問題