亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JSP > 正文

Spring AOP切面解決數據庫讀寫分離實例詳解

2020-07-27 21:22:48
字體:
來源:轉載
供稿:網友

Spring AOP切面解決數據庫讀寫分離實例詳解

為了減輕數據庫的壓力,一般會使用數據庫主從(master/slave)的方式,但是這種方式會給應用程序帶來一定的麻煩,比如說,應用程序如何做到把數據寫到master庫,而讀取數據的時候,從slave庫讀取。如果應用程序判斷失誤,把數據寫入到slave庫,會給系統造成致命的打擊。

解決讀寫分離的方案很多,常用的有SQL解析、動態設置數據源。SQL解析主要是通過分析sql語句是insert/select/update/delete中的哪一種,從而對應選擇主從。而動態設置數據源,則是通過攔截方法名稱的方式來決定主從的,例如:save*(),insert*() 形式的方法使用master庫,select()開頭的,使用slave庫。蠻多公司會使用在方法上標上自定義的@Master、@Slave之類的標簽來選擇主從,也有公司直接就調用setxxMaster,setxxSlave之類的代碼進行主從選擇。

下面我主要介紹一下基于Spring AOP動態設置數據源這種方式。注意這篇文章是基于自己項目的實際情況的,不是通用的方案,請知曉。

原理圖


 

Spring AOP的切面主要的職責是攔截Mybatis的Mapper接口,通過判斷Mapper接口中的方法名稱來決定主從。

 Spring AOP 切面配置

<aop:config expose-proxy="true">  <aop:pointcut id="txPointcut" expression="execution(* com.test..persistence..*.*(..))" />  <aop:aspect ref="readWriteInterceptor" order="1">  <aop:around pointcut-ref="txPointcut" method="readOrWriteDB"/>  </aop:aspect>  </aop:config>     <bean id="readWriteInterceptor" class="com.test.ReadWriteInterceptor">    <property name="readMethodList">     <list>      <value>query*</value>      <value>use*</value>      <value>get*</value>      <value>count*</value>      <value>find*</value>      <value>list*</value>      <value>search*</value>    </list>   </property>  <property name="writeMethodList">    <list>      <value>save*</value>      <value>add*</value>      <value>create*</value>      <value>insert*</value>      <value>update*</value>      <value>merge*</value>      <value>del*</value>      <value>remove*</value>      <value>put*</value>      <value>write*</value>    </list>  </property>  </bean> 

把所有Mybatis接口類都放置在persistence下。配置的切面類是ReadWriteInterceptor。這樣當Mapper接口的方法被調用時,會先調用這個切面類的readOrWriteDB方法。在這里需要注意<aop:aspect>中的order="1" 配置,主要是為了解決切面于切面之間的優先級問題,因為整個系統中不太可能只有一個切面類。

Spring AOP 切面類實現

public class ReadWriteInterceptor {   private static final String DB_SERVICE = "dbService";   private List<String> readMethodList = new ArrayList<String>();   private List<String> writeMethodList = new ArrayList<String>(); 
  public Object readOrWriteDB(ProceedingJoinPoint pjp) throws Throwable {     String methodName = pjp.getSignature().getName();     if (isChooseReadDB(methodName)) {       //選擇slave數據源     } else if (isChooseWriteDB(methodName)) {       //選擇master數據源     } else {      //選擇master數據源     }     return pjp.proceed(); }   private boolean isChooseWriteDB(String methodName) {    for (String mappedName : this.writeMethodList) {      if (isMatch(methodName, mappedName)) {        return true;      }    }   return false; }   private boolean isChooseReadDB(String methodName) {   for (String mappedName : this.readMethodList) {     if (isMatch(methodName, mappedName)) {       return true;     }   }   return false; }   private boolean isMatch(String methodName, String mappedName) {   return PatternMatchUtils.simpleMatch(mappedName, methodName); }   public List<String> getReadMethodList() {   return readMethodList;  }   public void setReadMethodList(List<String> readMethodList) {   this.readMethodList = readMethodList; }   public List<String> getWriteMethodList() {   return writeMethodList;  }   public void setWriteMethodList(List<String> writeMethodList) {   this.writeMethodList = writeMethodList; }  

覆蓋DynamicDataSource類中的getConnection方法

ReadWriteInterceptor中的readOrWriteDB方法只是決定選擇主還是從,我們還必須覆蓋數據源的getConnection方法,以便獲取正確的connection。一般來說,是一主多從,即一個master庫,多個slave庫的,所以還得解決多個slave庫之間負載均衡、故障轉移以及失敗重連接等問題。

1、負載均衡問題,slave不多,系統并發讀不高的話,直接使用隨機數訪問也是可以的。就是根據slave的臺數,然后產生隨機數,隨機的訪問slave。

2、故障轉移,如果發現connection獲取不到了,則把它從slave列表中移除,等其回復后,再加入到slave列表中

3、失敗重連,第一次連接失敗后,可以多嘗試幾次,如嘗試10次。

處理業務方法中的@Transactional注解

我參與的這個項目,大部分業務代碼是不需要事務的,只有極個別情況需要。那么按照上面提到的方案,如果不對業務方法中@Transactional注解進行特殊處理的話,主從的選擇會出現問題。大家都知道,如果使用了Spring的事務,那么在同一個業務方法內,只會調用一次數據源的getConnection方法,如果該業務方法內,調用的mapper接口剛好以select開頭的,就會選擇slave庫,那么接下來調用以insert開頭的mapper接口方法時,會把數據寫入到slave庫。如何解決這個問題呢?必須在進入標有@Transactional注解的業務方法前,指定選擇master主庫??梢酝ㄟ^覆蓋DataSourceTransactionManager類中的doBegin方法,如下:

public class MyTransactionManager extendsDataSourceTransactionManager{  @Override  protected void doBegin(Object transaction, TransactionDefinitiondefinition) {  //選擇master數據庫  super.doBegin(transaction, definition);  }  } 

這樣既可以避免,把數據寫入到從庫的問題。

總結

本人的解決方案是基于項目實際的,不一定合適你,我只是展示了解決方案而已。當然你可以選擇開源的框架,像阿里的Cobar,360的Atlas。

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲性视频网址| 午夜精品99久久免费| 亚洲美女精品成人在线视频| 91美女片黄在线观| 亚洲性线免费观看视频成熟| 国产美女久久精品香蕉69| 亚洲女人天堂色在线7777| 亚洲女人天堂成人av在线| 欧美一级视频在线观看| 亚洲一区二区福利| 91wwwcom在线观看| 国产成人福利夜色影视| 久久久久日韩精品久久久男男| 色先锋资源久久综合5566| 国产成人啪精品视频免费网| 亚洲美女视频网站| 青青草99啪国产免费| 国产成人精品999| 精品国产一区二区三区久久| 国产精品久久久久久久9999| 欧美乱妇40p| 日韩高清欧美高清| 97精品久久久中文字幕免费| 国产一区红桃视频| 亚洲片在线观看| 国产精品精品久久久久久| 亚洲国产欧美一区二区三区同亚洲| 在线观看日韩av| 一区二区日韩精品| 欧美在线不卡区| 秋霞午夜一区二区| 国产成人一区二区三区小说| 日韩免费在线免费观看| 2025国产精品视频| 国产精品一区二区久久| 91极品女神在线| 色综合天天狠天天透天天伊人| 欧美日韩午夜剧场| 一本色道久久综合狠狠躁篇的优点| 久久国产精品久久久| 日韩欧美极品在线观看| 亚洲综合成人婷婷小说| 亚洲激情视频网| 一本色道久久88综合亚洲精品ⅰ| 久久精品视频中文字幕| 欧美人与性动交| 亚洲免费视频在线观看| 国产精品91久久久久久| 91久久夜色精品国产网站| 亚洲欧美日韩综合| 亚洲成人三级在线| 欧美大秀在线观看| 精品成人av一区| 亚洲欧洲日产国产网站| 日韩一区视频在线| 欧美性生交xxxxxdddd| 啊v视频在线一区二区三区| 欧美激情一二三| 日韩欧美在线视频日韩欧美在线视频| 亚洲国产日韩一区| 国产色视频一区| 亚洲一区二区三区乱码aⅴ蜜桃女| 亚洲乱码一区二区| 日韩美女在线播放| 亚洲人成免费电影| 色妞在线综合亚洲欧美| 韩国精品美女www爽爽爽视频| 久久这里只有精品99| 久久香蕉国产线看观看网| 欧美一级在线播放| 国产精品普通话| 夜夜嗨av一区二区三区四区| 在线色欧美三级视频| 美日韩精品免费观看视频| 成人精品视频在线| 成人福利在线观看| 欧美在线观看网址综合| 久久久久日韩精品久久久男男| 日韩欧美国产激情| 欧美大片大片在线播放| 亚洲精品白浆高清久久久久久| 亚洲色图18p| 国产精品久久久久久久久久久久久久| 国产精品www网站| 国产成人精品日本亚洲专区61| 日韩美女在线看| 亚洲男人第一网站| 欧美精品18videos性欧| 草民午夜欧美限制a级福利片| 亚洲a在线播放| 亚洲欧美成人在线| 亚洲成人在线视频播放| 成人免费视频在线观看超级碰| 日本19禁啪啪免费观看www| 亚洲欧美日韩精品久久| 亚洲精品久久久久久久久久久| 青青精品视频播放| 欧美猛交免费看| 精品视频久久久久久久| 国产精品1234| 国产成人在线一区| 国产精品第一页在线| 影音先锋欧美精品| 欧美午夜www高清视频| 国产深夜精品福利| 性亚洲最疯狂xxxx高清| 久久九九热免费视频| www.亚洲男人天堂| 97超碰蝌蚪网人人做人人爽| 久久精品国产欧美亚洲人人爽| 成人伊人精品色xxxx视频| 国产999精品久久久| 亚洲精品黄网在线观看| 国产精品夜间视频香蕉| 欧美精品成人在线| 国产精品成人va在线观看| 91最新在线免费观看| 日韩视频在线一区| 亚洲在线一区二区| 亚洲电影在线观看| 中文字幕九色91在线| 亚洲国产精品一区二区三区| 国内伊人久久久久久网站视频| 欧美国产亚洲视频| 91成人精品网站| 国产精品999| 亚洲天堂成人在线视频| 欧美日韩美女在线观看| 欧美成人免费大片| 在线观看国产精品淫| 中文字幕精品久久久久| 国产日韩精品电影| 午夜精品视频在线| 亚洲欧美激情四射在线日| 日韩精品欧美激情| 成人精品一区二区三区电影黑人| 欧美日韩激情视频8区| 日本午夜精品理论片a级appf发布| 国产91ⅴ在线精品免费观看| 精品亚洲一区二区三区在线播放| 国产日韩欧美影视| 久久精品亚洲94久久精品| 欧美成人精品一区二区| 久久综合久中文字幕青草| 91老司机在线| 亚洲欧洲免费视频| www国产亚洲精品久久网站| 欧美激情在线狂野欧美精品| 精品视频在线播放免| 成人黄色免费看| 亚洲欧洲日本专区| 5278欧美一区二区三区| 午夜美女久久久久爽久久| 亚洲欧洲第一视频| 欧洲日本亚洲国产区| 在线日韩欧美视频| 国产精品aaaa| 97国产一区二区精品久久呦| 秋霞成人午夜鲁丝一区二区三区| 亚洲第一页自拍| 91精品国产综合久久香蕉最新版| 日日骚久久av| 亚洲天堂精品在线| 欧美激情一二三|