Sharding-JDBC:單庫分表的實現


劇情回顧

前面,我們一共學習了讀寫分離,垂直拆分,垂直拆分+讀寫分離。對應的文章分別如下:

Sharding-JDBC:查詢量大如何優化?

Sharding-JDBC:垂直拆分怎么做?

通過上面的優化,已經能滿足大部分的需求了。只有一種情況需要我們再次進行優化,那就是單表的數量急劇上升,超過了1千萬以上,這個時候就要對表進行水平拆分了。

表的水平拆分是什么?

就是將一個表拆分成N個表,就像一塊大石頭,搬不動,然后切割成10塊,這樣就能搬的動了。原理是一樣的。

除了能夠分擔數量的壓力,同時也能分散讀寫請求的壓力,當然這個得看你的分片算法了,合理的算法才能夠讓數據分配均勻並提升性能。

今天我們主要講單庫中進行表的拆分,也就是不分庫,只分表。

既分庫也分表的操作后面再講,先來一幅圖感受下未分表:

未分表

然后再來一張圖感受下已分表:

已分表

從上圖我們可以看出,user表由原來的一個被拆分成了4個,數據會均勻的分布在這3個表中,也就是原來的user=user0+user1+user2+user3。

分表配置

首先我們需要創建4個用戶表,如下:

CREATE TABLE `user_0`(
	id bigint(64) not null,
	city varchar(20) not null,
	name varchar(20) not null,
	PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `user_1`(
	id bigint(64) not null,
	city varchar(20) not null,
	name varchar(20) not null,
	PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `user_2`(
	id bigint(64) not null,
	city varchar(20) not null,
	name varchar(20) not null,
	PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `user_3`(
	id bigint(64) not null,
	city varchar(20) not null,
	name varchar(20) not null,
	PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

分表的數量你需要根據你的數據量也未來幾年的增長來評估。

分表的規則配置:

spring.shardingsphere.datasource.names=master

# 數據源
spring.shardingsphere.datasource.master.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.master.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.master.url=jdbc:mysql://localhost:3306/ds_0?characterEncoding=utf-8
spring.shardingsphere.datasource.master.username=root
spring.shardingsphere.datasource.master.password=123456

# 分表配置
spring.shardingsphere.sharding.tables.user.actual-data-nodes=master.user_${0..3}

# inline 表達式
spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user_${id.longValue() % 4}

  • actual-data-nodes
    配置分表信息,這邊用的inline表達式,翻譯過來就是master.user_0,master.user_1,master.user_2,master.user_3
  • inline.sharding-column
    分表的字段,這邊用id分表
  • inline.algorithm-expression
    分表算法行表達式,需符合groovy語法,上面的配置就是用id進行取模分片

如果我們有更復雜的分片需求,可以自定義分片算法來實現:

# 自定義分表算法
spring.shardingsphere.sharding.tables.user.table-strategy.standard.sharding-column=id
spring.shardingsphere.sharding.tables.user.table-strategy.standard.precise-algorithm-class-name=com.cxytiandi.sharding.algorithm.MyPreciseShardingAlgorithm

算法類:

public class MyPreciseShardingAlgorithm implements PreciseShardingAlgorithm<Long> {

	@Override
	public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
		for (String tableName : availableTargetNames) {
			if (tableName.endsWith(shardingValue.getValue() % 4 + "")) {
				return tableName;
			}
		}
		throw new IllegalArgumentException();
	}

}

在doSharding方法中你可以根據參數shardingValue做一些處理,最終返回這條數據需要分片的表名稱即可。

除了單列字段分片,還支持多字段分片,大家可以自己去看文檔操作一下。

需要分表的進行配置,不需要分表的無需配置,數據庫操作代碼一行都不用改變。

如果我們要在單庫分表的基礎上,再做讀寫分離,同樣很簡單,只要多配置一個從數據源就可以了,配置如下:

spring.shardingsphere.datasource.names=master,slave

# 主數據源
spring.shardingsphere.datasource.master.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.master.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.master.url=jdbc:mysql://localhost:3306/ds_0?characterEncoding=utf-8
spring.shardingsphere.datasource.master.username=root
spring.shardingsphere.datasource.master.password=123456

# 從數據源
spring.shardingsphere.datasource.slave.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.slave.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.slave.url=jdbc:mysql://localhost:3306/ds_1?characterEncoding=utf-8
spring.shardingsphere.datasource.slave.username=root
spring.shardingsphere.datasource.slave.password=123456

# 分表配置
spring.shardingsphere.sharding.tables.user.actual-data-nodes=ds0.user_${0..3}
spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user_${id.longValue() % 4}

# 讀寫分離配置
spring.shardingsphere.sharding.master-slave-rules.ds0.master-data-source-name=master
spring.shardingsphere.sharding.master-slave-rules.ds0.slave-data-source-names=slave

單庫分表讀寫分離

最后

你會發現,到最后這種復雜的分表場景,用框架來解決會非常簡單。至少比你自己通過字段去計算路由的表,去匯總查詢這種形式要好的多。

源碼參考:https://github.com/yinjihuan/sharding-jdbc

覺得不錯的記得關注下哦,給個Star吧!

歡迎加入我的知識星球,一起交流技術,免費學習猿天地的課程(http://cxytiandi.com/course)

PS:目前星球中正在星主的帶領下組隊學習Spring Cloud,等你哦!

微信掃碼加入猿天地知識星球

猿天地


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM