(springboot系列)springboot+sharding+動(dòng)態(tài)數(shù)據(jù)源

1. sharding簡(jiǎn)介

ShardingSphere是一套開(kāi)源的分布式數(shù)據(jù)庫(kù)中間件解決方案組成的生態(tài)圈,目前已在阿帕奇孵化成功,它由Sharding-JDBC恩脂、Sharding-Proxy和Sharding-Sidecar(計(jì)劃中)這3款相互獨(dú)立的產(chǎn)品組成缸剪,這里主要介紹shardingjdbc,文檔地址 https://shardingsphere.apache.org/document/current/cn/overview/

2. 使用

1.引入maven包

這里不適用start包,而直接使用原包,這里還需要排除sharding的mysql連接器,使用自己的連接器

<!-- https://mvnrepository.com/artifact/io.shardingsphere/sharding-jdbc-core -->
<dependency>
    <groupId>io.shardingsphere</groupId>
    <artifactId>sharding-jdbc-core</artifactId>
    <version>3.1.0</version>
    <exclusions>
        <exclusion>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </exclusion>
    </exclusions>
</dependency>

2.配置

sharding和動(dòng)態(tài)數(shù)據(jù)源整合一起,因?yàn)閟harding會(huì)全局解析所有sql,在某些情況下mybatis能解析的sql語(yǔ)句sharding是沒(méi)辦法解析的,會(huì)導(dǎo)致以前的業(yè)務(wù)sql出現(xiàn)問(wèn)題,所以我們通過(guò)動(dòng)態(tài)數(shù)據(jù)源和注解的形式標(biāo)注哪些sql需要使用sharding的數(shù)據(jù)源,靈活配置

DynamicDataSource

/**
 * 動(dòng)態(tài)數(shù)據(jù)源
 * Created by tyf on 2019/9/25 0025
 */
public class DynamicDataSource extends AbstractRoutingDataSource {


    //用來(lái)保存數(shù)據(jù)源與獲取數(shù)據(jù)源
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    public DynamicDataSource(DataSource defaultTargetDataSource, Map<String, DataSource> targetDataSources) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(new HashMap<>(targetDataSources));
        super.afterPropertiesSet();
    }

    public static void setDataSource(String dataSource) {
        contextHolder.set(dataSource);
    }

    public static String getDataSource() {
        return contextHolder.get();
    }

    public static void clearDataSource() {
        contextHolder.remove();
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return getDataSource();
    }
}

ShardingDataSourceAspect 動(dòng)態(tài)數(shù)據(jù)源aop切面,使用springboot的方式

/**
 * 動(dòng)態(tài)數(shù)據(jù)源aop切面
 * Created by tyf on 2019/9/25 0025
 */
@Aspect
public class ShardingDataSourceAspect {

    @Around(ExecutionConstant.CONTROLLER + "||" + ExecutionConstant.SERVICE)
    public Object around(ProceedingJoinPoint point) throws Throwable {
        // 獲取方法名
        String methodName = point.getSignature().getName();
        // 反射獲取目標(biāo)類(lèi)
        Class<?> targetClass = point.getTarget().getClass();
        // 拿到方法對(duì)應(yīng)的參數(shù)類(lèi)型
        Class<?>[] parameterTypes = ((MethodSignature) point.getSignature()).getParameterTypes();
        // 根據(jù)類(lèi)、方法东亦、參數(shù)類(lèi)型(重載)獲取到方法的具體信息
        Method method = targetClass.getMethod(methodName, parameterTypes);

        final ShardingDataSource methodAnnotation = AnnotationUtils.findAnnotation(method, ShardingDataSource.class);
        final ShardingDataSource classAnnotation = AnnotationUtils.findAnnotation(targetClass, ShardingDataSource.class);

        //當(dāng)類(lèi)和方法上都沒(méi)注解的時(shí)候,跳過(guò)
        if (methodAnnotation == null && classAnnotation == null) {
            return point.proceed();
        }

        DynamicDataSource.setDataSource(DataSourceNames.SHARDING);
        try {
            return point.proceed();
        } finally {
            DynamicDataSource.clearDataSource();
        }
    }

}

ShardingDataSource,注解

/**
 * Created by tyf on 2019/9/25 0025
 */
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ShardingDataSource {
}

DataSourceNames常量

/**
 * Created by tyf on 2019/9/25 0025
 */
public interface DataSourceNames {

    String DEFAULT = "default";
    String SHARDING = "sharding";

}

ShardingConfiguration,sharding配置類(lèi),將配置抽象在基礎(chǔ)包中,只有當(dāng)業(yè)務(wù)項(xiàng)目有ShardingRuleConfiguration類(lèi)之后才會(huì)加載sharding配置類(lèi)

@Configuration
@DependsOn("springTools")
@ConditionalOnBean({ShardingRuleConfiguration.class})
public class ShardingConfiguration {


    /**
     * 代理切面類(lèi)
     *
     * @return
     */
    @Bean
    public ShardingDataSourceAspect shardingDataSourceAspect() {
        return new ShardingDataSourceAspect();
    }

    /**
     * 多數(shù)據(jù)源,默認(rèn)為springboot數(shù)據(jù)源,使用{@link ShardingDataSource} 標(biāo)記為sharding數(shù)據(jù)源
     *
     * @param dataSourceProperties
     * @param shardingRuleConfiguration
     * @return
     * @throws SQLException
     */
    @Bean
    @Primary
    public DynamicDataSource dataSource(DataSourceProperties dataSourceProperties, ShardingRuleConfiguration shardingRuleConfiguration) throws SQLException {
        //初始化springboot數(shù)據(jù)源
        final DataSource dataSource = dataSourceProperties.initializeDataSourceBuilder().build();

        //設(shè)置動(dòng)態(tài)數(shù)據(jù)源
        Map<String, DataSource> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceNames.DEFAULT, dataSource);
        targetDataSources.put(DataSourceNames.SHARDING, getShardingDataSource(dataSource, shardingRuleConfiguration));
        return new DynamicDataSource(dataSource, targetDataSources);
    }


    private DataSource getShardingDataSource(DataSource dataSource, ShardingRuleConfiguration shardingRuleConfiguration) throws SQLException {
        final Properties properties = new Properties();

        // 獲取數(shù)據(jù)源對(duì)象
        final DataSource shardingDatasource = ShardingDataSourceFactory.createDataSource(ImmutableMap.of("ds0", dataSource),
                shardingRuleConfiguration, new ConcurrentHashMap(), properties);
        return shardingDatasource;
    }

}

在業(yè)務(wù)項(xiàng)目中,你只需要配置ShardingRuleConfiguration即可開(kāi)箱使用sharding了,例如

    /**
     * sharding分片規(guī)則
     *
     * @return
     */
    @Bean
    @Primary
    public ShardingRuleConfiguration shardingRuleConfiguration() {
        final ShardingRuleConfiguration shardingRuleConfiguration = new ShardingRuleConfiguration();
        TableRuleConfiguration sappPaperRankingTableRuleConfig = new TableRuleConfiguration();
        sappPaperRankingTableRuleConfig.setLogicTable("sapp_paper_ranking");

        //選需要分片的對(duì)應(yīng)的庫(kù)和表
        sappPaperRankingTableRuleConfig.setActualDataNodes("ds0.sapp_paper_ranking_0${1..9},ds0.sapp_paper_ranking_${10..31}");
        // 配置分庫(kù) + 分表策略
        sappPaperRankingTableRuleConfig.setDatabaseShardingStrategyConfig(new NoneShardingStrategyConfiguration());
        sappPaperRankingTableRuleConfig.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration(
                "create_date", new SappPaperRankingPreciseShardingAlgorithm()));
        // 配置分片規(guī)則
        shardingRuleConfiguration.getTableRuleConfigs().add(sappPaperRankingTableRuleConfig);
        return shardingRuleConfiguration;
    }
    
    
    /**
     * 精確分片算法,=與IN進(jìn)行分片
     */
    public class SappPaperRankingPreciseShardingAlgorithm implements PreciseShardingAlgorithm<Integer> {
        @Override
        public String doSharding(Collection<String> tableNames/*表名*/, PreciseShardingValue<Integer> shardingValue /*分片鍵*/) {
    
            final Integer uid = shardingValue.getValue();
            
            /*省略*/
            
            throw new UnsupportedOperationException();
        }
    }

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末杏节,一起剝皮案震驚了整個(gè)濱河市唬渗,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奋渔,老刑警劉巖镊逝,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異嫉鲸,居然都是意外死亡撑蒜,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)玄渗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)座菠,“玉大人,你說(shuō)我怎么就攤上這事藤树≡〉危” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵岁钓,是天一觀的道長(zhǎng)升略。 經(jīng)常有香客問(wèn)我,道長(zhǎng)屡限,這世上最難降的妖魔是什么品嚣? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮钧大,結(jié)果婚禮上翰撑,老公的妹妹穿的比我還像新娘。我一直安慰自己啊央,他們只是感情好眶诈,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著劣挫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪东帅。 梳的紋絲不亂的頭發(fā)上压固,一...
    開(kāi)封第一講書(shū)人閱讀 51,165評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音靠闭,去河邊找鬼帐我。 笑死,一個(gè)胖子當(dāng)著我的面吹牛愧膀,可吹牛的內(nèi)容都是我干的拦键。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼檩淋,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼芬为!你這毒婦竟也來(lái)了萄金?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤媚朦,失蹤者是張志新(化名)和其女友劉穎氧敢,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體询张,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡孙乖,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了份氧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片唯袄。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蜗帜,靈堂內(nèi)的尸體忽然破棺而出恋拷,到底是詐尸還是另有隱情,我是刑警寧澤钮糖,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布梅掠,位于F島的核電站,受9級(jí)特大地震影響店归,放射性物質(zhì)發(fā)生泄漏阎抒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一消痛、第九天 我趴在偏房一處隱蔽的房頂上張望且叁。 院中可真熱鬧,春花似錦秩伞、人聲如沸逞带。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)展氓。三九已至,卻和暖如春脸爱,著一層夾襖步出監(jiān)牢的瞬間遇汞,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工簿废, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留空入,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓族檬,卻偏偏與公主長(zhǎng)得像歪赢,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子单料,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容