spring+mybatis+uncode-dal实现数据库读写分离
1.准备工作搭建本地环境:virtualbox安装两个fedora虚拟机,部署流复制主从postgres数据库在两台机器上 部署应用,测试应用是否可以访问主库搭建流复制环境参考http://www.sijitao.net/1764.html要注意的事项是:从库不需要initdbpg_basebackup到从库的目录所属用户应该是postgres:postgres
·
1.准备工作
搭建本地环境:
virtualbox安装两个fedora虚拟机,部署流复制主从postgres数据库在两台机器上
部署应用,测试应用是否可以访问主库
搭建流复制环境参考http://www.sijitao.net/1764.html
要注意的事项是:
从库不需要initdb
pg_basebackup到从库的目录所属用户应该是postgres:postgres
需要将
wal_keep_segments设为一个比较大的值譬如32,防止在创建从库的过程中有些segment被删除了,导致从库起不起来
2.代码实现
uncode-dal使用
其原理是根据不同的操作,设置不同的route,从而选择不同的datasource
例如调用其insert方法,先设置route为写,那么只会从主datasource中获得连接
具体代码逻辑是
a.设置
DBContextHolder的该线程的thread local中值为write
b.调用动态数据源的getConnection的时候判断当前线程的thread local中的值,如果是write,
从主datasource获得connection
如果是read,从多个slaveDataSource中随机的获得一个datasource,并获得其连接
c.如果连续三次获得datasource连接失败(对应应用的三次数据库操作),
如果是读操作,那么将这个失败的从库datasource
从从库list中删除
如果是写操作,那么切换当前datasource为主库,备库中的一个(
原来是主库,如果当前从库可用,切换为从库,对原来是从库也是同样的逻辑),这个就导致数据库切换太慢了,可以根据具体的业务场景做优化
由于使用了threadlocal,所以多个线程同时执行数据库操作,获取datasource的逻辑也不会出错
3.spring+mybatis+uncode dal
spring applicationcontext.xml
1.配置多个数据源,建议使用druiddatasource
<bean id="dataSource1" class="com.alibaba.druid.pool.DruidDataSource"
...
</bean>
<bean id="dataSource2" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
destroy-method="close">
...
</bean>
2.配置uncode动态数据源,指定主库,备库(用于写操作),从库(用于读操作)
<bean id="dynamicDataSource" class="cn.uncode.dal.datasource.DynamicDataSource">
<bean id="dynamicDataSource" class="cn.uncode.dal.datasource.DynamicDataSource">
<property name="slaveDataSources”>//设置从库,读操作从这些数据库中读
<map key-type="java.lang.String">
<entry key="readDataSourceOne" value-ref="dataSource2"/> (可配置多个)
</map>
</property>
<!-- 主数据库配置 -->
<entry key="readDataSourceOne" value-ref="dataSource2"/> (可配置多个)
</map>
</property>
<!-- 主数据库配置 -->
<property name="masterDataSource" ref="dataSource1" />
<property name="standbyDataSource" ref=“dataSource2”/ >
</bean>
<bean id="transactionManager" class="cn.uncode.dal.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dynamicDataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="cn.uncode.dal.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dynamicDataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
3.指定mybatis mapper配置文件及dao类位置,需指定datasource为上面定义的动态数据源
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dynamicDataSource" />
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"></property>
<property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"></property>
</bean>
<bean id="sqlSessionTemplateSimple" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
<!--更新采用单个模式 -->
<constructor-arg index="1" value="SIMPLE" />
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="...dao(包名)" />
<property name="sqlSessionTemplateBeanName" value="sqlSessionTemplateSimple" />
</bean>
<property name="dataSource" ref="dynamicDataSource" />
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"></property>
<property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"></property>
</bean>
<bean id="sqlSessionTemplateSimple" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
<!--更新采用单个模式 -->
<constructor-arg index="1" value="SIMPLE" />
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="...dao(包名)" />
<property name="sqlSessionTemplateBeanName" value="sqlSessionTemplateSimple" />
</bean>
4.那么在使用dao的时候,可以先指定是读操作还是写操作,然后再调用相应的操作
DBContextHolder.swithToRead();//这里可以定义dao的拦截器,指定某一类方法调用时都先执行这个操作
userDao.getNewAccount("1");
如果想使用其提供的baseDal(但是只支持单表操作)
在上面的applicationcontext.xml中再增加spring-jdbc配置(参加uncode-dal wiki)
java代码调用,见其说明
遇到的问题:
1.流复制从数据库不能启动
原因是主库保留的wal log数目太少,等从库配好启动的时候主库已经有些wal log被删除了
导致从库启动的时候从主库获得不了需要的wal log,需要不能启动
2.虚拟机上各种网络的含义,为啥有时候能联网,有时候不能联网(绕过)
怎么设置静态ip地址(通过界面settings,网络解决,后面看一些怎么通过修改配置文件解决)
3.迁移之后插入新的数据会报
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "index_28"
org.postgresql.util.PSQLException: ERROR: function geometry(text) does not exist
查看已经安装的extension,查看pg_extension视图
说明迁移的时候序列,extension有问题,后面看怎么解决,先绕过
4.如何纪录在每个数据库上执行了哪些操作
通过修改postgresql的log配置解决
5.在maven库中找不到uncode-dal的一些包?
解决方法:将uncode-dal的代码下载下来,重新编译生成jar包在本地
更多推荐
已为社区贡献2条内容
所有评论(0)