sharding sphere 4.0.0-RC1版本 按年分表(後續優化)

sharding sphere 4.0.0-RC1版本 按年分表(後續優化)


1. sharding sphere 4.0.0-RC1版本 按年分表(後續優化)

1.1. 概述

關於上一篇中LogShardingAlgorithm的tables,我原先是在第一次調用的時候初始化,這樣做雖然能實現功能,但每次調用都會走這個if判斷,雖然性能損耗不大,但我覺得這不是業務應該走的邏輯順序,我的理想是在LogShardingAlgorithm被實例化後去自動初始化tables

現在面對的問題是LogShardingAlgorithm的實例化是在Spring初始化中間執行的,且它本身的創建不是通過Spring的@Component等註解生成,而是通過反射實例化。若在實例化剛開始,也就是構造方法執行的時候執行初始化,那時候applicationContext還沒有初始化完畢,拿不到環境參數,連Datasource也還沒開始初始化


1.2. 解決方法

經過改造後,代碼如下,單獨拎出一個初始化方法,在類對象實例化後調用

<code> 
 

public

class

LogShardingAlgorithm

implements

PreciseShardingAlgorithm, RangeShardingAlgorithm {

private

List<

String

> tables;

private

final

String

systemLogHead =

"system_log_"

;

public

void

init(){ tables = DBUtil.getAllSystemLogTable(); }

public

String

doSharding(Collection availableTargetNames, PreciseShardingValue shardingValue) {

String

target = shardingValue.getValue().toString();

String

year = target.substring(target.lastIndexOf(

"_"

) +

1

, target.lastIndexOf(

"_"

) +

5

);

if

(!tables.contains(systemLogHead + year)) { DBUtil.createLogTable(year); tables.add(year); }

return

shardingValue.getLogicTableName() +

"_"

+ year; }

public

Collection<

String

> doSharding(Collection<

String

> availableTargetNames, RangeShardingValue shardingValue) { Collection<

String

> availables =

new

ArrayList<>(); Range valueRange = shardingValue.getValueRange();

for

(

String

target : tables) { Integer shardValue = Integer.parseInt(target.substring(target.lastIndexOf(

"_"

) +

1

, target.lastIndexOf(

"_"

) +

5

));

if

(valueRange.hasLowerBound()) {

String

lowerStr = valueRange.lowerEndpoint().toString(); Integer start = Integer.parseInt(lowerStr.substring(

0

,

4

));

if

(start - shardValue >

0

) {

continue

; } }

if

(valueRange.hasUpperBound()) {

String

upperStr = valueRange.upperEndpoint().toString(); Integer end = Integer.parseInt(upperStr.substring(

0

,

4

));

if

(end - shardValue

0

) {

continue

; } } availables.add(target); }

return

availables; } }/<code>

其中init方法通過另一個類實例化完成後調用,難點在於如何拿到該實例化的LogShardingAlgorithm

<code>

import

cn.hutool.core.util.ReflectUtil;

import

com.google.common.base.Optional;

import

com.onegene.platform.system.log.LogShardingAlgorithm;

import

org.apache.shardingsphere.core.rule.ShardingRule;

import

org.apache.shardingsphere.core.rule.TableRule;

import

org.apache.shardingsphere.core.strategy.route.ShardingStrategy;

import

org.apache.shardingsphere.shardingjdbc.jdbc.core.ShardingContext;

import

org.apache.shardingsphere.shardingjdbc.jdbc.core.datasource.ShardingDataSource;

import

org.springframework.beans.factory.annotation.Autowired;

import

org.springframework.stereotype.Component;

import

javax.annotation.PostConstruct;

import

javax.sql.DataSource; @

Component

public

class

StartupConfig

{ @

Autowired

private

DataSource

dataSource; @

PostConstruct

public

void

init

() { this.loadLogInit(); }

private

void loadLogInit() {

if

(dataSource instanceof

ShardingDataSource

) {

ShardingDataSource

sds = (

ShardingDataSource

) dataSource;

ShardingContext

shardingContext = sds.getShardingContext();

ShardingRule

shardingRule = shardingContext.getShardingRule();

Optional

<

TableRule

> systemLog = shardingRule.findTableRule(

"system_log"

);

TableRule

tableRule = systemLog.orNull();

if

(tableRule != null) {

ShardingStrategy

tableShardingStrategy = tableRule.getTableShardingStrategy();

LogShardingAlgorithm

preciseShardingAlgorithm = (

LogShardingAlgorithm

)

ReflectUtil

.getFieldValue(tableShardingStrategy,

"preciseShardingAlgorithm"

);

LogShardingAlgorithm

rangeShardingAlgorithm = (

LogShardingAlgorithm

)

ReflectUtil

.getFieldValue(tableShardingStrategy,

"rangeShardingAlgorithm"

); preciseShardingAlgorithm.

init

(); rangeShardingAlgorithm.

init

(); } } } }/<code>


1.3. 總結

通過查看源碼可以知道,它最後把LogShardingAlgorithm實例化的對象放入了ShardingDataSource,那我們就要從裡面把它取出來,若它正常沒提供get方法,那我們就用反射硬把它取出來

通過上述代碼可以看出,範圍分片和精確分片需要實例化兩個類,我想是否可以合到一個類,網上也找了一下,發現有的版本使用
ComplexKeysShardingAlgorithm算法是可以同時實現範圍和精確分片查詢的,但經過我實際測試,現在的4.0.0版本不行,原因在於以下代碼,此為複雜分片源碼

<code>

public

final

class

ComplexShardingStrategy

implements

ShardingStrategy

{

private

final

Collection shardingColumns;

private

final

ComplexKeysShardingAlgorithm shardingAlgorithm;

public

ComplexShardingStrategy

(

final

ComplexShardingStrategyConfiguration complexShardingStrategyConfig)

{ Preconditions.checkNotNull(complexShardingStrategyConfig.getShardingColumns(),

"Sharding columns cannot be null."

); Preconditions.checkNotNull(complexShardingStrategyConfig.getShardingAlgorithm(),

"Sharding algorithm cannot be null."

); shardingColumns =

new

TreeSet<>(String.CASE_INSENSITIVE_ORDER); shardingColumns.addAll(Splitter.on(

","

).trimResults().splitToList(complexShardingStrategyConfig.getShardingColumns())); shardingAlgorithm = complexShardingStrategyConfig.getShardingAlgorithm(); } (

"unchecked"

)

public

Collection

doSharding

(

final

Collection availableTargetNames,

final

Collection shardingValues)

{ Map>> columnShardingValues =

new

HashMap<>(shardingValues.size(),

1

); String logicTableName =

""

;

for

(RouteValue each : shardingValues) { columnShardingValues.put(each.getColumnName(), ((ListRouteValue) each).getValues()); logicTableName = each.getTableName(); } Collection shardingResult = shardingAlgorithm.doSharding(availableTargetNames,

new

ComplexKeysShardingValue(logicTableName, columnShardingValues)); Collection result =

new

TreeSet<>(String.CASE_INSENSITIVE_ORDER); result.addAll(shardingResult);

return

result; } }/<code>


分享到:


相關文章: