2012-03-13 49 views
1

我們正在基於Spring的Web應用中的關鍵業務高可用性的工作。 Hibernate是ORM,MySQL是使用的數據庫。我們的架構迫使我們有以下機制。使用對Hibernate的回退數據源春

  • Webapp首先嚐試連接到主MySQL服務器。
  • 如果失敗,它將連接到次要MySQL服務器,該服務器大部分與數據不同步。
  • 的Web應用程序需要知道哪個MySQL服務器它連接到,因爲我們要通知時,他使用輔助服務器的用戶。
  • 只要連接重新建立與主,連接必須從次級切換到主。

我停留在第一個階段。我無法找到如何指導Spring/Hibernate使用多個數據庫服務器。

這是當前配置文件(去掉不需要的東西):

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang" 
    xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:util="http://www.springframework.org/schema/util" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd 
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 
     http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd 
     http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd 
     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd 
     http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> 


    <context:annotation-config /> 

    <context:component-scan base-package="com.smartshop" /> 

    <bean 
     class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" /> 


    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 
     destroy-method="close"> 
     <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
     <property name="url" value="jdbc:mysql://localhost:3306/primarydb" /> 
     <property name="username" value="username" /> 
     <property name="password" value="password" /> 
     <property name="maxIdle" value="10" /> 
     <property name="maxActive" value="100" /> 
     <property name="maxWait" value="10000" /> 
     <property name="validationQuery" value="select 1" /> 
     <property name="testOnBorrow" value="false" /> 
     <property name="testWhileIdle" value="true" /> 
     <property name="timeBetweenEvictionRunsMillis" value="1200000" /> 
     <property name="minEvictableIdleTimeMillis" value="1800000" /> 
     <property name="numTestsPerEvictionRun" value="5" /> 
     <property name="defaultAutoCommit" value="false" /> 
    </bean> 


    <bean id="sessionFactory" 
     class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
     <property name="dataSource" ref="dataSource" /> 
     <property name="configLocation"> 
      <value>/WEB-INF/hibernate.cfg.xml</value> 
     </property> 
     <property name="configurationClass"> 
      <value>org.hibernate.cfg.AnnotationConfiguration</value> 
     </property> 
     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 
       <prop key="hibernate.show_sql">false</prop> 
      </props> 
     </property> 
    </bean> 

    <tx:annotation-driven /> 

    <bean id="transactionManager" 
     class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="sessionFactory" /> 
    </bean> 

    <bean 
     class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor" 
     name="openSessionInViewInterceptor"> 
     <property name="sessionFactory" ref="sessionFactory"></property> 
     <property name="flushMode"> 
      <bean 
       id="org.springframework.orm.hibernate3.HibernateAccessor.FLUSH_AUTO" 
       class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean" /> 
     </property> 
    </bean> 

    <bean id="handlerMapping" 
     class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> 
     <property name="interceptors"> 
      <list> 
       <ref bean="localeChangeInterceptor" /> 
       <ref bean="openSessionInViewInterceptor" /> 
      </list> 
     </property> 
    </bean> 

有沒有一種方法來定義彈簧連接到備份數據源當主數據源不可訪問?

+0

* *也許這將是有益的:http://ha-jdbc.sourceforge.net – 2012-03-13 08:20:52

+0

不會出現服務我的目的:( – 2012-03-13 09:49:50

回答

0

這種技巧必須在MySQL端完成,而不是在webapp上完成。例如MySQL羣集可以處理這個問題。

更多的相關信息在這裏:

-http://www.mysql.com/products/cluster/

-http://en.wikipedia.org/wiki/MySQL_Cluster

更新:

好的,那麼,看看這裏 - > org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource。構建一個覆蓋方法getConnection()和getConnection(String username,String password)的自定義實現。通過捕獲SQLException覆蓋它們,如果發生,請選擇其他數據源。

+0

我知道這是錯誤的..但我們目前的架構迫使我們有以上機制:(我們堅持舊的架構,不能立即行動!! – 2012-03-13 10:45:56

1

,如果您配置數據源作爲一個JNDI數據源,你可以使用下面的配置

<bean id="dataSource" 
    class="org.springframework.jndi.JndiObjectFactoryBean"> 
    <property name="jndiName" ref="datasourceJNDIName" /> 
    <property name="defaultObject" ref="fallBackDataSource" /> 
</bean> 

<!-- fall back datasource if JNDI look up of main datasource fails --> 
<bean id="fallBackDataSource" 
    class="org.springframework.jndi.JndiObjectFactoryBean"> 
    <property name="jndiName" ref="datasourceJNDIName-2" /> 
</bean> 
+0

謝謝它解決了第一部分。我們是否有一個選項來檢查defaultDataSource是否已經恢復並連接到它? – 2012-03-13 10:51:45

+0

hmmm,你可以創建一個表讓我們說'TDBVERSION',它只包含一行,不管dat基地是否備份。並且通過查詢「TDBVERSION」,您的系統會知道它是否正在使用備份。 – dursun 2012-03-13 11:09:39