一:问题的引出
在上一篇,我对于读写分离和主从切换提到了一点个人的不成熟的想法:读写分离和主从切换应该从应用层面或者中间件层面来实现,而不是一问的交由数据库。然后这里我就说明一些个人对此的见解:
(1)在实际项目中,读的操作量是远远大于写的操作量。
(2)为了切合事务的特性,很多时候需要在写的时候进行加锁,导致读的效率大大降低,一次读写分离很有必要。
(3)在应用层面(或者中间件)不会影响数据库的整体。
这里我们主要就是在应用层面做一下扩展,至于中间件层面会在后面谈到。
二:代码解读
我们这里使用了Springboot+Druid来实现读写分离。实际上读写分离的核心还是挺简单的就是基于Aop实现在读取Mysql之前来切换数据源,这里就有个问题,就是这个aop加载service还是Mapper层的问题?如何加载Service层,那么就需要考虑事物和AOP的执行顺序问题,如果加载Mapper层那么就不用考虑了。
(1)Yml文件配置多数据源和druid(主要就是Spirng.datasource的配置了)
server:
port: 8987
spring:
application:
name: system-basic
thymeleaf:
mode: HTML
cache: false
mvc:
view:
prefix: /templates
cache:
ehcache:
config: classpath:config/ehcache/ehcache.xml
datasource:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://192.168.36.132:3306/fk?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 123qwe
readSize: 1
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
driver-class-name: com.mysql.jdbc.Driver
filters: stat,wall
initialSize: 5
maxActive: 20
maxPoolPreparedStatementPerConnectionSize: 20
maxWait: 60000
minEvictableIdleTimeMillis: 300000
minIdle: 5
poolPreparedStatements: true
testOnBorrow: false
testOnReturn: false
testWhileIdle: true
timeBetweenEvictionRunsMillis: 60000
useGlobalDataSourceStat: true
validationQuery: SELECT 1 FROM DUAL
slave:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://192.168.36.132:3307/fk?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 123qwe
connectionProperties: