2012-03-13 42 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