虛擬電商-數據庫分庫分表(二)

本文章介紹:使用Sharding-JDBC實現數據庫分庫分表,數據庫分片策略,實現數據庫按月分表

一、Sharding-JDBC使用

1.1.準備環境

步驟一:分庫分表sql腳本導入

創建了兩個數據庫:chongba_schedule0 和chongba_schedule1

每個數據庫中任務表和任務日志表各自兩張:taskinfo_0,taskinfo_1,taskinfo_logs_0,taskinfo_logs_1

DROP database if exists `chongba_schedule0`;
CREATE DATABASE `chongba_schedule0` DEFAULT CHARACTER SET utf8;
USE `chongba_schedule0`;
CREATE TABLE `taskinfo_0` (`task_id` bigint(20) NOT NULL    comment '任務id',`execute_time` datetime(3) NOT NULL comment '執行時間',`parameters` longblob  comment '參數',`priority` int(11) NOT NULL      comment '優先級',`task_type` int(11) NOT NULL     comment '任務類型',PRIMARY KEY (`task_id`),KEY `index_taskinfo_time` (`task_type`,`priority`,`execute_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
?
CREATE TABLE `taskinfo_1` (`task_id` bigint(20) NOT NULL    comment '任務id',`execute_time` datetime(3) NOT NULL comment '執行時間',`parameters` longblob  comment '參數',`priority` int(11) NOT NULL      comment '優先級',`task_type` int(11) NOT NULL     comment '任務類型',PRIMARY KEY (`task_id`),KEY `index_taskinfo_time` (`task_type`,`priority`,`execute_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
?
CREATE TABLE `taskinfo_logs_0` (`task_id` bigint(20) NOT NULL     comment '任務id',`execute_time` datetime(3) NOT NULL  comment '執行時間',`parameters` longblob   comment '參數',`priority` int(11) NOT NULL       comment '優先級',`task_type` int(11) NOT NULL      comment '任務類型',`version` int(11) NOT NULL        comment '版本號,用樂觀鎖',`status` int(11) DEFAULT '0' COMMENT '狀態 0=初始化狀態 1=EXECUTED 2=CANCELLED',PRIMARY KEY (`task_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
?
CREATE TABLE `taskinfo_logs_1` (`task_id` bigint(20) NOT NULL     comment '任務id',`execute_time` datetime(3) NOT NULL  comment '執行時間',`parameters` longblob   comment '參數',`priority` int(11) NOT NULL       comment '優先級',`task_type` int(11) NOT NULL      comment '任務類型',`version` int(11) NOT NULL        comment '版本號,用樂觀鎖',`status` int(11) DEFAULT '0'      comment '狀態 0=初始化狀態 1=EXECUTED 2=CANCELLED',PRIMARY KEY (`task_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
?
drop database if exists `chongba_schedule1`;
CREATE DATABASE `chongba_schedule1` DEFAULT CHARACTER SET utf8;
USE `chongba_schedule1`;
CREATE TABLE `taskinfo_0` (`task_id` bigint(20) NOT NULL    comment '任務id',`execute_time` datetime(3) NOT NULL comment '執行時間',`parameters` longblob  comment '參數',`priority` int(11) NOT NULL      comment '優先級',`task_type` int(11) NOT NULL     comment '任務類型',PRIMARY KEY (`task_id`),KEY `index_taskinfo_time` (`task_type`,`priority`,`execute_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
?
CREATE TABLE `taskinfo_1` (`task_id` bigint(20) NOT NULL    comment '任務id',`execute_time` datetime(3) NOT NULL comment '執行時間',`parameters` longblob  comment '參數',`priority` int(11) NOT NULL      comment '優先級',`task_type` int(11) NOT NULL     comment '任務類型',PRIMARY KEY (`task_id`),KEY `index_taskinfo_time` (`task_type`,`priority`,`execute_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
?
CREATE TABLE `taskinfo_logs_0` (`task_id` bigint(20) NOT NULL     comment '任務id',`execute_time` datetime(3) NOT NULL  comment '執行時間',`parameters` longblob   comment '參數',`priority` int(11) NOT NULL       comment '優先級',`task_type` int(11) NOT NULL      comment '任務類型',`version` int(11) NOT NULL        comment '版本號,用樂觀鎖',`status` int(11) DEFAULT '0'      comment '狀態 0=初始化狀態 1=EXECUTED 2=CANCELLED',PRIMARY KEY (`task_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
?
CREATE TABLE `taskinfo_logs_1` (`task_id` bigint(20) NOT NULL     comment '任務id',`execute_time` datetime(3) NOT NULL  comment '執行時間',`parameters` longblob   comment '參數',`priority` int(11) NOT NULL       comment '優先級',`task_type` int(11) NOT NULL      comment '任務類型',`version` int(11) NOT NULL        comment '版本號,用樂觀鎖',`status` int(11) DEFAULT '0'      comment '狀態 0=初始化狀態 1=EXECUTED 2=CANCELLED',PRIMARY KEY (`task_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

步驟二:在chongba_schedule_service 模塊的pom文件中引入依賴:

<dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>4.0.0-RC1</version>
</dependency>
<dependency><!-- druid數據源--><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.19</version>
</dependency>

1.2.基本概念

邏輯表

是對于水平拆分的數據庫(表)的同一類表的總稱。例如:訂單數據根據主鍵尾數拆分為10張表,分別是t_order_0到t_order_9,他們的邏輯表可以表示為t_order,在應用程序中操作的是邏輯表。

@TableName("taskinfo")
public class TaskInfoEntity implements Serializable {.........
}

真實表

在分片的數據庫中真實存在的物理表。即上個示例中的t_order_0到t_order_9。

數據節點

數據分片的最小單元, 由數據源名稱和數據表組成

例如:db_0.t_order_0。 表示 數據庫db_0下名稱為t_order_0的表

1.3.數據源整合

下面我們進行數據源整合

分庫分表之后,就不用之前的數據源了,改用新的數據源,因為有多個數據庫,所以需要配置多數據源。

對于程序中的代碼我們無需修改,只需要通過配置支持多數據源即可,官方文檔中有提供好的配置參考。

為了讓配置更加的清晰和有條理,我們使用新的配置,操作步驟如下:

步驟一:在chongba_schedule_service模塊中的bootstrap.yml配置文件中修改加載的配置:schedule-sharding

spring:application:  name: schedule-serviceprofiles:active: devcloud:consul:host: 127.0.0.1port: 8500discovery:serviceName: ${spring.application.name}config:enabled: trueformat: yaml         prefix: configdefaultContext: schedule-sharding   # 只修改此處,其他和之前一樣data-key: data

步驟二:在Consul中建立新的key/value配置,Consul中的key為:config/schedule-sharding,dev/data,注意在Consul中新建key/value時要在最外層

然后在該key下配置對應的value如下:(可以先在applicatoin-dev.yml文件中配置好再配置到Consul)

chongba: preLoad: 1 #自定義預加載時間selectMasterZookeeper: 192.168.200.129:2181  
spring:redis:host: 192.168.200.129password: chongbaport: 6379sleuth:sampler:probability: 1     #這是收集比例,1表示100% ,全部收集zipkin:#base-url: http://localhost:9411sender:type: rabbitrabbitmq:host: 192.168.200.129port: 5672username: guestpassword: guest    shardingsphere:datasource:ds0:driver-class-name: com.mysql.cj.jdbc.Driverpassword: 123456type: com.alibaba.druid.pool.DruidDataSourceurl: jdbc:mysql://192.168.200.129:3306/chongba_schedule0?serverTimezone=Asia/Shanghaiusername: rootds1:driver-class-name: com.mysql.cj.jdbc.Driverpassword: 123456type: com.alibaba.druid.pool.DruidDataSourceurl: jdbc:mysql://192.168.200.129:3306/chongba_schedule1?serverTimezone=Asia/Shanghaiusername: rootnames: ds0,ds1

步驟三:在chongba_schedule_service模塊中啟動:ScheduleApplication,查看控制臺輸出

3.1)項目基于SpringBoot,啟動時會自動配置,其中有一個關于數據源的自動配置類如下:

org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

@Configuration
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})
@EnableConfigurationProperties({DataSourceProperties.class})
@Import({DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class})
public class DataSourceAutoConfiguration {......
}@ConfigurationProperties(prefix = "spring.datasource"
)
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {private Class<? extends DataSource> type;private String driverClassName;private String url;private String username;private String password;
}

默認去加載spring的數據源,而我們使用sharding-jdbc后用的不再是spring默認提供的數據源,通過配置可以發現我們使用的是:spring.shardingsphere.datasource

解決方案:

在啟動類:ScheduleApplication 上將系統默認spring的數據源自動配置類排除

//@SpringBootApplication
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@MapperScan("com.chongba.schedule.mapper")
@ComponentScan({"com.chongba.cache","com.chongba.schedule"})
@EnableScheduling
@EnableAsync
public class ScheduleApplication {..........
}

3.2)sqlSessionFactory屬于mybatis的工廠類,該工廠類沒有創建好

原因:默認情況下spring整合mybtis會自動創建sqlSessionFactory,而創建sqlSessionFactory需要用到數據源dataSource,采用的也是spring默認提供的數據源,通過我們上面的分析,此時的數據源是由shardingsphere來提供的,因此創建sqlSessionFactory不成功!

解決方案:

在chongba_schedule_service模塊中的com.chongba.schedule.conf包下創建

MybatisPlusShardingConfiguration 配置類,將shardingDataSource數據源集成到mybatis-plus中去

/***mybatis-plus 使用sharding-jdbc數據源問題*/
@Configuration
@AutoConfigureAfter(DataSource.class)
public class MybatisPlusShardingConfiguration {//獲取sharding 數據源@Autowiredprivate DataSource dataSource;@Beanpublic MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean(){MybatisSqlSessionFactoryBean mysqlplus = new MybatisSqlSessionFactoryBean();mysqlplus.setDataSource(dataSource);return mysqlplus;}
}

3.3)現在雖然數據源的問題解決了,但是數據庫表的問題還沒解決,因為報錯信息是數據庫chongba_schedule1中的taskinfo表不存在,我們現在的表是taskinfo_0,taskinfo_1,如何解決?

二、分片路由配置

2.1.taskinfo表分片路由配置

配置好了數據源,對于數據庫表并沒有做任何處理,我們要對數據庫表進行分片路由配置,當向數據庫表中寫入數據的時候通過特定的路由規則來判定數據寫入到哪個庫及哪個表中

例如對taskinfo 表根據用戶task_type字段分庫,priority字段分表,修改Consul中config/schedule-sharding,dev/data下的value如下

chongba: preLoad: 1 #自定義預加載時間selectMasterZookeeper: 192.168.200.129:2181  
spring:redis:host: 192.168.200.129password: chongbaport: 6379zipkin:#base-url: http://localhost:9411sender:type: rabbitrabbitmq:host: 192.168.200.129port: 5672username: guestpassword: guest      shardingsphere:datasource:ds0:driver-class-name: com.mysql.cj.jdbc.Driverpassword: 123456type: com.alibaba.druid.pool.DruidDataSourceurl: jdbc:mysql://192.168.200.129:3306/chongba_schedule0?serverTimezone=Asia/Shanghaiusername: rootds1:driver-class-name: com.mysql.cj.jdbc.Driverpassword: 123456type: com.alibaba.druid.pool.DruidDataSourceurl: jdbc:mysql://192.168.200.129:3306/chongba_schedule1?serverTimezone=Asia/Shanghaiusername: rootnames: ds0,ds1sharding:tables:taskinfo:actual-data-nodes: ds$->{0..1}.taskinfo_$->{0..1}key-generator: #主鍵生成策略column: task_idtype: SNOWFLAKEdatabase-strategy:  #分庫策略inline:sharding-column: task_typealgorithm-expression: ds$->{task_type % 2}table-strategy: #分表策略inline:sharding-column: priority algorithm-expression: taskinfo_$->{priority % 2}

注意:
數據節點含義 采用 e x p r e s s i o n 或 {expression}或 expression->{expression}
也是 s p r i n g b o o t 讀取變量的規則,為了防止沖突,建議 {}也是springboot 讀取變量的規則,為了防止沖突,建議 也是springboot讀取變量的規則,為了防止沖突,建議->
?
db0
├── taskinfo_0
└── taskinfo_1
?
db1
├── taskinfo_1
└── taskinfo_1
?
以上對于數據源和數據表的配置都是連續,下面看不連續的配置,比如要配置成:
db0
├── t_order0
└── t_order1
db1
├── t_order2
├── t_order3
└── t_order4
這種情況對于actual-data-nodes的配置:
actual-data-nodes: db0.t_order ? > 0..1 , d b 1. t o r d e r ->{0..1},db1.t_order ?>0..1,db1.to?rder->{2…4}

2.2.taskinfo表分片測試

測試:

在chongba_schedule_service工程中找到測試類:TaskInfoMapperTest,運行測試方法:test1(),

TaskInfoEntity taskInfoEntity = new TaskInfoEntity();
taskInfoEntity.setExecuteTime(new Date());
taskInfoEntity.setPriority(1);
taskInfoEntity.setTaskType(1001);
taskInfoEntity.setParameters("test".getBytes());
taskInfoMapper.insert(taskInfoEntity);

測試案例1:按照分片路由規則:task_type % 2 == 1該數據將被分配到ds1數據源上,priority % 2 ==1,該數據將被分配到taskinfo_1表中存儲。

**測試案例2:**可以更改TaskType =1000 priority =10,繼續測試

2.3.taskinfo_logs表分片路由配置

taskinfo_logs分片策略跟taskinfo表一致,所以直接修改Consul中config/schedule-sharding,dev/data下的value如下:chongba: preLoad: 1 #自定義預加載時間selectMasterZookeeper: 192.168.200.129:2181  
spring:redis:host: 192.168.200.129password: chongbaport: 6379zipkin:#base-url: http://localhost:9411sender:type: rabbitrabbitmq:host: 192.168.200.129port: 5672username: guestpassword: guest      shardingsphere:datasource:ds0:driver-class-name: com.mysql.cj.jdbc.Driverpassword: 123456type: com.alibaba.druid.pool.DruidDataSourceurl: jdbc:mysql://192.168.200.129:3306/chongba_schedule0?serverTimezone=Asia/Shanghaiusername: rootds1:driver-class-name: com.mysql.cj.jdbc.Driverpassword: 123456type: com.alibaba.druid.pool.DruidDataSourceurl: jdbc:mysql://192.168.200.129:3306/chongba_schedule1?serverTimezone=Asia/Shanghaiusername: rootnames: ds0,ds1sharding:tables:taskinfo:actual-data-nodes: ds$->{0..1}.taskinfo_$->{0..1}key-generator: #主鍵生成策略column: task_idtype: SNOWFLAKEdatabase-strategy:  #分庫策略inline:sharding-column: task_typealgorithm-expression: ds$->{task_type % 2}table-strategy: #分表策略inline:sharding-column: priority algorithm-expression: taskinfo_$->{priority % 2}taskinfo_logs:actual-data-nodes: ds$->{0..1}.taskinfo_logs_$->{0..1}database-strategy: #分庫策略inline:sharding-column: task_typealgorithm-expression: ds$->{task_type % 2}key-generator:column: task_idtype: SNOWFLAKEtable-strategy: #分表策略inline:sharding-column: priorityalgorithm-expression: taskinfo_logs_$->{priority % 2}

2.4.taskinfo_logs表分片測試:

在chongba_schedule_service工程中,找到測試類:TaskInfoLogsMapperTest,運行測試方法:test()

測試案例1:task_type=1003,priority=3,數據會被路由到:ds1.taskinfo_logs_1中

結果:

1:數據能夠正常入庫

2:樂觀鎖出現問題

對應樂觀鎖我們希望:

但是實際情況:

樂觀鎖出現問題的原因:

1:關于樂觀鎖我們之前是在啟動類ScheduleApplication中進行了如下配置,將樂觀鎖插件放入IOC容器中然后自動的注冊到SqlSessionFactory

@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){return new OptimisticLockerInterceptor();
}

但是現在我們使用的是mybatis-plus集成了sharding-jdbc數據源后的MybatisSqlSessionFactoryBean,我們的樂觀鎖插件并沒有自動的注冊進去。

在chongba_schedule_service模塊中的com.chongba.schedule.conf包下找到配置類:

MybatisPlusShardingConfiguration并做出修改

 @Beanpublic MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean(){MybatisSqlSessionFactoryBean mysqlplus = new MybatisSqlSessionFactoryBean();mysqlplus.setDataSource(dataSource);mysqlplus.setPlugins(new Interceptor[]{new OptimisticLockerInterceptor()}); //注冊插件return mysqlplus;}

注意:注釋掉啟動類中關于樂觀鎖插件的配置!
最后再次進行測試!

三、Sharding-JDBC分片策略

3.1.分片策略介紹
Sharding分片策略繼承自ShardingStrategy,提供了5種分片策略:

在這里插入圖片描述

1.StandardShardingStrategy
標準分片策略。提供對SQL語句中的=, IN和BETWEEN AND的分片操作支持。

StandardShardingStrategy只支持單分片鍵,提供PreciseShardingAlgorithm和RangeShardingAlgorithm兩個分片算法。

1:PreciseShardingAlgorithm是必選的,用于處理=和IN的分片。

2:RangeShardingAlgorithm是可選的,用于處理BETWEEN AND分片,如果不配置RangeShardingAlgorithm,SQL中的BETWEEN AND將按照全庫路由處理。

1566457504884
2.ComplexShardingStrategy

復合分片策略。提供對SQL語句中的=, IN和BETWEEN AND的分片操作支持。

ComplexShardingStrategy支持多分片鍵,由于多分片鍵之間的關系復雜,因此Sharding-JDBC并未做過多的封裝,而是直接將分片鍵值組合以及分片操作符交于算法接口,完全由應用開發者實現,提供最大的靈活度。

3.InlineShardingStrategy
Inline表達式分片策略。使用Groovy的Inline表達式,提供對SQL語句中的=和IN的分片操作支持。

InlineShardingStrategy只支持單分片鍵,對于簡單的分片算法,可以通過簡單的配置使用,從而避免繁瑣的Java代碼開發,如: t_user_${user_id % 8} 表示t_user表按照user_id按8取模分成8個表,表名稱為t_user_0到t_user_7。

1566457463389

4.HintShardingStrategy
通過Hint而非SQL解析的方式分片的策略。

對于分片字段非SQL決定,而由其他外置條件決定的場景,可使用SQL Hint靈活的注入分片字段。例:內部系統,按照員工登錄主鍵分庫,而數據庫中并無此字段。SQL Hint支持通過Java API和SQL注釋(待實現)兩種方式使用。

5.NoneShardingStrategy

不分片的策略。

6.自定義分片策略介紹

由于分片算法和業務實現緊密相關,因此Sharding-JDBC是通過分片策略將各種場景提煉出來,提供更高層級的抽象,并提供接口讓應用開發者自行實現分片算法。

為了方便獲取定義的參數及集成,自定義的算法要實現Sharding-jdbc 提供的接口,

Sharding提供了以下4種算法接口:

1):精確分片算法–PreciseShardingAlgorithm

用于處理使用單一鍵作為分片鍵的=與IN進行分片的場景。需要配合StandardShardingStrategy使用。

2):范圍分片算法–RangeShardingAlgorithm

用于處理使用單一鍵作為分片鍵的BETWEEN AND進行分片的場景。需要配合StandardShardingStrategy使用。

3):復合分片算法–ComplexKeysShardingAlgorithm

用于處理使用多鍵作為分片鍵進行分片的場景,包含多個分片鍵的邏輯較復雜,需要應用開發者自行處理其中的復雜度。需要配合ComplexShardingStrategy使用。

注 : 我們在業務開發中,經常有根據用戶id 查詢某用戶的記錄列表,又有根據某個業務主鍵查詢該用戶的某記錄的需求,這就需要用到復合分片算法。比如,訂單表中,我們既需要查詢某個userId的某時間段內的訂單列表數據,又需要根據orderId查詢某條訂單數據。這里,orderId與userId就屬于復合分片鍵。

4):Hint分片算法–HintShardingAlgorithm

Hint分片指的是對于分片字段非SQL決定,而由其他外置條件決定的場景,可以通過使用SQL Hint靈活注入分片字段。

Hint分片策略是繞過SQL解析的,因此能夠通過實現該算法來實現Sharding-JDBC不支持的語法限制。

用于處理使用Hint行分片的場景。需要配合HintShardingStrategy使用。

四、任務日志表按月分表

需求:

對于數據庫表taskinfo,我們消費完任務或者取消完任務后數據都會從該表中去刪除,而對于taskinfo_logs日志表數據是一直累加的,對于數據量大的情況下只分兩張表仍然會存在性能瓶頸,我們現在要對taskinfo_logs根據任務的執行時間execute_time進行按月分表

實現:

步驟1:導入數據表

步驟2:在Consul中創建新的配置并使用

2.1:在chonba_sechedule_service的bootstrap.yml配置文件中修改加載的配置:schedule-sharding-month

2.2:在Consul中添加新的key:config/schedule-sharding-month,dev/data ,并配置如下值:

chongba: preLoad: 1 #自定義預加載時間selectMasterZookeeper: 192.168.200.129:2181  
spring:redis:host: 192.168.200.129password: chongbaport: 6379zipkin:#base-url: http://localhost:9411sender:type: rabbitrabbitmq:host: 192.168.200.129port: 5672username: guestpassword: guest      shardingsphere:datasource:ds0:driver-class-name: com.mysql.cj.jdbc.Driverpassword: 123456type: com.alibaba.druid.pool.DruidDataSourceurl: jdbc:mysql://192.168.200.129:3306/chongba_schedule0?serverTimezone=Asia/Shanghaiusername: rootds1:driver-class-name: com.mysql.cj.jdbc.Driverpassword: 123456type: com.alibaba.druid.pool.DruidDataSourceurl: jdbc:mysql://192.168.200.129:3306/chongba_schedule1?serverTimezone=Asia/Shanghaiusername: rootnames: ds0,ds1sharding:tables:taskinfo:actual-data-nodes: ds$->{0..1}.taskinfo_$->{0..1}key-generator: #主鍵生成策略column: task_idtype: SNOWFLAKEdatabase-strategy:  #分庫策略inline:sharding-column: task_typealgorithm-expression: ds$->{task_type % 2}table-strategy: #分表策略inline:sharding-column: priority algorithm-expression: taskinfo_$->{priority % 2}taskinfo_logs: #邏輯表actual-data-nodes: ds$->{0..1}.taskinfo_logs_20$->{19..22}_$->{1..12}key-generator: #主鍵生成策略column: task_idtype: SNOWFLAKEdatabase-strategy:  #分庫策略inline:sharding-column: task_typealgorithm-expression: ds$->{task_type % 2}table-strategy: #分表策略 按月分庫standard:precise-algorithm-class-name: com.chongba.schedule.conf.ShardingAlgorithmMonthsharding-column: execute_time

步驟3:自定義分片算法實現

在chongba_schedule_service工程中的包com.chongba.schedule.conf下創建分片算法類:

ShardingAlgorithmMonth,實現PreciseShardingAlgorithm接口,實現根據任務的執行時間進行按月分片。

@Slf4j
public class ShardingAlgorithmMonth implements PreciseShardingAlgorithm<Date> {
?/*** 執行分片策略   * @param collection                    候選表集合 * @param preciseShardingValue          精確分片值:任務的執行時間* @return                              數據路由到的表名稱*/@Overridepublic String doSharding(Collection<String> collection, PreciseShardingValue<Date> preciseShardingValue) {String node = null;try {DateFormat dateFormat = new SimpleDateFormat("yyyy_M");String dateStr = dateFormat.format(preciseShardingValue.getValue());for (String nodeCandidate : collection) {if(nodeCandidate.endsWith(dateStr)){node  = nodeCandidate;break;}}} catch (Exception e) {log.error("sharding-sphere doSharding exception {}",e.getMessage());}return node;}   
}

步驟4:找到測試類:TaskInfoLogsMapperTest,運行測試方法:test(),查看控制臺輸出

報錯信息:無法將數據路由到表

解決方案:debug運行測試方法,查看問題,發現是由于時間格式的問題,修改分片算法實現,然后再次測試!

五、分庫分表優化介紹

5.1.優化1

優化1:任務表和任務日志表我們做了分庫分表,對于有一些表,數據量很小,我們無需進行分庫分表,有哪些解決方案?

廣播表:指所有的分片數據源中都存在的表,表結構和表中的數據在每個數據庫中均完全一致。適用于數據量不大且需要與海量數據的表進行關聯查詢的場景,例如:字典表。

不指定分庫分表策略:如果某張表不需要分庫分表,那我們可以不指定分庫分表策略,讓這張表的數據直接落到指定的數據源中即可

spring:shardingsphere:datasource:df:driver-class-name: com.mysql.cj.jdbc.Driverpassword: 123456type: com.alibaba.druid.pool.DruidDataSourceurl: jdbc:mysql://192.168.200.129:3306/chongba_schedule?serverTimezone=Asia/Shanghaiusername: rootds0:driver-class-name: com.mysql.cj.jdbc.Driverpassword: 123456type: com.alibaba.druid.pool.DruidDataSourceurl: jdbc:mysql://192.168.200.129:3306/chongba_schedule0?serverTimezone=Asia/Shanghaiusername: rootnames: df,ds0sharding:tables:ok: actual-data-nodes: df.okkey-generator: #主鍵生成策略column: idtype: SNOWFLAKE

5.2.優化2

優化2:在延遲任務系統中我們有一個啟動后進行數據恢復,然后定時的預加載數據庫中的數據到緩存,我們查詢數據的時候是按照任務類型和優先級進行的分組查詢,

QueryWrapper qryWrapper = new QueryWrapper();
qryWrapper.select("task_type", "priority");
qryWrapper.groupBy("task_type","priority");
List<Map<String, Object>>  result = taskMapper.selectMaps(qryWrapper);

問題:分庫分表后要根據任務類型和優先級進行分組查詢,勢必要檢索所有數據源和所有表才能得到分組的結果,我們如何處理?

業務改造:對于任務的類型和優先級可以在后臺做成可配置的,建立一張表任務配置表taskConfig,存儲所有的任務類型和優先級分組關系,添加任務的時候,類型和優先級不得隨意指定,必須是配置表中已配置好的,這樣子,在做數據恢復的時候我們就無需從所有數據源中去分組檢索,而只需要從配置表中查詢數據即可

reloadData優化:

//改造成讀取字典表
List<TaskConfig> configList= taskConfigMapper.selectAll();
?
// QueryWrapper qryWrapper = new QueryWrapper();
// qryWrapper.select("task_type", "priority");
// qryWrapper.groupBy("task_type","priority");
// List<Map<String, Object>>  result = taskMapper.selectMaps(qryWrapper);
log.info("分組 {}",configList);

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/897966.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/897966.shtml
英文地址,請注明出處:http://en.pswp.cn/news/897966.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

向量數據庫對比以及Chroma操作

一、向量數據庫與傳統類型數據庫 向量數據庫&#xff08;Vector Storage Engine&#xff09;與傳統類型的數據庫如關系型數據庫&#xff08;MySQL&#xff09;、文檔型數據庫&#xff08;MongoDB&#xff09;、鍵值存儲&#xff08;Redis&#xff09;、全文搜索引擎&#xff0…

python列表基礎知識

列表 創建列表 1.列表的定義&#xff1a;可變的&#xff0c;有序的數據結構&#xff0c;可以隨時添加或者刪除其中的元素 2.基本語法&#xff1a;字面量【元素1&#xff0c;元素2&#xff0c;元素3】使用[]創建列表 定義變量&#xff1a;變量名稱【元素1&#xff0c;元素2&…

Node.js 的模塊作用域和 module 對象詳細介紹

目錄 代碼示例 1. 創建模塊文件 module-demo.js 2. 導入模塊并使用 module-demo.js 運行結果 總結 在 Node.js 中&#xff0c;每個文件都是一個獨立的模塊&#xff0c;具有自己的作用域。與瀏覽器 JavaScript 代碼不同&#xff0c;Node.js 采用模塊作用域&#xff0c;這意味…

美暢物聯丨WebRTC 技術詳解:構建實時通信的數字橋梁

在互聯網技術飛速發展的今天&#xff0c;實時通信已成為數字生活的核心需求。WebRTC作為一個開源項目&#xff0c;憑借卓越的技術實力與創新理念&#xff0c;為網頁和移動應用帶來了顛覆性的實時通信能力。它突破了傳統通信方式的限制&#xff0c;實現了音頻、視頻和數據在用戶…

excel中兩個表格的合并

使用函數&#xff1a; VLOOKUP函數 如果涉及在excel中兩個工作表之間進行配對合并&#xff0c;則&#xff1a; VLOOKUP(C1,工作表名字!A:B,2,0) 參考&#xff1a; excel表格中vlookup函數的使用方法步驟https://haokan.baidu.com/v?pdwisenatural&vid132733503560775…

單引號與雙引號在不同編程語言中的使用與支持

在編程語言中&#xff0c;單引號和雙引號是常見的符號&#xff0c;它們通常用來表示字符和字符串。然而&#xff0c;如何使用這兩種符號在不同的編程語言中有所不同&#xff0c;甚至有一些語言并不區分單引號和雙引號的用途。本文將詳細介紹不同編程語言中單引號與雙引號的支持…

怎么鑒別金媒v10.51和v10.5的區別!單單從CRM上區分!

2.怎么鑒別程序是10.5還是10.51 &#xff1f;* 作為商業用戶&#xff0c;升級完全沒有這個擔心&#xff0c;但是這次升級從全局來看清晰度不是很高&#xff0c;不像10.5的升級后臺UI都變化了&#xff01;你說有漏洞但是我沒遇到過 所以我也不知道升級了啥只能看版本數字是無法區…

python腳本實現服務器內存和cpu使用監控,并記錄日志,可以設置閾值和采樣頻率

Python 腳本&#xff0c;實現以下功能&#xff1a; 按日期自動生成日志文件&#xff08;例如 cpu_mem_20231001.csv&#xff09;當 CPU 或內存超過閾值時觸發記錄獨立記錄報警事件&#xff08;保存到 alert.log&#xff09;支持自定義閾值和監控間隔 腳本代碼 import psutil …

【Oracle】19c數據庫控制文件多路徑配置

一、關閉數據庫&#xff08;2個節點實例都要關閉&#xff09; srvctl stop database -d ora19c 二、多路徑控制文件 打開其中一個節點到nomount狀態 sqlplus / as sysdba startup nomount; [oracleora19c1:/home/oracle]$ rman target / RMAN> restore controlfile to…

大模型訓練全流程深度解析

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到網站。https://www.captainbed.cn/north 文章目錄 1. 大模型訓練概覽1.1 訓練流程總覽1.2 關鍵技術指標 2. 數據準備2.1 數據收集與清洗2.2 數據…

【Linux】進程(1)進程概念和進程狀態

&#x1f31f;&#x1f31f;作者主頁&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所屬專欄&#xff1a;Linux 目錄 前言 一、什么是進程 二、task_struct的內容 三、Linux下進程基本操作 四、父進程和子進程 1. 用fork函數創建子進程 五、進程狀態 1. 三種重…

lws-minimal-ws-server前端分析

index.html index.html是前端入口 <html><head><meta charsetutf-8 http-equiv"Content-Language" content"en"/><!-- 引入js --><script src"/example.js"></script></head><body><img s…

L1-7 統一命名規范(java)

你所在的公司剛剛招收了幾位程序員&#xff0c;然而這些程序員之前在不同的公司工作&#xff0c;所以他們習慣的變量命名規范可能存在差異&#xff0c;需要讓他們都習慣公司要求的命名規范&#xff0c;然而這樣可能會降低他們的工作效率。 你的上司找到了你&#xff0c;希望你…

Flexus應用服務器L實例、X實例以及ECS(彈性計算服務)之間的區別及其適用場景

為了更好地理解Flexus應用服務器L實例、X實例以及ECS&#xff08;彈性計算服務&#xff09;之間的區別及其適用場景&#xff0c;下面我將通過具體的例子來說明每種類型的使用情況。 1. Flexus L實例 特點: 針對高并發和負載均衡進行了優化。它可能包括更快的網絡接口、更高效…

WebRTC中音視頻服務質量QoS之RTT衡量網絡往返時延的加權平均RTT計算機制?詳解

WebRTC中音視頻服務質量QoS之RTT衡量網絡往返時延加權平均RTT計算機制?的詳解 WebRTC中音視頻服務質量QoS之RTT衡量網絡往返時延加權平均RTT計算機制?的詳解 WebRTC中音視頻服務質量QoS之RTT衡量網絡往返時延加權平均RTT計算機制?的詳解前言一、 RTT 網絡往返時延的原理?1、…

odbus TCP轉Modbus RTU網關快速配置案例

Modbus TCP 轉Modbus RTU網關快速配置案例 在工業自動化領域&#xff0c;Modbus 協議以其簡潔和高效而著稱&#xff0c;成為眾多設備通信的首選。 隨著技術的發展和應用場景的變化&#xff0c;Modbus 協議也發展出了不同的版本&#xff0c;其中 Modbus TCP 和 Modbus RTU 是兩種…

《高效遷移學習:Keras與EfficientNet花卉分類項目全解析》

從零到精通的遷移學習實戰指南&#xff1a;以Keras和EfficientNet為例 一、為什么我們需要遷移學習&#xff1f; 1.1 人類的學習智慧 想象一下&#xff1a;如果一個已經會彈鋼琴的人學習吉他&#xff0c;會比完全不懂音樂的人快得多。因為TA已經掌握了樂理知識、節奏感和手指…

WSL2 Ubuntu安裝GCC不同版本

WSL2 Ubuntu安裝GCC不同版本 介紹安裝gcc 7.1方法 1&#xff1a;通過源碼編譯安裝 GCC 7.1步驟 1&#xff1a;安裝編譯依賴步驟 2&#xff1a;下載 GCC 7.1 源碼步驟 3&#xff1a;配置和編譯步驟 4&#xff1a;配置環境變量步驟 5&#xff1a;驗證安裝 方法 2&#xff1a;通過…

淘寶API vs 爬蟲:合規獲取實時商品數據的成本與效率對比

以下是淘寶 API 和爬蟲在合規獲取實時商品數據方面的成本與效率對比&#xff1a; 成本對比 淘寶 API 開發成本&#xff1a;需要申請開發者賬號并獲取 API 權限&#xff0c;部分敏感或高頻訪問的接口可能需要額外的審核或付費。開發過程中需要按照平臺規定進行編程&#xff0c;相…

Android 手機啟動過程

梳理 為了梳理思路&#xff0c;筆者畫了一幅關于 Android 手機啟動的過程圖片內容純屬個人見解&#xff0c;如有錯誤&#xff0c;歡迎各位指正