在线不卡日本ⅴ一区v二区_精品一区二区中文字幕_天堂v在线视频_亚洲五月天婷婷中文网站

  • <menu id="lky3g"></menu>
  • <style id="lky3g"></style>
    <pre id="lky3g"><tt id="lky3g"></tt></pre>

    spring多數(shù)據(jù)源實(shí)現(xiàn)讀寫分離

    一、常用場景

    讀寫分離:寫走主庫,讀走從庫

    分庫分表:通常有兩種路由算法,范圍或hash。

    二、讀寫分離實(shí)現(xiàn)方法

    1.實(shí)現(xiàn)動態(tài)數(shù)據(jù)源

    spring提供了抽象類AbstractRoutingDataSource,里面有兩個重要的參數(shù),

    targetDataSources代表提供的數(shù)據(jù)源。

    defaultTargetDataSource代表默認(rèn)數(shù)據(jù)源。

    public void setTargetDataSources(Map targetDataSources) { this.targetDataSources = targetDataSources;}public void setDefaultTargetDataSource(Object defaultTargetDataSource) { this.defaultTargetDataSource = defaultTargetDataSource;}

    還有一個抽象方法

    @Nullableprotected abstract Object determineCurrentLookupKey();

    我們可以繼承AbstractRoutingDataSource,實(shí)現(xiàn)determineCurrentLookupKey方法進(jìn)行動態(tài)路由數(shù)據(jù)源。實(shí)現(xiàn)如下:

    public class DynamicRoutingDataSource extends AbstractRoutingDataSource { private static ThreadLocal ROUTING_KEY = new ThreadLocal(); @Override protected Object determineCurrentLookupKey() { return ROUTING_KEY.get(); } public static void setRoutingKey(String routingKey) { ROUTING_KEY.set(routingKey); } public static void removeRoutingKey() { ROUTING_KEY.remove(); } //不用重寫改方法,這里是為了打印數(shù)據(jù)源信息 @Override public Connection getConnection() throws SQLException { DataSource dataSource = this.determineTargetDataSource(); logger.info(dataSource); return dataSource.getConnection(); }}

    2.基于注解的方式,實(shí)現(xiàn)動態(tài)切換數(shù)據(jù)源

    @Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Master {}@Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Slave {}@Aspect@Component@Order(-99)public class MasterAop { @Pointcut(“@annotation(com.example.demo.aop.Master)”) public void recordAspect() {} @Around(“recordAspect()”) public Object recordAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { try { DynamicRoutingDataSource.setRoutingKey(“master”); return proceedingJoinPoint.proceed(); } finally { DynamicRoutingDataSource.removeRoutingKey(); } }}@Aspect@Component@Order(-99)public class SlaveAop { @Pointcut(“@annotation(com.example.demo.aop.Slave)”) public void recordAspect() { } @Around(“recordAspect()”) public Object recordAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { try { DynamicRoutingDataSource.setRoutingKey(“slave”); return proceedingJoinPoint.proceed(); } finally { DynamicRoutingDataSource.removeRoutingKey(); } }}

    3.配置數(shù)據(jù)源

    @Bean@Primarypublic DataSource dataSource() { DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource(); HikariConfig masterHikariConfig = new HikariConfig(); masterHikariConfig.setPassword(“xx”); masterHikariConfig.setUsername(“xx”); masterHikariConfig.setDriverClassName(“com.mysql.cj.jdbc.Driver”); masterHikariConfig.setJdbcUrl(“jdbc:mysql://xxxx?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true”); masterHikariConfig.setPoolName(“masterPool”); HikariDataSource masterDataSource = new HikariDataSource(masterHikariConfig); HikariConfig slaveHikariConfig = new HikariConfig(); slaveHikariConfig.setPassword(“xx”); slaveHikariConfig.setUsername(“xx”); slaveHikariConfig.setDriverClassName(“com.mysql.cj.jdbc.Driver”); slaveHikariConfig.setJdbcUrl(“jdbc:mysql://xxxx?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true”); slaveHikariConfig.setPoolName(“slavePool”); HikariDataSource slaveDataSource = new HikariDataSource(slaveHikariConfig); HashMap targetDataSources = new HashMap(); targetDataSources.put(“master”, masterDataSource); targetDataSources.put(“slave”, slaveDataSource); dynamicRoutingDataSource.setTargetDataSources(targetDataSources); return dynamicRoutingDataSource;}

    4.實(shí)現(xiàn)一個測試Service

    @Service@Slf4jpublic class MasterSlaveService { @Slave @Transactional public void slaveTest() { } @Master @Transactional public void masterTest() { }}

    5.測試如下

    @SpringBootApplication@EnableTransactionManagementpublic class RoutingDataSourceDemoApplication { public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication.run(RoutingDataSourceDemoApplication.class, args); MasterSlaveService bean = run.getBean(MasterSlaveService.class); bean.masterTest(); bean.slaveTest(); }}

    我們可以看到數(shù)據(jù)源的切換信息

    com.zaxxer.hikari.HikariDataSource : masterPool – Starting…com.zaxxer.hikari.HikariDataSource : masterPool – Start completed.com.zaxxer.hikari.HikariDataSource : slavePool – Starting…com.zaxxer.hikari.HikariDataSource : slavePool – Start completed.c.e.d.RoutingDataSourceDemoApplication : Started RoutingDataSourceDemoApplication in 2.054 seconds (JVM running for 2.682)c.e.d.d.DynamicRoutingDataSource : HikariDataSource (masterPool)c.e.d.d.DynamicRoutingDataSource : HikariDataSource (slavePool)

    三、其他

    如果業(yè)務(wù)簡單,我們可以自己實(shí)現(xiàn)數(shù)據(jù)源的切換,如果復(fù)雜的話,建議使用ShardingSphere框架,ShardingSphere是基于更底層的jdbc代理實(shí)現(xiàn)。

    鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場,版權(quán)歸原作者所有,如有侵權(quán)請聯(lián)系管理員(admin#wlmqw.com)刪除。
    上一篇 2022年7月1日 12:57
    下一篇 2022年7月1日 12:57

    相關(guān)推薦

    聯(lián)系我們

    聯(lián)系郵箱:admin#wlmqw.com
    工作時間:周一至周五,10:30-18:30,節(jié)假日休息