国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

springboot實踐筆記之一:springboot+sharding-jdbc+mybatis全

Snailclimb / 1049人閱讀

摘要:現在的分片策略是上海深圳分別建庫,每個庫都存各自交易所的兩支股票的,且按照月分表。五配置分片策略數據庫分片策略在這個實例中,數據庫的分庫就是根據上海和深圳來分的,在中是單鍵分片。

由于當當發布了最新的Sharding-Sphere,所以本文已經過時,不日將推出新的版本

項目中遇到了分庫分表的問題,找到了shrding-jdbc,于是就搞了一個springboot+sharding-jdbc+mybatis的增量分片的應用。今天寫博客總結一下遇到的坑。

其實,我自己寫了一個increament-jdbc組件的,當我讀了sharding-jdbc的源碼之后,發現思路和原理差不多,sharding這個各方面要比我的強,畢竟我是一天之內趕出來的東東。

示例代碼地址:https://gitee.com/spartajet/s...

demo沒有寫日志,也沒有各種異常判斷,只是說明問題

一、需求背景

我的項目背景就不說了,現在舉一個例子吧:A,B兩支股票都在上海,深圳上市,需要實時記錄這兩支股票的交易tick(不懂tick也沒有關系)。現在的分片策略是:上海、深圳分別建庫,每個庫都存各自交易所的兩支股票的ticktick,且按照月分表。如圖:

db_sh

tick_a_2017_01

tick_b_2017_01

........

tick_a_2017_12

tick_b_2017_12

db_sz

tick_a_2017_01

tick_b_2017_01

........

tick_a_2017_12

tick_b_2017_12

分庫分表就是這樣的。根據這個建庫。

**千萬不要討論這樣分庫分表是否合適,這里這樣分片只是舉個栗子,說明分庫分表這個事情。**

**Sharding-jdbc是不支持建庫的SQL,如果像我這樣增量的數據庫和數據表,那就要一次性把一段時期的數據庫和數據表都要建好。**
二、建庫

考慮到表確實多,所以我就只建1,2月份的表。語句見demo文件。

三、springboot集成sharding-jdbc

mvn配置pom如下:

com.spartajet
    springboot-sharding-jdbc-demo
    0.0.1-SNAPSHOT
    jar

    springboot-sharding-jdbc-demo
    Springboot integrate Sharding-jdbc Demo

    
        UTF-8
        UTF-8
        UTF-8
        zh_CN
        1.8
        ${java.version}
        1.4.1.RELEASE
        1.0.13
        5.1.36
        1.4.1
        2.8.0
        2.9.7
        1.4
        2.5
        1.2.0
    

    
        
            org.springframework.boot
            spring-boot-starter-jdbc
            ${spring.boot.version}
        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            ${mybatis-spring-boot-starter.version}
        
        
            commons-dbcp
            commons-dbcp
            ${commons-dbcp.version}
        
        
            com.dangdang
            sharding-jdbc-core
            ${sharding-jdbc.version}
        
        
            com.dangdang
            sharding-jdbc-config-spring
            ${sharding-jdbc.version}
        
        
            com.dangdang
            sharding-jdbc-self-id-generator
            ${sharding-jdbc.version}
        
        
            com.google.code.gson
            gson
            ${com.google.code.gson.version}
        
        
            org.springframework.boot
            spring-boot-starter-web
            ${spring.boot.version}
            
                
                    org.springframework.boot
                    spring-boot-start-logging
                
            
        
        
            org.springframework.boot
            spring-boot-starter-test
            ${spring.boot.version}
            test
        
        
            org.springframework.boot
            spring-boot-starter-log4j2
            ${spring.boot.version}
            
                
                    log4j
                    log4j
                
            
        
        
            org.springframework.boot
            spring-boot-starter
            ${spring.boot.version}
            
                
                    org.springframework.boot
                    spring-boot-start-logging
                
                
                    logback-classic
                    ch.qos.logback
                
                
                    log4j-over-slf4j
                    org.slf4j
                
            
        
        
            mysql
            mysql-connector-java
            ${mysql-connector-java.version}
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                ${spring.boot.version}
            
            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.1
                
                    ${project.build.jdk}
                    ${project.build.jdk}
                    ${project.build.sourceEncoding}
                
            
            
                org.apache.maven.plugins
                maven-jar-plugin
                2.4
            
        
    

其實這個和sharding-jdbc的官網差不多。其實我想寫一個sharding-jdbc-spring-boot-starter的pom的,等項目業務都做完再說吧。

四、配置數據源

我想將數據庫做成可配置的,所以我沒有在application.properties文件中直接配置數據庫,而是寫在了database.json文件中。

[
  {
    "name": "db_sh",
    "url": "jdbc:mysql://localhost:3306/db_sh",
    "username": "root",
    "password": "root",
    "driveClassName":"com.mysql.jdbc.Driver"
  },
  {
    "name": "db_sz",
    "url": "jdbc:mysql://localhost:3306/db_sz",
    "username": "root",
    "password": "root",
    "driveClassName":"com.mysql.jdbc.Driver"
  }
]

然后在springboot讀取database文件,加載方式如下:

@Value("classpath:database.json")
    private Resource databaseFile;

    @Bean
    public List databases() throws IOException {
        String databasesString = IOUtils.toString(databaseFile.getInputStream(), Charset.forName("UTF-8"));
        List databases = new Gson().fromJson(databasesString, new TypeToken>() {
        }.getType());
        return databases;
    }

加載完database信息之后,可以通過工廠方法配置邏輯數據庫:

    @Bean
    public HashMap dataSourceMap(List databases) {
        Map dataSourceMap = new HashMap<>();
        for (Database database : databases) {
            DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
            dataSourceBuilder.url(database.getUrl());
            dataSourceBuilder.driverClassName(database.getDriveClassName());
            dataSourceBuilder.username(database.getUsername());
            dataSourceBuilder.password(database.getPassword());
            DataSource dataSource = dataSourceBuilder.build();
            dataSourceMap.put(database.getName(), dataSource);
        }
        return dataSourceMap;
    }

這樣就把各個邏輯數據庫就加載好了。

五、配置分片策略 5.1數據庫分片策略

在這個實例中,數據庫的分庫就是根據上海(sh)和深圳(sz)來分的,在sharding-jdbc中是單鍵分片。根據官方文檔實現接口SingleKeyDatabaseShardingAlgorithm就可以

@service
public class DatabaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm {
    /**
     * 根據分片值和SQL的=運算符計算分片結果名稱集合.
     *
     * @param availableTargetNames 所有的可用目標名稱集合, 一般是數據源或表名稱
     * @param shardingValue        分片值
     *
     * @return 分片后指向的目標名稱, 一般是數據源或表名稱
     */
    @Override
    public String doEqualSharding(Collection availableTargetNames, ShardingValue shardingValue) {
        String databaseName = "";
        for (String targetName : availableTargetNames) {
            if (targetName.endsWith(shardingValue.getValue())) {
                databaseName = targetName;
                break;
            }
        }
        return databaseName;
    }
}

此接口還有另外兩個方法,doInShardingdoBetweenSharding,因為我暫時不用IN和BETWEEN方法,所以就沒有寫,直接返回null。

5.2數據表分片策略

數據表的分片策略是根據股票和時間共同決定的,在sharding-jdbc中是多鍵分片。根據官方文檔,實現MultipleKeysTableShardingAlgorithm接口就OK了

@service
public class TableShardingAlgorithm implements MultipleKeysTableShardingAlgorithm {
    /**
     * 根據分片值計算分片結果名稱集合.
     *
     * @param availableTargetNames 所有的可用目標名稱集合, 一般是數據源或表名稱
     * @param shardingValues       分片值集合
     *
     * @return 分片后指向的目標名稱集合, 一般是數據源或表名稱
     */
    @Override
    public Collection doSharding(Collection availableTargetNames, Collection> shardingValues) {
        String name = null;
        Date time = null;
        for (ShardingValue shardingValue : shardingValues) {
            if (shardingValue.getColumnName().equals("name")) {
                name = ((ShardingValue) shardingValue).getValue();
            }
            if (shardingValue.getColumnName().equals("time")) {
                time = ((ShardingValue) shardingValue).getValue();
            }
            if (name != null && time != null) {
                break;
            }
        }
        String timeString = new SimpleDateFormat("yyyy_MM").format(time);
        String suffix = name + "_" + timeString;
        Collection result = new LinkedHashSet<>();
        for (String targetName : availableTargetNames) {
            if (targetName.endsWith(suffix)) {
                result.add(targetName);
            }
        }
        return result;
    }
}

這些方法的使用可以查官方文檔。

5.3注入分片策略

以上只是定義了分片算法,還沒有形成策略,還沒有告訴shrding將哪個字段給分片算法:

@Configuration
public class ShardingStrategyConfig {
    @Bean
    public DatabaseShardingStrategy databaseShardingStrategy(DatabaseShardingAlgorithm databaseShardingAlgorithm) {
        DatabaseShardingStrategy databaseShardingStrategy = new DatabaseShardingStrategy("exchange", databaseShardingAlgorithm);
        return databaseShardingStrategy;
    }

    @Bean
    public TableShardingStrategy tableShardingStrategy(TableShardingAlgorithm tableShardingAlgorithm) {
        Collection columns = new LinkedList<>();
        columns.add("name");
        columns.add("time");
        TableShardingStrategy tableShardingStrategy = new TableShardingStrategy(columns, tableShardingAlgorithm);
        return tableShardingStrategy;
    }
}

這樣才能形成完成的分片策略。

六、配置Sharding-jdbc的DataSource

sharding-jdbc的原理其實很簡單,就是自己做一個DataSource給上層應用使用,這個DataSource包含所有的邏輯庫和邏輯表,應用增刪改查時,他自己再修改sql,然后選擇合適的數據庫繼續操作。所以這個DataSource創建很重要。

    @Bean
    @Primary
    public DataSource shardingDataSource(HashMap dataSourceMap, DatabaseShardingStrategy databaseShardingStrategy, TableShardingStrategy tableShardingStrategy) {
        DataSourceRule dataSourceRule = new DataSourceRule(dataSourceMap);
        TableRule tableRule = TableRule.builder("tick").actualTables(Arrays.asList("db_sh.tick_a_2017_01", "db_sh.tick_a_2017_02", "db_sh.tick_b_2017_01", "db_sh.tick_b_2017_02", "db_sz.tick_a_2017_01", "db_sz.tick_a_2017_02", "db_sz.tick_b_2017_01", "db_sz.tick_a_2017_02")).dataSourceRule(dataSourceRule).build();
        ShardingRule shardingRule = ShardingRule.builder().dataSourceRule(dataSourceRule).tableRules(Arrays.asList(tableRule)).databaseShardingStrategy(databaseShardingStrategy).tableShardingStrategy(tableShardingStrategy).build();
        DataSource shardingDataSource = ShardingDataSourceFactory.createDataSource(shardingRule);
        return shardingDataSource;
    }

這里要著重說一下為什么要用@Primary這個注解,沒有這個注解是會報錯的,錯誤大致意思就是DataSource太多了,mybatis不知道用哪個。加上這個mybatis就知道用sharding的DataSource了。這里參考的是jpa的多數據源配置

七、配置mybatis 7.1 Bean
public class Tick {
    private long id;
    private String name;
    private String exchange;
    private int ask;
    private int bid;
    private Date time;
}
7.2 Mapper

很簡單,只實現一個插入方法

@Mapper
public interface TickMapper {
    @Insert("insert into tick (id,name,exchange,ask,bid,time) values (#{id},#{name},#{exchange},#{ask},#{bid},#{time})")
    void insertTick(Tick tick);
}
7.3 SessionFactory配置

還要設置一下tick的SessionFactory:

@Configuration
@MapperScan(basePackages = "com.spartajet.shardingboot.mapper", sqlSessionFactoryRef = "sessionFactory")
public class TickSessionFactoryConfig {
    @Bean
    public SqlSessionFactory sessionFactory(DataSource shardingDataSource) throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(shardingDataSource);
        return sessionFactory.getObject();
    }

    @Bean
    public CommonSelfIdGenerator commonSelfIdGenerator() {
        CommonSelfIdGenerator.setClock(AbstractClock.systemClock());
        CommonSelfIdGenerator commonSelfIdGenerator = new CommonSelfIdGenerator();
        return commonSelfIdGenerator;
    }
}

這里添加了一個CommonSelfIdGenerator,sharding自帶的id生成器,看了下代碼和facebooksnowflake類似。我又不想把數據庫的主鍵設置成自增的,否則數據雙向同步會死的很慘的。

八、測試寫入
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class SpringbootShardingJdbcDemoApplicationTests {
    @Autowired
    private TickMapper tickMapper;
    @Autowired
    private CommonSelfIdGenerator commonSelfIdGenerator;
    
    
    @Test
    public void contextLoads() {
        Tick tick = new Tick(commonSelfIdGenerator.generateId().longValue(), "a", "sh", 100, 200, new Date());
        this.tickMapper.insertTick(tick);
    }

}

成功實現增量分庫分表!!!

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/71030.html

相關文章

  • java篇

    摘要:多線程編程這篇文章分析了多線程的優缺點,如何創建多線程,分享了線程安全和線程通信線程池等等一些知識。 中間件技術入門教程 中間件技術入門教程,本博客介紹了 ESB、MQ、JMS 的一些知識... SpringBoot 多數據源 SpringBoot 使用主從數據源 簡易的后臺管理權限設計 從零開始搭建自己權限管理框架 Docker 多步構建更小的 Java 鏡像 Docker Jav...

    honhon 評論0 收藏0
  • 基于 SpringBoot2.0+優雅整合 SpringBoot+Mybatis

    摘要:基于最新的,是你學習的最佳指南。驅動程序通過自動注冊,手動加載類通常是不必要。由于加上了注解,如果轉賬中途出了意外和的錢都不會改變。三的方式項目結構相比于注解的方式主要有以下幾點改變,非常容易實現。公眾號多篇文章被各大技術社區轉載。 Github 地址:https://github.com/Snailclimb/springboot-integration-examples(Sprin...

    gghyoo 評論0 收藏0
  • 寫這么多系列博客,怪不得找不到女朋友

    摘要:前提好幾周沒更新博客了,對不斷支持我博客的童鞋們說聲抱歉了。熟悉我的人都知道我寫博客的時間比較早,而且堅持的時間也比較久,一直到現在也是一直保持著更新狀態。 showImg(https://segmentfault.com/img/remote/1460000014076586?w=1920&h=1080); 前提 好幾周沒更新博客了,對不斷支持我博客的童鞋們說聲:抱歉了!。自己這段時...

    JerryWangSAP 評論0 收藏0
  • Java相關

    摘要:本文是作者自己對中線程的狀態線程間協作相關使用的理解與總結,不對之處,望指出,共勉。當中的的數目而不是已占用的位置數大于集合番一文通版集合番一文通版垃圾回收機制講得很透徹,深入淺出。 一小時搞明白自定義注解 Annotation(注解)就是 Java 提供了一種元程序中的元素關聯任何信息和著任何元數據(metadata)的途徑和方法。Annotion(注解) 是一個接口,程序可以通過...

    wangtdgoodluck 評論0 收藏0
  • Springboot應用緩存實踐之:Ehcache加持

    摘要:但本文將講述如何將緩存應用到應用中。這是的使用注解之一,除此之外常用的還有和,分別簡單介紹一下配置在方法上表示其返回值將被加入緩存。 showImg(https://segmentfault.com/img/remote/1460000016643568); 注: 本文首發于 博客 CodeSheep · 程序羊,歡迎光臨 小站!本文共 851字,閱讀大約需要 3分鐘 ! 本文內...

    luzhuqun 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<