1. 程式人生 > >微服務架構springboot讀寫分離這麼難寫麼?我就覺得很簡單

微服務架構springboot讀寫分離這麼難寫麼?我就覺得很簡單

最近在學習Spring boot,寫了個讀寫分離。並未照搬網文,而是獨立思考後的成果,寫完以後發現從零開始寫讀寫分離並不難!

我最初的想法是: 讀方法走讀庫,寫方法走寫庫(一般是主庫),保證在Spring提交事務之前確定資料來源.

保證在Spring提交事務之前確定資料來源,這個簡單,利用AOP寫個切換資料來源的切面,讓他的優先順序高於Spring事務切面的優先順序。至於讀,寫方法的區分可以用2個註解。

但是如何切換資料庫呢? 我完全不知道!多年經驗告訴我

我搜索了一些網文,發現都提到了一個AbstractRoutingDataSource類。檢視原始碼註釋如下

/**

Abstract {@link javax.sql.DataSource} implementation that routes {@link #getConnection()}

* calls to one of various target DataSources based on a lookup key. The latter is usually

* (but not necessarily) determined through some thread-bound transaction context.

*

* @author Juergen Hoeller

* @since 2.0.1

* @see #setTargetDataSources

* @see #setDefaultTargetDataSource

* @see #determineCurrentLookupKey()

*/

AbstractRoutingDataSource就是DataSource的抽象,基於lookup key的方式在多個數據庫中進行切換。重點關注setTargetDataSources,setDefaultTargetDataSource,determineCurrentLookupKey三個方法。那麼AbstractRoutingDataSource就是Spring讀寫分離的關鍵了。

仔細閱讀了三個方法,基本上跟方法名的意思一致。setTargetDataSources設定備選的資料來源集合。 setDefaultTargetDataSource設定預設資料來源,determineCurrentLookupKey決定當前資料來源的對應的key。

但是我很好奇這3個方法都沒有包含切換資料庫的邏輯啊!我仔細閱讀原始碼發現一個方法,determineTargetDataSource方法,其實它才是獲取資料來源的實現。原始碼如下:

簡單說就是,根據determineCurrentLookupKey獲取的key,在resolvedDataSources這個Map中查詢對應的datasource!,注意determineTargetDataSource方法竟然不使用的targetDataSources!

那一定存在resolvedDataSources與targetDataSources的對應關係。我接著翻閱程式碼,發現一個afterPropertiesSet方法(Spring原始碼中InitializingBean介面中的方法),這個方法將targetDataSources的值賦予了resolvedDataSources。原始碼如下:

afterPropertiesSet 方法,熟悉Spring的都知道,它在bean例項已經建立好,且屬性值和依賴的其他bean例項都已經注入以後執行。

也就是說呼叫,targetDataSources,defaultTargetDataSource的賦值一定要在afterPropertiesSet前邊執行。

AbstractRoutingDataSource簡單總結:

  1. AbstractRoutingDataSource,內部有一個Map<Object,DataSource>的域resolvedDataSources

  2. determineTargetDataSource方法通過determineCurrentLookupKey方法獲得key,進而從map中取得對應的DataSource。

  3. setTargetDataSources 設定 targetDataSources

  4. setDefaultTargetDataSource 設定 defaultTargetDataSource,

  5. targetDataSources和defaultTargetDataSource 在afterPropertiesSet分別轉換為resolvedDataSources和resolvedDefaultDataSource。

  6. targetDataSources,defaultTargetDataSource的賦值一定要在afterPropertiesSet前邊執行。

進一步瞭解理論後,讀寫分離的方式則基本上出現在眼前了。(“下列方法不唯一”)

先寫一個類繼承AbstractRoutingDataSource,實現determineCurrentLookupKey方法,和afterPropertiesSet方法。afterPropertiesSet方法中呼叫setDefaultTargetDataSource和setTargetDataSources方法之後呼叫super.afterPropertiesSet。

之後定義一個切面在事務切面之前執行,確定真實資料來源對應的key。但是這又出現了一個問題,如何執行緒安全的情況下傳遞每個執行緒獨立的key呢?沒錯使用ThreadLocal傳遞真實資料來源對應的key

ThreadLocal,Thread的區域性變數,確保每一個執行緒都維護變數的一個副本

到這裡基本邏輯就想通了,之後就是寫了。

DataSourceContextHolder 使用ThreadLocal儲存真實資料來源對應的key

DataSourceAopAspect 切面切換真實資料來源對應的key,並設定優先順序保證高於事務切面

RoutingDataSouceImpl實現AbstractRoutingDataSource的邏輯

基本邏輯實現完畢了就進行,通用設定,設定資料來源,事務,SqlSessionFactory等

其他程式碼,就不在這裡贅述了,有興趣可以移步完整程式碼。

使用Spring寫讀寫分離,其核心就是AbstractRoutingDataSource,原始碼不難,讀懂之後,寫個讀寫分離就簡單了!。

AbstractRoutingDataSource重點回顧:

  1. AbstractRoutingDataSource,內部有一個Map<Object,DataSource>的域resolvedDataSources

  2. determineTargetDataSource方法通過determineCurrentLookupKey方法獲得key,進而從map中取得對應的DataSource。

  3. setTargetDataSources 設定 targetDataSources

  4. setDefaultTargetDataSource 設定 defaultTargetDataSource,

  5. targetDataSources和defaultTargetDataSource 在afterPropertiesSet分別轉換為resolvedDataSources和resolvedDefaultDataSource。

  6. targetDataSources,defaultTargetDataSource的賦值一定要在afterPropertiesSet前邊執行。

這周確實有點忙,週五花費了些時間不過總算實現了自己的諾言。

完成承諾不容易,喜歡您就點個贊!

推薦一個交流學習群:575745314 裡面會分享一些資深架構師錄製的視訊錄影:有Spring,MyBatis,Netty原始碼分析,高併發、高效能、分散式、微服務架構的原理,JVM效能優化這些成為架構師必備的知識體系。還能領取免費的學習資源,目前受益良多:

相關推薦

服務架構springboot分離這麼覺得簡單

最近在學習Spring boot,寫了個讀寫分離。並未照搬網文,而是獨立思考後的成果,寫完以後發現從零開始寫讀寫分離並不難!我最初的想法是: 讀方法走讀庫,寫方法走寫庫(一般是主庫),保證在Spring提交事務之前確定資料來源.保證在Spring提交事務之前確定資料來源,這個

1124——使用Springboot和Vue開發的CRM系統,真正前後端分離服務架構,BAT網際網路公司主流技術的集大成者

使用Springboot和Vue開發的CRM系統,真正前後端分離的微服務架構,BAT網際網路公司主流技術的集大成者 2017年07月18日 22:16:54 李國才 閱讀數:37532 標籤: 微服務 更多 個人分類: java mysql 前後端分離 i18n springboot 微服

百度服務架構師隨手筆記:教你如何手Docker

names lar 朋友 -i oot 封裝 路由 必須 spa 模擬Docker實現一個簡單的容器,不到 200行代碼(包括空行、註釋、異常處理),這並不是吹牛B。容器技術幾乎是Linux kernel內置的模塊,我們簡單調用一下API就能搞定很多事情。當然你要考慮各種商

一文懂Spring Boot、服務架構和大數據治理之間的故事

Springboot微服務架構 微服務的誕生並非偶然,它是在互聯網高速發展,技術日新月異的變化以及傳統架構無法適應快速變化等多重因素的推動下誕生的產物。互聯網時代的產品通常有兩類特點:需求變化快和用戶群體龐大,在這種情況下,如何從系統架構的角度出發,構建靈活、易擴展的系統,快速應對需求的變化;同時,隨著用戶的

大型電商基於Springboot+Springcloud服務+Dubbo分散式,JVM虛擬機器,併發原理程式設計,實現服務架構

大型電商基於Springboot+Springcloud微服務+Dubbo分散式,JVM虛擬機器,併發原理程式設計,實現微服務架構39套Java架構師,高併發,高效能,高可用,分散式,叢集,電商,快取,微服務,微信支付寶支付,公眾號開發,java8新特性,P2P金融專案,程式設計,功能設計,資料庫設

Java分散式網際網路架構/服務/高效能/springboot/springcloud 2018年10月17日直播內容

2018年10月17日直播內容 大規模併發必備的訊息中介軟體技術ActiveMq 網盤連結: https://pan.baidu.com/s/1GlxsZ2JnrvX- YN16-S7lQw 提取碼: xrtv 更多課程線上免費觀看↓↓↓↓↓↓https://ke.qq.com/course/17944

Java分散式網際網路架構/服務/高效能/springboot/springcloud2018年10月16日直播內容

2018年10月16日直播內容 架構師揭祕springboot對springmvc的自動配置原理 直播地址:https://ke.qq.com/course/179440?tuin=9b386640 工作日14:00-15:00,     20:00-21:00 連結: https

SpringBoot SpringCloud運用Euraka服務架構(聚合分散式架構)Euraka釋出與消費

SpringBoot SpringCloud運用Euraka微服務架構 首先說到SpringBooot專案架構,首選jdk1.8以上,當然啊,jdk1.7也不是不可以; 我們本次要做的是建立父工程(pom),和多個子工程(pojo,common,server,web等),一箇中間件E

基於SpringBoot和SpringCloud實現服務架構

Spring 頂級框架 spring IO platform 用於系統部署,是可整合的,構建現代化應用的版本平臺,具體來說當你使用maven dependency引入spring jar包時它就在工作了。 Spring Boot 旨在簡化建立產品級的 Spring 應

服務架構實戰》讀書筆記三---SpringBoot

《微服務架構實戰》讀書筆記三—SpringBoot springboot是什麼? springboot是為了簡化spring的開發過程,通過少量程式碼就能建立一個獨立的,產品級spring應用 springboot的核心思想是約定大於配置,基本不需要寫配置檔案,

一文懂 Spring Boot、服務架構和大資料治理三者之間的故事

微服務架構 微服務的誕生並非偶然,它是在網際網路高速發展,技術日新月異的變化以及傳統架構無法適應快速變化等多重因素的推動下誕生的產物。網際網路時代的產品通常有兩類特點:需求變化快和使用者群體龐大,在這種情況下,如何從系統架構的角度出發,構建靈活、易擴充套件的系統,快速應對需求的變化;同時,隨著使用者的增加,如

基於SpringBoot服務架構實踐

引言 微服務是近期火爆IT業界的新概念,在某種意義上這算是一個全新架構,微服務繼承了面向服務架構(SOA)的整體思路,強調將巨石型應用或服務拆分為由微小的服務應用。按照通常理解和定義,微服務是指開發一個單個小型的但有業務功能的服務,每個服務都有自己的處

Java程式設計服務架構框架-監控與管理(SpringBoot

       在微服務架構中,我們將原本龐大的單體系統拆分成多個提供不同服務的應用。 雖然 各個應用的內部邏輯因分解而得以簡化,但是由於部署應用的數量成倍增長,使得系統的 維護複雜度大大提升。 對於運維人員來說,隨著應用的不斷增多,系統叢集中出現故障的 頻率也變得越來 越高,

使用Redis為註冊中心的Dubbo服務架構(基於SpringBoot

title: 使用Redis為註冊中心的Dubbo微服務架構(基於SpringBoot) date: 2019-07-30 14:06:29 categories: 架構 author: mrzhou tags: SpringBoot redis Dubbo 微服務 RPC 前言 Dubbo作為一款高效

一文懂Spring Boot、服務架構和大資料治理之間的故事

微服務架構 微服務的誕生並非偶然,它是在網際網路高速發展,技術日新月異的變化以及傳統架構無法適應快速變化等多重因素的推動下誕生的產

一文服務架構的重構策略 | 內含福利

  你很有可能正在處理大型複雜的單體應用程式,每天開發和部署應用程式的經歷都很緩慢而且很痛苦。微服務看起來非常適

服務架構學習Day01-SpringBoot入門

# 基本概念 - **SpringBoot的優點:** - 可以建立獨立的**Spring**應用 - **SpringBoot**嵌入**Tomcat,Jetty**和**Unsertow,** 不需要部署**war**檔案 - 根據需要通過**maven**獲取**starter**

服務架構Day02-SpringBoot日誌slf4j

# 日誌框架 |日誌門面(介面,日誌抽象層 )|日誌實現| |--|--| |JCL(Jakarta Commons Logging)、slf4j(Simple Logging Facade for Java)、jboss-logging|log4j、JUL(java.util.logging)、log4j2

服務架構Day04-SpringBoot之web開發

# 引入專案 - 把**html**頁面放在模板引擎資料夾**templates**下,這樣能使用模板引擎的功能。 # 登入頁面國際化 - **國際化**:編寫國際化配置檔案 1.編寫國際化配置檔案,抽取頁面需要顯示的國際化訊息 2.SpringBoot自動配置好了管理國際化資原始檔的元件 ```java

服務架構與實踐及雲原生等相關概念

定時 服務器端 body 內容 開放封閉原則 logs 方法 服務架構 binding 微服務架構與實踐 筆記:《微服務架構與實踐》 王磊 著 一 單塊架構   1 定義:對於這種功能集中、代碼和數據中心化、一個發布包、部署後運行在同一進程的應用程序,我們通常稱之為單塊架構