Spring Boot多數據源切換查詢

今天遇到一個場景,公司的消息因爲過多。所以做成了分庫的情況。一個月內的數據存在當前表中。一個月之前的數據存放在備份表中。然後把主庫和備份庫做成多數據源的形式。在查詢的時候如果主庫表中沒有就去備份庫中查詢。
其實說起來好像挺高端的。但是實現上很簡單,下面是具體的實現。

數據源配置

導包,基本項目架構啥的我就不多說了。直接上配置文件。我這裏是用yml的形式:

spring:
  datasource:
    # Druid數據庫連接池
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:clickhouse://xxx:8123/test
    driverClassName: com.clickhouse.jdbc.ClickHouseDriver
    druid:
      first:  # 數據源1
        # 數據庫驅動
        driver-class-name: com.clickhouse.jdbc.ClickHouseDriver
        url: jdbc:clickhouse://xxx:8123/test
        username: default
        password: default
      second:  # 數據源2
        # 數據庫驅動
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://xxx:3306/test?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone= GMT%2B8
        username: root
        password: 123456
      third:  # 數據源3
        # 數據庫驅動
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://xxx:3306/test?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone= GMT%2B8
        username: root
        password: 123456
      fourth:  # 數據源3
        # 數據庫驅動
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://XXX:3306/test_b?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false
        username: root
        password: 123456
      initial-size: 10
      max-active: 100
      min-idle: 10
      max-wait: 60000

這裏所有關於數據庫地址和名稱我都隱藏了,要根據具體的情況配置。但是如圖所示,我們這裏配置了四個數據源。第一個是個clickhouse數據庫,二三四都是mysql。其中第三個是我說到的消息的主庫,第四個是我說的消息的歷史庫。

sql配置

    @DataSource(name = DataSourceNames.THIRD)
    Integer if_exist(Map<String, Object> params);

    @DataSource(name = DataSourceNames.FOURTH)
    Integer if_exist_archive(Map<String, Object> params);

    @DataSource(name = DataSourceNames.THIRD)
    Map<String, Object> preview(Map<String, Object> params);

    @DataSource(name = DataSourceNames.FOURTH)
    Map<String, Object> preview_archive(Map<String, Object> params);

注意看上面的代碼,第一個方法if_exist 指定的是第三個數據源,我上面說過是消息表的主庫。if_exist_archive指定的是第四個數據源,也就是消息錶的歷史庫。
同理下面的兩個查詢數據的方法一個是主庫查詢,一個是歷史庫查詢。
sql其實就是很無腦的一個判斷是否存在,一個查詢數據。

    <select id="if_exist" parameterType="map" resultType="int">
        SELECT EXISTS(SELECT 1
        FROM msg AS b
        WHERE FileName = #{filename}
        LIMIT 1)
    </select>

    <select id="if_exist_archive" parameterType="map" resultType="int">
        SELECT EXISTS(SELECT 1
        FROM msg AS b
        WHERE FileName = #{filename}
        LIMIT 1)
    </select>

    <select id="preview" parameterType="map" resultType="map">
        SELECT
            uncompress(b.Message) AS Message
        FROM msg AS b
        WHERE FileName = #{filename}
        LIMIT 1
    </select>
    
    <select id="preview_archive" parameterType="map" resultType="map">
        SELECT
        uncompress(b.Message) AS Message
        FROM msg AS b
        WHERE FileName = #{filename}
        LIMIT 1
    </select>

代碼維護切換數據庫

上面我們數據源,sql都配置好了。接下來就是代碼維護了。理論上就是主庫查不到就去歷史庫查詢,使用方法如下:

        Map<String, Object> result;

        if (msgDao.if_exist(params) > 0) {
            result = msgDao.preview(params);
        } else {
            result = msgDao.preview_archive(params);
        };

就這麼幾行代碼就實現了這個功能。

結語

其實這個功能我感覺是會則不難,難則不會。
看到了人家的做法之後恍然大悟,覺得簡單的很。可是在這之前我是沒有這種類似的想法的。甚至說之前的做法都侷限於一個數據庫,最多就是分表而已。寫起來也沒這麼簡單。兩張表需要兩個entity和Dao甚至xml。總而言之又學到了一種用法,還是挺開心的。
本篇筆記就記到這裏,如果稍微幫到你了記得點個喜歡點個關注,也祝大家工作順順利利,每天學習一點點~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章