随笔-199  评论-203  文章-11  trackbacks-0
 在很多大型应用中都会对数据进行切分,并且采用多个数据库实例进行管理,这样可以有效提高系统的水平伸缩性。而这样的方案就会不同于常见的单一数据实例的方案,这就要程序在运行时根据当时的请求及系统状态来动态的决定将数据存储在哪个数据库实例中,以及从哪个数据库提取数据。

 

Figure 1 数据分割及多数据库架构

    通常这种多数据源的逻辑会渗透到业务逻辑中,同时也会给我们使用的数据访问API诸如Hibernate和iBatis等带来不便(需要指定多个SessionFactory或SqlMapClient实例来对应多个DataSource)。


Figure 2 多数据源的选择逻辑渗透至客户端

 

    解决方案


Figure 3 采用Proxy模式来封装数据源选择逻辑

    通过采用Proxy模式我们在方案中实现一个虚拟的数据源,并且用它来封装数据源选择逻辑,这样就可以有效地将数据源选择逻辑从Client中分离出来。

    Client提供选择所需的上下文(因为这是Client所知道的),由虚拟的DataSource根据Client提供的上下文来实现数据源的选择。

    Spring2.x的版本中提供了实现这种方式的基本框架,虚拟的DataSource仅需继承AbstractRoutingDataSource实现determineCurrentLookupKey()在其中封装数据源的选择逻辑。

    实例:

publicclass DynamicDataSource extends AbstractRoutingDataSource {

      static Logger log = Logger.getLogger("DynamicDataSource");

      @Override

      protected Object determineCurrentLookupKey() {

            String userId=(String)DbContextHolder.getContext();

            Integer dataSourceId=getDataSourceIdByUserId(userId);

            return dataSourceId;

      }

}

    实例中通过UserId来决定数据存放在哪个数据库中。

    配置文件示例:

<bean id="dataSource" class="com.bitfone.smartdm.datasource.DynamicDataSource">

              <property name="targetDataSources">

                 <map key-type="java.lang.Integer">

                    <entry key="0" value-ref="dataSource0"/>

                    <entry key="1" value-ref="dataSource1"/>

                    <entry key="2" value-ref="dataSource2"/>

                 </map>

              </property>

              <property name="defaultTargetDataSource" ref="dataSource0"/>

            </bean>

            <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">

                <property name="configLocation" value="classpath:com/bitfone/smartdm/dao/sqlmap/sql-map-config.xml"/>

                <property name="dataSource" ref="dataSource"/>

           </bean>

            <bean id="UserInfoDAO" class="com.bitfone.smartdm.dao.impl.UserInfoDAO">

 

                  <property name="sqlMapClient" ref="sqlMapClient"/>

            </bean>

posted on 2009-07-27 21:54 Werther 阅读(4800) 评论(6)  编辑  收藏 所属分类: 10.Java

评论:
# re: Spring多数据源解决方案 2009-07-28 09:35 | 扬帆出海
是个不错的方法,不过有些地方还是不明白。
以前采用的方式是创建两个sessionFactory,配置数据访问类的时候选择相应的sessionFactory。

我有两个问题:
1)sql-map-config.xml里是什么内容
2)String userId=(String)DbContextHolder.getContext();上下文中是怎么管理ID的?  回复  更多评论
  
# re: Spring多数据源解决方案 2009-07-28 13:57 | 海边沫沫
不错,收藏!  回复  更多评论
  
# re: Spring多数据源解决方案 2009-07-28 22:19 | MyYate
这个没法保证事务啊,我如果要对其中两个数据源进行更新操作,这种就不能实现了吧!  回复  更多评论
  
# re: Spring多数据源解决方案 2009-07-29 09:13 | 和尚
不错,不过应该再详细点就解答上面两个网友的问题就最好了:一个是如何管理sessionFactory?是spring来管理吗?底层实现了?另一个就是事务,如何细粒度事务?  回复  更多评论
  
# re: Spring多数据源解决方案 2009-07-29 15:44 | lordz
如果是MySQL+Oracle,sql-map-config.xml是不一样的 那怎么配置呢?  回复  更多评论
  
# re: Spring多数据源解决方案 [未登录] 2009-12-01 13:23 | 懒猫
如果各个dataSource上的数据库结构不一样的话,这个方法是不能解决问题的  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: