今天遇到一個場景,公司的消息因爲過多。所以做成了分庫的情況。一個月內的數據存在當前表中。一個月之前的數據存放在備份表中。然後把主庫和備份庫做成多數據源的形式。在查詢的時候如果主庫表中沒有就去備份庫中查詢。
其實說起來好像挺高端的。但是實現上很簡單,下面是具體的實現。
數據源配置
導包,基本項目架構啥的我就不多說了。直接上配置文件。我這裏是用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。總而言之又學到了一種用法,還是挺開心的。
本篇筆記就記到這裏,如果稍微幫到你了記得點個喜歡點個關注,也祝大家工作順順利利,每天學習一點點~