案例-数据源切换读写分离

数据库主备

在高并发的环境下数据库常常会进行高可用的拓展,例如分库分表,读写分离,集群,主备,主备复制,当然也会暴露很多的问题:数据迁移,数据一致性,单点故障等等问题。

(当然上述的内容都要根据公司内部的业务场景、数据量、访问量、并发量、高可用的要求)

这些大部分的操作都不是开发人员操心的,我们操心的是如何在应用层的读写分离(驱动层应该会更好吧),多数据源主备切换等等,此次分享的就是一个在Mybaits+spring整合的情况下多数据源切换和读写分离的案例

项目说明

1.读写分离:写操作进入到主库,读操作进入到备库集。
2.多数据源:采用一主多从的数据源配置 ,根据操作切换数据源
3.使用java项目搭建

注意:读写分离的情况下,主备数据同步依靠于本身提供的数据库同步复制功能

项目

  1. 加入项目需要的jar包

这里写图片描述

  1. 项目配置文件

这里写图片描述

  1. 项目
    这里写图片描述

2.1 applicationContext.xml (头尾省去)

<context:annotation-config />
<!-- <context:component-scan base-package="dao" /> -->
<aop:aspectj-autoproxy/>
<!-- ibatis3 工厂类 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="classpath:sqlMapConfig.xml" />
    </bean>
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory" />
    </bean>
<bean id="dynamicSqlSessionTemplate" class="datasource.DynamicSqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory" />
        <constructor-arg index="1" ref="sqlSessionTemplate" />
</bean>
<!-- mapper扫描器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionTemplate" ref="dynamicSqlSessionTemplate"></property>
<!-- 扫描包路径,如果需要扫描多个包,中间使用半角逗号隔开  com.yuhiwy.SysManager.dao-->
        <property name="basePackage" value="dao"></property> 
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>

2.2 applicationContext-tx.xml


    <!-- 定义单个jdbc数据源的事务管理器 -->
    <bean id="transactionManager"
        class="datasource.DynamicDataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <!-- 以 @Transactional 标注来定义事务  -->
    <tx:annotation-driven transaction-manager="transactionManager"/>


    <!-- 配置事务的传播特性 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="insert*" propagation="REQUIRED" read-only="false"
                rollback-for="Exception" />
            <tx:method name="delete*" propagation="REQUIRED" read-only="false"
                rollback-for="Exception" />
            <tx:method name="update*" propagation="REQUIRED" read-only="false"
                rollback-for="Exception" />
            <tx:method name="proc*" propagation="REQUIRED" read-only="false"
                rollback-for="Exception" />
            <tx:method name="select*" read-only="true" />
            <tx:method name="*" read-only="false" />
            <!-- <tx:method name="*" read-only="true" /> -->
        </tx:attributes>
    </tx:advice>

    <aop:aspectj-autoproxy/>
    <!-- 那些类的哪些方法参与事务 -->
    <aop:config>
        <aop:pointcut id="allManagerMethod" expression="execution(* dao..*(..))" />
        <aop:advisor pointcut-ref="allManagerMethod" advice-ref="txAdvice" />
    </aop:config>

2.3 application-dataSource.xml

    <!-- C3P0连接池配置 -->
    <bean id="master" class="com.alibaba.druid.pool.DruidDataSource">

         <!-- 基本属性 url、user、password -->  
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/db1"/>  
        <property name="username" value="root"/>  
        <property name="password" value="root"/>  

        <!-- 配置初始化大小、最小、最大 -->  
        <property name="initialSize" value="20"/>  
        <property name="minIdle" value="20"/>  
        <property name="maxActive" value="200"/>  

        <!-- 配置获取连接等待超时的时间 -->  
        <property name="maxWait" value="255000"/>  

    </bean>

    <bean id="dataSource2" class="com.alibaba.druid.pool.DruidDataSource">
     <!-- 基本属性 url、user、password -->  
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/db2"/>  
        <property name="username" value="root"/>  
        <property name="password" value="root"/>  

        <!-- 配置初始化大小、最小、最大 -->  
        <property name="initialSize" value="20"/>  
        <property name="minIdle" value="20"/>  
        <property name="maxActive" value="200"/>  

        <!-- 配置获取连接等待超时的时间 -->  
        <property name="maxWait" value="255000"/>  
    </bean>

    <!-- <bean id="dataSource3" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass">
            <value>com.mysql.jdbc.Driver</value>
        </property>
        <property name="jdbcUrl">
            <value>jdbc:mysql://192.168.1.246:3306/db3</value>
        </property>
        <property name="user">
            <value>ysb</value>
        </property>
        <property name="password">
            <value>ysb</value>
        </property>
        <property name="initialPoolSize">
            <value>20</value>
        </property>
        <property name="minPoolSize">
            <value>20</value>
        </property>
        <property name="maxPoolSize">
            <value>200</value>
        </property>
        <property name="maxIdleTime">
            <value>255000</value>
        </property>
    </bean> -->

    <bean id="dataSource" class="datasource.DynamicDataSource">
        <property name="master" ref="master" />     
        <property name="slaves">
            <list>
                <ref bean="dataSource2"/>
                <!-- <ref bean="dataSource3"/> -->
            </list>         
        </property>
    </bean>

未完待续。

发布了48 篇原创文章 · 获赞 8 · 访问量 9万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章