先大概介绍一下主从数据库是什么?
其实就是两个或N个数据库,一个或几个主负责写(当然也可以读),另一个或几个从只负责读.从数据库要记录主数据库的具体url以及BigLOG(二进制日志文件)的参数.原理就是在
定时的从主数据库的BigLOG文件中获取相应的日志记录,并转换成相应的sql语句进行同步.

SpringBoot整合Mybatis怎么自动化的区分主从数据库进行读写,并且保证其线程安全性;
创建一个DataBaseContextHolder类,在类里定义一个成员变量ThreadLocal(一个可以绑定线程的Map,自动会以当前线程为Key,并将传入的值做浅克隆保存),
定义一个枚举,创建两个枚举常量(Master,Slave),并写上get,set方法,以及clean方法(getDataBaseType(),setDataBaseType());
public class DataBaseContextHolder {
public enum DataBaseType {
Master, Slave;
}

private static final ThreadLocal<DataBaseType> CONTEXTHOLDER = new ThreadLocal<>();

public static void setDataBaseType(DataBaseType dst) {
if (dst == null)
throw new NullPointerException();
CONTEXTHOLDER.set(dst);
}

public static DataBaseType getDataBaseType() {
return CONTEXTHOLDER.get() == null ? DataBaseType.Master : CONTEXTHOLDER.get();
}

public static void clearDataSource() {
CONTEXTHOLDER.remove();
}

之后创建一个Mybatis配置类,继承MyBatisAutoConfiguration(这是SpringBoot对Mybatis的默认配置类,所以我们可以继承它进行一个扩展),
注入主数据源和从数据源,并复写SqlSessionFactory()方法,在方法里调用父类的SqlSessionFactory方法,参数需要传入一个AbstractRoutingDataSource对象,
这个我们需要写一个自定义类,并且继承这个类,实现它的一个抽象方法determineCurrentLookupKey(),在方法中,直接调用DataBaseContextHolder.getDataBaseType(),
并返回它的返回值.
之后我们需要创建我们自定义类的对象,并通过ClassLoaderRepository对象的SoftHashMap方法获得一个SoftHashMap对象(一个线程安全,并且排序也就是存取有序的Map集合,也不知道它很LinklistHashMap有神马区别),
将我们的枚举,DataBaseContextHolder.DataBaseType.Master和DataBaseContextHolder.DataBaseType.Slave作为键,两个主从数据源作为值传入,我们自定义的AbstractRoutingDataSource子类对象调用setTargetDataSource(SoftHashMap)方法(记录指向数据源),
再指定一个默认数据源setDefaultDataSource(master),这个肯定指定主数据源,可读可写啊.
@Configuration
@AutoConfigureAfter({ DataBaseConfiguration.class })
public class MybatisConfiguration extends MybatisAutoConfiguration {
@Resource(name = "masterDataSource")
private DataSource masterDataSource;
@Resource(name = "slaveDataSource")
private DataSource slaveDataSource;

@Bean(name = "sqlSessionFactory")
public SqlSessionFactory SqlSessionFactory() throws Exception {
return super.sqlSessionFactory(roundrobinDataSource());
}

public AbstractRoutingDataSource roundrobinDataSource() {
ReadWriterSplitRoutingDataSource rsd = new ReadWriterSplitRoutingDataSource();
SoftHashMap shm = new ClassLoaderRepository.SoftHashMap();
shm.put(DataBaseContextHolder.DataBaseType.Master, masterDataSource);
shm.put(DataBaseContextHolder.DataBaseType.Slave, slaveDataSource);
rsd.setDefaultTargetDataSource(masterDataSource);
rsd.setTargetDataSources(shm);
return rsd;
}
}

public class ReadWriterSplitRoutingDataSource extends AbstractRoutingDataSource {

@Override
protected Object determineCurrentLookupKey() {
return DataBaseContextHolder.getDataBaseType();
}
}

当然做完这一切也仅仅是指定了配置而已,我们并没有在我们想切换数据源时就可以指定数据源的函数.这个我们可以通过注解加Aop的方式来实现;
创建一个注解,不用添加属性,只要指定其可以在方法和类上生效,生命周期的话需要指定为运行时.
之后创建一个Aop类,并拦截带有此注解的方法,在其运行之前更换当前ThreadLocal中保存的DataBaseType为Slave,并在方法执行完后清除ThreadLocal.

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface ReadOnlyConnection {

}

@Aspect
@Component
public class ReadOnlyConnectionInterceptor implements Ordered {
private static final Logger log = LoggerFactory.getLogger(ReadOnlyConnectionInterceptor.class);

@Around("@annotation(readOnlyConnection)")
public Object connetionProceed(ProceedingJoinPoint proceedingJoinPoint, ReadOnlyConnection readOnlyConnection)
throws Throwable {
try {
log.info("set database connection to readonly");
DataBaseContextHolder.setDataBaseType(DataBaseContextHolder.DataBaseType.Slave);
return proceedingJoinPoint.proceed();
} finally {
DataBaseContextHolder.clearDataSource();
log.info("restore database connection");
}
}

@Override
public int getOrder() {
return 0;
}

}
这个Order的话只是一个可以指定执行顺序(执行优先级)的接口,其实用@Order注解也可以指定,实现不实现都无所谓,不用管它.

普通视图,物化视图

普通视图的话只是定义,不是一个物理上的实表,并且不能做增删改操作,当我们查找普通视图上保存的数据的时候,是由数据库根据定义来生成sql在基表上进行查询的.
而物化视图则是一个实实在在的物理意义上的实表,和普通表一样可以创建索引,做增删改操作,并可以指定两种更新方式(就是讲基表上更新过的数据同步到物化视图上),OnDemand和OnCommit.
OnDemand的话也有两种一种是手动刷新,也就是需要我们代码调用存储函数,而自动刷新则可以在创建物化视图的时候直接指定时间,具体操作请百度.
OnCommit则是见其名知其义了,就是在基表发生commit事件的时候(任何事件完成后都会触发),就将基表数据同步更新到物化视图上.

个人观点:视图的创建除非是安全必要,否则没有必要且浪费性能,很多时候一个冗余字段就可以解决的事情就不必做跨表或者跨库(Oracle专属)的视图了;

分表,分库
水平拆分:按行拆分,id若为int自增可以直接利用取膜再查表.为UUID类字符型,则需要先计算出其HASH值再取膜查找是那个表;
垂直拆分:根据字段关联性拆分;

当每日增长新数据很大的时候,可以利用存储过程加定时任务,进行一个周期性的建表;

分布式事物要解决的就是两个不同数据源之间保存的数据的最终一致性,实现方式只能通过合理的代码设计(例如:加版本号字段实现乐观锁)

2018-01-08 学习随笔 SpirngBoot整合Mybatis进行主从数据库的动态切换,以及一些数据库层面和分布式事物的解决方案的更多相关文章

  1. mybatis源码学习(四)--springboot整合mybatis原理

    我们接下来说:springboot是如何和mybatis进行整合的 1.首先,springboot中使用mybatis需要用到mybatis-spring-boot-start,可以理解为mybati ...

  2. SpringBoot学习- 3、整合MyBatis

    SpringBoot学习足迹 1.下载安装一个Mysql数据库及管理工具,同类工具很多,随便找一个都可以,我在windows下做测试项目习惯使用的是haosql 它内部集成了MySql-Front管理 ...

  3. spring学习07(整合MyBatis)

    10.整合MyBatis 10.1 相关jar包 junit <dependency> <groupId>junit</groupId> <artifactI ...

  4. Spring Boot入门系列(十九)整合mybatis,使用注解实现动态Sql、参数传递等常用操作!

    前面介绍了Spring Boot 整合mybatis 使用注解的方式实现数据库操作,介绍了如何自动生成注解版的mapper 和pojo类. 接下来介绍使用mybatis 常用注解以及如何传参数等数据库 ...

  5. Java学习笔记-spring整合mybatis

    这个项目就是一个例子,只有添加图书的功能: 项目架构: resource: 整合流程: 1.pom文件节点,这两个是整合用的,其他节点不再赘述: <!-- https://mvnreposito ...

  6. SpirngBoot整合Mybatis Plus多数据源

    导读 有一个这样子的需求,线上正在跑的业务,由于业务发展需要,需重新开发一套新系统,等新系统开发完成后,需要无缝对接切换,当初具体设计见草图. 添加依赖 <!--lombok--> < ...

  7. springboot学习四:整合mybatis

    在application.properties加入配置 ## Mybatis 配置 mybatis.typeAliasesPackage=org.spring.springboot.domain my ...

  8. Spring Boot学习笔记(五)整合mybatis

    pom文件里添加依赖 <!-- 数据库需要的依赖 --> <dependency> <groupId>org.mybatis.spring.boot</gro ...

  9. spring boot整合mybatis基于注解开发以及动态sql的使用

    让我们回忆一下上篇博客中mybatis是怎样发挥它的作用的,主要是三类文件,第一mapper接口,第二xml文件,第三全局配置文件(application.properties),而今天我们就是来简化 ...

随机推荐

  1. HDU 2544 最短路(模板题——Floyd算法)

    题目: 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你 ...

  2. Struts2与Ajax数据交互

    写在前面: ajax请求在项目中常常使用,今天就平时掌握的总结一下,关于使用ajax请求到Struts2中的action时,前台页面与后台action之间的数据传递交互问题. 这里我主要记录下自己所掌 ...

  3. 新版Azure Automation Account 浅析(一) --- 创建和Run As Account

    去年年底Azure中国的Automation Account悄悄做了升级.新版本不管从功能还是end user experience方面都让人耳目一新.如果说升级前只是一个运行脚本的小工具,升级后的A ...

  4. 利用光场进行深度图估计(Depth Estimation)算法之二——匹配算法

    光场相机由于能够捕获相机内部光线的强度和方向而得到整个光场,可以实现重聚焦(refocus)和视角变换等功能.进而可以进行深度估计获取深度图,前面说过利用重聚焦的图像进行深度估计,今天说一下利用不同视 ...

  5. 风险案例-28期-项目Leader与团队成员缺乏沟通,问题响应度较慢导致团队士气低落,工作效率低

    典型案例: A公司某C类项目目前进入开发高峰期,项目组的三个leader预计在项目的实际task投入占比为70%,剩30%工作时间用于指导组员进行作业实施并担当部分管理工作.从项目实施过程中发现Lea ...

  6. Django权限机制的实现

    Django权限机制的实现 1. Django权限机制概述 权限机制能够约束用户行为,控制页面的显示内容,也能使API更加安全和灵活:用好权限机制,能让系统更加强大和健壮.因此,基于Django的开发 ...

  7. Dreamweaver cs6中文版完整安装步骤:

    Dreamweaver cs6中文版完整安装步骤: http://www.cr173.com/soft/72633.html 1.首先我们需要下载Dreamweaver cs6官方中文原版安装程序,下 ...

  8. mybatis_helloword(1)

    摘录自:http://blog.csdn.net/y172158950/article/details/16979391 新的项目中用到mybatis,虽然不用自己写ORM的代码,但是借这个机会,学习 ...

  9. JVM内存划分简介

    参考:深入理解JAVA虚拟机(第二版)

  10. 理解rem实现响应式布局原理及js动态计算rem

    前言 移动端布局中,童鞋们会使用到rem作为css单位进行不同手机屏幕大小上的适配.那么来讲讲rem在其中起的作用和如何动态设置rem的值. 1.什么是rem rem是相对于根元素(html标签)的字 ...