搭建基於springboot輕量級讀寫分離開發框架
阿新 • • 發佈:2021-02-08
#何為讀寫分離
讀寫分離是指對資源的修改和讀取進行分離,能解決很多資料庫瓶頸,以及程式碼混亂難以維護等相關的問題,使系統有更好的擴充套件性,維護性和可用性。
一般會分三個步驟來實現:
一. 主從資料庫搭建
資訊管理系統的絕大部分瓶頸在資料庫,通過搭建主從資料庫,寫到主資料庫,讀取從資料庫,提高資料庫的吞吐量,根據業務需求可以搭建一主一從、一主多從的資料庫同步架構。如果報表多的系統,可以搭個一主多從架構,一個從資料庫供普通查詢,另一個從資料庫供報表查詢,這樣能夠避免報表的複雜查詢影響客戶正常操作。
二. 讀寫程式碼分離
程式碼上對讀寫進行分離。讀的邏輯相對簡單,幾乎不需要做過多的分層封裝。大部分業務邏輯在寫操作,所以我們需要專注於對寫程式碼的分層、抽象封裝。注意: 在寫模組涉及到業務資料讀取,幾乎要實時的,而且基於高內聚的原則,應該封裝進寫程式碼類中,讀取主資料庫。
三. 程序分離
將讀和寫的程式碼封裝到不同的程序,從程序級別避免相互影響,其實就是分散式。實現從程序上解耦,程式執行期間的效能、異常錯誤不會相互影響,所以系統有相對高的可用性。
這裡多說一句, 如果對寫業務按領域拆分到不同的程序,會涉及到分散式事務,在未涉及到高併發、大資料的系統,其實沒必要從程序上拆分,分散式對事務不友好,為了處理分散式事務,你需要付出更多的時間和金錢成本。考慮程序拆分,一定要基於實際業務需求再三權衡利弊。很多時候,也許你只需要多一個從資料庫、一個快取、多一臺伺服器、多幾G記憶體、多幾核cpu、優化一下sql 即可解決很多效能上的問題。
#如何搭建
現在我們搭建一主一從資料庫架構, 並且實現從程式碼上進行讀寫分離的開發框架,但不涉及程序分離。
## 1. 搭建主從資料庫
mariadb 可參考[搭建 mariadb 資料庫主從同步](https://www.cnblogs.com/grissom007/p/14368831.html) 或者 [https://mariadb.com/kb/en/setting-up-replication/](https://mariadb.com/kb/en/setting-up-replication/) 。
## 2. 基於springboot 搭建開發框架
### 2.1 專案結構
畫一下框架的模組結構
![](https://img2020.cnblogs.com/blog/488490/202102/488490-20210208155507407-1040650420.png)
1. api 模組相當於 gateway, 接收和響應請求,還包括鑑權, 引數的校驗和組裝,呼叫 command, query 的介面。
2. common 模組封裝一些和業務無關的通用功能類。
3. query 是讀模組,封裝非實時的查詢介面,查詢"從資料庫"。
4. command 是寫模組,封裝領域的業務邏輯,操作"主資料庫"。
按照上圖,用 idea 建立專案結構如下
![](https://img2020.cnblogs.com/blog/488490/202102/488490-20210208155543404-1252942376.png)
對 command 和 query 模組再進行細化
![](https://img2020.cnblogs.com/blog/488490/202102/488490-20210208155620201-1986039308.png)
因為 command 模組我們使用領域驅動開發,所以拆分成服務(Service), 倉儲(Repository), ORM, 聚合根(Aggregate)。
Query 只是簡單的查詢,我們直接用 Dao 訪問資料庫,然後把資料轉成 DTO 返回。
根據上圖,再細化專案的文件結構
![](https://img2020.cnblogs.com/blog/488490/202102/488490-20210208161622202-386373869.png)
### 2.2 配置檔案
假設我們有三個環境, 分別是開發(dev), 測試(uat), 生產(prod)。每個模組都有單獨的配置檔案。
api:
application-api-dev.yml
application-api-uat.yml
application-api-prod.yml
command:
application-command-dev.yml
application-command-uat.yml
application-command-prod.yml
query:
application-query-dev.yml
application-query-uat.yml
application-query-prod.yml
在系統啟動時,指定使用的環境, api 作為啟動專案,新增 bootstrap.yml, 因為 bootstrap.yml 優先於 application.yml 生效,所以可以在 bootstrap.yml 配置啟動環境。
我們啟用 dev 環境, bootstrap.yml 內容如下:
```yml
spring:
profiles:
active: common-dev,command-dev,query-dev,api-dev
```
那麼,對應的 application-common-dev.yml, application-command-dev.yml, application-query-dev.yml, application-api-dev.yml 配置檔案將起效。
### 2.3 執行
在 query 專案新增一個介面
```java
public interface UserQueryService {
String getName(Long id);
}
```
並實現它
```java
@Service
public class UserQueryServiceImpl implements UserQueryService {
@Override
public String getName(Long id) {
return "my name is grissom" + id;
}
}
```
在 api 中呼叫該介面
```java
@RestController
@RequestMapping("user")
public class UserController {
private final UserQueryService userQueryService;
public UserController(UserQueryService userQueryService) {
this.userQueryService = userQueryService;
}
@GetMapping("/name/{id}")
public String name(@PathVariable("id") Long id) {
return this.userQueryService.getName(id);
}
}
```
將 api 作為啟動項,配置 application-api-dev.yml, 開放 8003 埠
```yml
server:
port: 8003
```
用 postman 請求
![](https://img2020.cnblogs.com/blog/488490/202102/488490-20210208161710012-274639215.png)
至此,咱們的專案結構已經搭建好。
下一篇再寫如何訪問資料庫。
# 原始碼
[https://github.com/grissomlau/cqrs-springboot](https://github.com/grissomlau/cqrs-springboot)