AWS MySQL 讀寫分離配置指南

# AWS JDBC Wrapper讀寫分離配置實戰:Spring Boot + MyBatis Plus完整解決方案

## 前言

在微服務架構中,數據庫讀寫分離是提升系統性能的重要手段。本文將詳細介紹如何在Spring Boot項目中使用AWS JDBC Wrapper實現自動讀寫分離,重點解決MyBatis Plus框架下的配置難點,并對比Spring JPA的差異。

**核心結論**:AWS JDBC Wrapper需要連接的`readOnly`狀態來判斷路由,MyBatis Plus需要手動添加`@Transactional(readOnly = true)`,而Spring JPA會自動處理。

## 一、AWS JDBC Wrapper簡介

### 1.1 什么是AWS JDBC Wrapper

AWS JDBC Wrapper是Amazon提供的數據庫連接增強工具,支持:

- 自動故障轉移

- 讀寫分離

- 連接池管理

- 性能監控

### 1.2 讀寫分離原理

```mermaid

graph TD

A[應用程序] --> B[AWS JDBC Wrapper]

B --> C{檢查Connection.readOnly}

C -->|true| D[Aurora Reader Endpoint]

C -->|false| E[Aurora Writer Endpoint]

D --> F[只讀副本]

E --> G[主庫]

```

**關鍵機制**:AWS JDBC Wrapper通過檢測JDBC連接的`readOnly`屬性來決定路由目標。

## 二、基礎配置

### 2.1 Maven依賴

```xml

<dependency>

<groupId>software.amazon.jdbc</groupId>

<artifactId>aws-advanced-jdbc-wrapper</artifactId>

<version>2.2.0</version>

</dependency>

<dependency>

<groupId>com.baomidou</groupId>

<artifactId>mybatis-plus-boot-starter</artifactId>

<version>3.4.3</version>

</dependency>

```

### 2.2 數據源配置

```yaml

spring:

datasource:

type: com.zaxxer.hikari.HikariDataSource

driver-class-name: software.amazon.jdbc.Driver

username: ${DB_USERNAME}

password: ${DB_PASSWORD}

url: jdbc:aws-wrapper:mysql://${AURORA_CLUSTER_ENDPOINT}:3306/${DATABASE_NAME}?wrapperPlugins=readWriteSplitting,failover&characterEncoding=utf-8&wrapperLogLevel=FINEST&useSSL=true&requireSSL=true

```

**重要參數說明**:

- `wrapperPlugins=readWriteSplitting,failover`:啟用讀寫分離和故障轉移

- `wrapperLogLevel=FINEST`:啟用詳細日志,便于調試

### 2.3 日志配置

```xml

<!-- logback.xml -->

<configuration>

<!-- AWS JDBC Wrapper日志 -->

<logger name="software.amazon.jdbc" level="TRACE"/>

<logger name="software.amazon.jdbc.plugin.readwritesplitting" level="TRACE"/>

<logger name="software.amazon.jdbc.plugin.failover" level="TRACE"/>

<!-- HikariCP連接池日志 -->

<logger name="com.zaxxer.hikari" level="DEBUG"/>

</configuration>

```

## 三、核心問題:MyBatis Plus的讀寫分離挑戰

### 3.1 問題現象

**預期**:查詢操作自動路由到只讀副本

**實際**:所有操作都路由到主庫

**關鍵日志**:

```

TRACE ReadWriteSplittingPlugin - Writer connection set to 'cluster-endpoint:3306'

```

### 3.2 根本原因分析

**Spring JPA vs MyBatis Plus的差異**:

| 框架 | 事務配置 | readOnly設置 | 讀寫分離效果 |

|------|----------|--------------|-------------|

| Spring JPA | Repository方法自動添加`@Transactional(readOnly=true)` | ? 自動 | ? 有效 |

| MyBatis Plus | ServiceImpl無自動事務配置 | ? 手動 | ? 無效 |

**技術原理**:

1. AWS JDBC Wrapper依賴`Connection.setReadOnly(true)`來判斷路由

2. Spring事務管理器負責設置連接的readOnly狀態

3. 只有在`@Transactional(readOnly=true)`時,Spring才會調用`connection.setReadOnly(true)`

## 四、解決方案

### 4.1 方案一:Service層添加只讀事務(推薦)

```java

@Service

@Slf4j

public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

/**

* 查詢方法 - 走讀庫

*/

@Override

@Transactional(readOnly = true)

public List<User> list(QueryWrapper<User> queryWrapper) {

return super.list(queryWrapper);

}

/**

* 分頁查詢 - 走讀庫

*/

@Override

@Transactional(readOnly = true)

public IPage<User> page(IPage<User> page, QueryWrapper<User> queryWrapper) {

return super.page(page, queryWrapper);

}

/**

* 統計查詢 - 走讀庫

*/

@Override

@Transactional(readOnly = true)

public int count(QueryWrapper<User> queryWrapper) {

return super.count(queryWrapper);

}

/**

* 寫操作 - 走寫庫

*/

@Override

@Transactional

public boolean save(User entity) {

return super.save(entity);

}

}

```

### 4.2 方案二:Controller層添加只讀事務

```java

@RestController

@RequestMapping("/api/users")

public class UserController {

@Autowired

private IUserService userService;

/**

* 查詢接口 - 走讀庫

*/

@GetMapping("/list")

@Transactional(readOnly = true)

public Result<List<User>> getUserList() {

List<User> users = userService.list();

return Result.success(users);

}

/**

* 創建接口 - 走寫庫

*/

@PostMapping

@Transactional

public Result<Boolean> createUser(@RequestBody User user) {

boolean success = userService.save(user);

return Result.success(success);

}

}

```

### 4.3 方案三:創建專門的只讀Service

```java

@Service

@Transactional(readOnly = true) // 類級別只讀事務

public class UserReadOnlyService {

@Autowired

private UserMapper userMapper;

public List<User> queryUsers(QueryWrapper<User> queryWrapper) {

return userMapper.selectList(queryWrapper);

}

public IPage<User> queryUsersPage(IPage<User> page, QueryWrapper<User> queryWrapper) {

return userMapper.selectPage(page, queryWrapper);

}

public long queryCount(QueryWrapper<User> queryWrapper) {

return userMapper.selectCount(queryWrapper);

}

}

```

### 4.4 方案四:混合使用JDBC和MyBatis Plus

```java

@Service

public class UserHybridService {

@Autowired

private DataSource dataSource;

@Autowired

private IUserService userService;

/**

* 簡單查詢用JDBC - 走讀庫

*/

public long getUserCount() throws SQLException {

try (Connection conn = dataSource.getConnection()) {

conn.setReadOnly(true);

try (PreparedStatement stmt = conn.prepareStatement("SELECT COUNT(*) FROM user")) {

try (ResultSet rs = stmt.executeQuery()) {

return rs.next() ? rs.getLong(1) : 0;

}

}

}

}

/**

* 復雜操作用MyBatis Plus - 走寫庫

*/

@Transactional

public boolean createUserWithRelations(User user) {

return userService.save(user);

}

}

```

## 五、驗證方法

### 5.1 測試代碼

```java

@RestController

@RequestMapping("/api/test")

public class ReadWriteTestController {

@Autowired

private IUserService userService;

@Autowired

private DataSource dataSource;

/**

* 測試JDBC讀操作

*/

@GetMapping("/jdbc-read")

public String testJdbcRead() throws SQLException {

try (Connection conn = dataSource.getConnection()) {

conn.setReadOnly(true);

// 執行查詢...

return "JDBC讀測試完成";

}

}

/**

* 測試MyBatis Plus讀操作

*/

@GetMapping("/mybatis-read")

@Transactional(readOnly = true)

public String testMybatisRead() {

userService.list();

return "MyBatis Plus讀測試完成";

}

}

```

### 5.2 期望的日志輸出

**走讀庫的日志**:

```

TRACE ReadWriteSplittingPlugin - Reader connection set to 'cluster-ro-endpoint:3306'

TRACE ReadWriteSplittingPlugin - Routing read operation to reader endpoint

```

**走寫庫的日志**:

```

TRACE ReadWriteSplittingPlugin - Writer connection set to 'cluster-endpoint:3306'

TRACE ReadWriteSplittingPlugin - Routing write operation to writer endpoint

```

## 六、最佳實踐

### 6.1 設計原則

1. **查詢操作**:統一添加`@Transactional(readOnly = true)`

2. **寫操作**:使用`@Transactional`或不添加注解

3. **事務邊界**:在Service層或Controller層明確定義

4. **職責分離**:考慮創建專門的只讀Service類

### 6.2 實施優先級

**高優先級**:

- 核心業務Service(訂單、支付、用戶等)

- 高頻查詢接口

- 報表和統計功能

**中優先級**:

- 基礎數據Service

- 管理后臺查詢

- 定時任務查詢

**低優先級**:

- 低頻管理功能

- 工具類查詢

### 6.3 注意事項

1. **事務傳播**:在事務中的所有操作都會走主庫

2. **連接復用**:HikariCP可能復用連接,觀察日志時注意時間戳

3. **故障轉移**:讀庫不可用時會自動轉移到主庫

4. **復制延遲**:業務邏輯需要考慮主從復制延遲

## 七、Spring JPA對比

### 7.1 為什么Spring JPA更容易實現讀寫分離

```java

// Spring Data JPA - 自動只讀

@Repository

public interface UserRepository extends JpaRepository<User, Long> {

// 框架自動為查詢方法添加 @Transactional(readOnly = true)

List<User> findByStatus(String status); // 自動走讀庫

// 框架自動為寫方法添加 @Transactional

User save(User user); // 自動走寫庫

}

```

### 7.2 JPA vs MyBatis Plus總結

| 特性 | Spring JPA | MyBatis Plus |

|------|------------|--------------|

| 學習曲線 | 簡單,開箱即用 | 需要理解事務配置 |

| 自動化程度 | 高度自動化 | 需要手動配置 |

| 性能控制 | 抽象層較厚 | 更接近原生SQL |

| 讀寫分離 | 自動支持 | 需要手動實現 |

| SQL優化 | 相對困難 | 靈活度高 |

## 八、故障排查

### 8.1 常見問題

**問題1:看不到ReadWriteSplittingPlugin日志**

- 檢查URL中的`wrapperLogLevel=FINEST`

- 確認logback.xml中的日志級別

- 重啟應用重新觀察

**問題2:所有操作都連接同一endpoint**

- 檢查`@Transactional(readOnly = true)`是否正確添加

- 確認Aurora集群是否有只讀副本

- 驗證URL中的`wrapperPlugins`參數

**問題3:連接失敗**

- 檢查SSL證書配置

- 驗證網絡連通性

- 確認Aurora集群狀態

### 8.2 調試技巧

1. **啟用詳細日志**:

```yaml

logging:

level:

software.amazon.jdbc: TRACE

com.zaxxer.hikari: DEBUG

```

2. **診斷連接狀態**:

```java

@GetMapping("/diagnose")

public Map<String, Object> diagnoseDatasource() {

try (Connection conn = dataSource.getConnection()) {

DatabaseMetaData metaData = conn.getMetaData();

Map<String, Object> info = new HashMap<>();

info.put("driverName", metaData.getDriverName());

info.put("url", metaData.getURL());

info.put("isAwsWrapper", metaData.getDriverName().contains("Amazon"));

return info;

}

}

```

## 九、總結

AWS JDBC Wrapper是一個強大的數據庫連接工具,但在MyBatis Plus環境下需要正確配置事務注解才能實現讀寫分離。核心要點:

1. **理解原理**:讀寫分離依賴`Connection.setReadOnly()`狀態

2. **正確配置**:為查詢方法添加`@Transactional(readOnly = true)`

3. **驗證效果**:通過日志確認路由行為

4. **漸進實施**:按優先級逐步改造現有代碼

通過本文的配置方案,可以有效提升系統的數據庫讀性能,減輕主庫壓力,為系統的高可用和高性能打下堅實基礎。

---

> **作者經驗**:在實際項目中,建議先在測試環境驗證配置,觀察日志確認讀寫分離生效后,再逐步推廣到生產環境。同時要注意監控Aurora集群的讀寫負載分布,確保達到預期的性能提升效果。

**技術棧**:Spring Boot 2.x + MyBatis Plus 3.4.x + AWS JDBC Wrapper 2.2.x + Aurora MySQL

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/87153.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/87153.shtml
英文地址,請注明出處:http://en.pswp.cn/web/87153.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

opencv檢測運動物體

檢測到的所有移動物體中輪廓中找到面積最大的輪廓&#xff0c;并繪制這個輪廓的矩形框。 #include <opencv2/opencv.hpp> #include <iostream>int main() {// 打開視頻文件或攝像頭cv::VideoCapture capture;capture.open("move3.mp4"); // 打開視頻文件…

Camera相機人臉識別系列專題分析之十五:人臉特征檢測FFD算法之libcvface_api.so算法API詳細注釋解析

【關注我,后續持續新增專題博文,謝謝!!!】 上一篇我們講了: 這一篇我們開始講: Camera相機人臉識別系列專題分析之十五:人臉特征檢測FFD算法之libcvface_api.so算法API詳細注釋解析 目錄 一、libcvface_api.so算法API詳細注釋解析

圖像擦除論文-2:SmartEraser、Erase Diffusion、OmniEraser

圖像生成模型應用系列——圖像擦除&#xff1a; 圖像擦除論文-1&#xff1a;PixelHacker、PowerPanint等 圖像擦除論文-2&#xff1a;擦除類型數據集構建(1) Erase Diffusion Erase Diffusion: Empowering Object Removal Through Calibrating Diffusion Pathways https://git…

九識無人車陜西運營中心展廳啟幕 打造智能城配物流新標桿

7月1日&#xff0c;九識無人車陜西運營中心展廳正式開業&#xff0c;全國業務版圖再添重要一子。這座展廳是九識在陜西省的首家展廳&#xff0c;由九識第一位正式提車的客戶、首位代理商伙伴孫朋奇先生打造。展廳集產品展示與技術體驗于一體&#xff0c;成為西北地區城配領域自…

AI智能體|扣子(Coze)搭建【沉浸式歷史故事解說視頻】工作流

主包講解歷史對我們的好處&#xff0c;純個人觀點&#xff01; 這個世界是存在一些規律的&#xff0c;很多東西并不能夠通過自己的聰明去創新&#xff0c;去改變的。 無論你怎么樣創新&#xff0c;你都會回到哪個規律中去&#xff0c;比如很多人做一些商業模式的創新&#xff0…

Softhub軟件下載站實戰開發(十):實現圖片視頻上傳下載接口

文章目錄 Softhub軟件下載站實戰開發&#xff08;十&#xff09;&#xff1a;實現圖片視頻上傳下載接口 &#x1f5bc;?&#x1f3a5;系統架構圖核心功能設計 &#x1f6e0;?1. 文件上傳流程2. 關鍵技術實現2.1 雪花算法2.2 文件校驗機制 ?2.3 文件去重機制 &#x1f50d;2.…

[JS逆向] 喜馬拉雅登錄案例 -- 補環境

博客配套代碼發布于github&#xff1a;喜馬拉雅登錄 &#xff08;歡迎順手Star一下?&#xff09; 相關知識點&#xff1a;webpack 補環境 相關爬蟲專欄&#xff1a;JS逆向爬蟲實戰 爬蟲知識點合集 爬蟲實戰案例 逆向知識點合集 此案例目標為逆向成功對應的參數&#xff0c…

大語言模型推理系統綜述

摘要 近年來&#xff0c;隨著 ChatGPT 等服務推動大語言模型&#xff08;LLM&#xff09;的快速普及&#xff0c;一批專門面向 LLM 推理的系統相繼涌現&#xff0c;如 vLLM、SGLang、Mooncake 和 DeepFlow。這些系統設計工作的核心動因是 LLM 請求處理過程中所特有的自回歸特性…

用Firecrawl輕松獲取網站數據,提升AI應用的效率!

&#x1f525; Firecrawl&#xff1a;助力AI應用的強大工具&#xff01; 在數字化信息爆炸的時代&#xff0c;如何高效地從海量網頁中提取有用數據變得尤其重要。Firecrawl的問世&#xff0c;為我們揭開了一種便捷的方法來應對這一挑戰。它不僅能夠將整個網站的數據轉化為適用…

【王陽明代數講義】谷歌編程智能體Gemini CLI 使用指南、架構詳解與核心框架分析

Gemini CLI 使用指南、架構詳解與核心框架分析 Gemini CLI 使用指南、架構詳解與核心框架分析Gemini CLI 使用指南Gemini CLI 架構詳解Gemini CLI 核心框架總結 Gemini CLI 使用指南、架構詳解與核心框架分析 Gemini CLI 使用指南 1. 安裝與配置 環境要求&#xff1a; Node.…

camera調試:安卓添加xml注冊

對接安卓的平臺時&#xff0c;需要注冊對應的camera設備&#xff0c;供安卓標準api進行操作&#xff0c;rk的平臺需要在HAL層配置camera3_profiles.xml文件&#xff0c;適配驅動的信息&#xff0c;進行注冊camera設備。該xml對應的內容很多&#xff0c;很多CTS測試問題都是該文…

使用 Ansys Discovery 為初學者準備幾何結構

介紹 設計幾何體通常會包含一些特征&#xff0c;使其無法直接導入我們的仿真工具&#xff0c;例如 Ansys Mechanical、LS-DYNA、Fluent 等。有些干擾或錯位雖然適合制造&#xff0c;但在我們的仿真工具中卻會造成問題。有時&#xff0c;一些小特征&#xff08;例如孔或圓角&am…

推客系統全棧開發指南:從架構設計到商業化落地

一、推客系統概述 推客系統&#xff08;TuiKe System&#xff09;是一種結合社交網絡與內容分發的創新型平臺&#xff0c;旨在通過用戶間的相互推薦機制實現內容的高效傳播。這類系統通常包含用戶關系管理、內容發布、智能推薦、數據分析等核心模塊&#xff0c;廣泛應用于電商…

大數據開發實戰:如何做企業級的數據服務產品

1.背景 數據服務通常以解決方案的形式進行組織&#xff0c;面向一個應用場景的所有數據需求或數據內容可以通過一個解決方案進行封裝&#xff0c;統一對外服務。一個數據需求或數據接口以一個數據服務實例的形式存在于解決方案之下。 下游消費方可以通過統一API進行數據消費&…

基于IndexTTS的零樣本語音合成

IndexTTS 項目采用模塊化設計&#xff0c;將 BPE 文本編碼、GPT 單元預測、dVAE 語音特征抽取和 BigVGAN 音頻生成串聯為完整的語音合成流程。系統通過統一的配置文件和模型目錄規范&#xff0c;實現高效的文本到語音轉換&#xff0c;支持命令行與 Web 界面雙模式操作&#xff…

基于go-zero的短鏈生成系統

go-zero框架 gozero&#xff08;又稱go-zero&#xff09;是一款由知名開發者kevwan設計的Golang微服務框架&#xff0c;專注于高性能、低延遲和易用性。其核心目標是簡化分布式系統的開發&#xff0c;提供開箱即用的工具鏈&#xff0c;涵蓋API網關、RPC服務、緩存管理、數據庫…

Linux-修改線上MariaDB服務端口號

準備工作&#xff08;很重要&#xff01;&#xff01;&#xff01;&#xff09;&#xff1a; 提前做好Linux服務器快照 提前做好數據庫數據備份 1. 修改配置文件 首先&#xff0c;我們需要找到MariaDB的配置文件。通常情況下&#xff0c;這個文件位于以下位置&#xff1a;…

Spring Cloud 微服務(負載均衡策略深度解析)

&#x1f4cc; 摘要 在微服務架構中&#xff0c;負載均衡是實現高可用、高性能服務調用的關鍵機制之一。Spring Cloud 提供了基于客戶端的負載均衡組件 Ribbon&#xff0c;結合 Feign 和 OpenFeign&#xff0c;實現了服務間的智能路由與流量分配。 本文將深入講解 Spring Clo…

HTML/CSS基礎

1.html:超文本標記語言。它是一種標識性的語言&#xff0c;非編程語言&#xff0c;不能使用邏輯運算。通過標簽將網絡上的文本格式進行統一&#xff0c;使用分散網絡資源鏈接為一個邏輯整體&#xff0c;屬于標記語言。 超文本&#xff1a;就是指頁面內可以包含圖片&#xff0…

C# 事件驅動編程的核心:深度解析發布者_訂閱者模式

適用場景&#xff1a;GUI交互、消息隊列、微服務通信等需要解耦事件生產與消費的系統 &#x1f9e9; 模式核心組件解析 發布者&#xff08;Publisher&#xff09; 作用&#xff1a;定義事件并管理訂閱者列表關鍵行為&#xff1a; 提供和-運算符注冊/注銷訂閱者通過Invoke()方…