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
LogShardingAlgorithmimplements
PreciseShardingAlgorithm, RangeShardingAlgorithm {private
List<String
> tables;private
finalString
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 - shardValue0
) {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
voidinit
() { this.loadLogInit(); }private
void loadLogInit() {if
(dataSource instanceofShardingDataSource
) {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
CollectiondoSharding
(
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>