概述
描述
读写分离是数据库集群的一种方式,这种方式可以将对数据库访问的压力分散到集群的各个节点上,但是因为是通过与主服务器进行同步,存储的数据量并没有减少,所有读写分离并没有解决如何减少存储压力。像微信的朋友圈,上亿人发布,这些数据还是必不可删的,数据量大,服务器数据库的存储却是有限的。读写分离无法解决。
使用场景
在存储量不大的情况下,并且访问量大的情况,当然,如果是访问量比较小的程序,也没有必要去使用读写分离。
实现方式
通过主从复制实现,主服务器复制数据同步到从服务器,可以进行一主一从,一主多从,主服务器进行读写(主要是写),从服务器进行读数据。还有一种热备功能(主备),当主服务器挂掉后,从服务器顶替主服务器。
主从复制(mysql为例)
复制类型
1.基于语句复制,也就是执行sql语句,mysql默认。
2.基于行的复制,把改变的内容复制到从服务器。
3.混合类型的复制。默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制。
主从同步原理
binlog:一个二进制的文件,记录了数据库更改的操作,不记录查询操作。可使用mysqlbinlog查看该文件。
- master有一个log dump线程,给slave传输bin log文件。
- slave有两个线程,一个I/O线程,去请求主库的binlog日志,将master的biglog拷贝到slave的relay(中继)log文件中。
- slave的第二个线程sql线程会读取relay log,执行具体操作,实现主从复制。
实现
我是通过虚拟机创建两个centos7系统模拟,ip地址(主:192.168.52.131,从:192.168.52.133)。各自安装mysql。
master配置:
vi /etc/my.cnf 修改配置文件
在[mysqld]下添加
server-id=1 //用作标识
log-bin=master-bin //二进制文件
log-slave-updates=true //级联复制
service mysqld restart //重启服务
show master status; //查看数据库状态
slave配置:
修改配置文件添加
server-id=10
log-bin=slave-bin
relay-log=relay-log
read_only=ON
重启mysql服务
修改要同步的master:
change master to master_host=‘192.168.52.131’,
master_port=3306,
master_user=‘root’,
master_password=‘123456’,
master_log_file=‘master-bin.000001’,
master_log_pos=120;
启动slave:start slave;
这时,我们在master进行的增删改等操作会在slave中会同步操作。可以自行测试。
读写分离
实现方式
- 代码方面使用spring路由数据源以及aop进行实现
- MySql中间件
第一种方式是把写在代码的配置中,所以在动态增加数据库节点时会出现问题,耦合度高,推荐使用中间件的形式。
MySql各类中间件:
1.Cobar:是阿里巴巴团队开发,由于最近几年不维护了,不推荐使用
2.MyCat:基于Cobar进行的二次开发,社区维护
3.mysql-proxy:其是mysql官方提供的mysql中间件服务
4.sharding-proxy:也是蛮常用的一个吧,并且该社区还有sharding-JDBC通过jdbc协议实现读写分离
MyCat搭建
MyCat:开源的分布式数据库系统,用java开发,所以安装MyCat前必须安装JDK,实现MySql、JDBC协议,通过Mysql协议与多个Mysql服务器通信,通过JDBC协议与其它主流数据库通信。
下载地址 http://dl.mycat.io/1.6.5/ 自行下载所需版本
解压:tar -zxvf Mycat-server-1.6.5-release-20180122220033-linux.tar.gz
配置环境变量,不用每次都进入bin目录执行命令
vi /etc/profile
//参考,只加mycat的就行了,其它不用管
export MYCAT_HOME=/usr/mycat
export CLASS_PATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$JAVA_HOME/lib
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$ZOOKEEPER_HOME/bin:$MYCAT_HOME/bin:$PATH
测试是否安装成功:
开启:mycat start
查看其它命令:mycat -h
配置文件
server.xml:mycat配置信息和用户授权信息
schema.xml:保存了mycat的逻辑库、表以及分片配置
rule.xml:分片规则
wrapper.xml:jvm内存配置
zkconf:zookeeper配置目录
<!-- 配置主机信息和用户 -->
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<!-- 心跳检测语句 -->
<heartbeat>select user()</heartbeat>
<!-- 远程数据库配置信息 -->
<writeHost host="192.168.52.131" url="192.168.52.131:3306" user="root"
password="123456">
<!-- can have multi read hosts -->
<readHost host="192.168.52.133" url="192.168.52.133:3306" user="root" password="123456" />
</writeHost>
<!-- 192.168.52.134是备份数据库,当131节点宕机时当作主机使用,测试的话可以不写 -->
<writeHost host="192.168.52.134" url="192.168.52.134:3306" user="root"
password="123456" />
</dataHost>
datahost:配置主机信息和
在dataHost节点的属性
- balance:
0是不开起读写分离
1是指所有的readHost(读服务器)与standby writeHost(备用服务器:主机宕机后切换到的服务器)都进行查询的负载均衡
2是指所有writeHost节点都不进行读操作,只有readHost进行读操作 - writeType:
0是所有写操作请求到可用writeHost
1是所有写操作随机请求到readHost
2是所有写操作随机请求到writeHost和readHost
dbDriver:
native:mysql与mysql通信
jdbc:mysql与其它主流数据库通信
代码实现读写分离
在代码中修改数据源
spring:
datasource:
password: 123456
url: jdbc:mysql://127.0.0.1:8066/mycatTest
username: root
driver-class-name: com.mysql.cj.jdbc.Driver
在master添加数据库mycatTest和表user后配置
server.xml
<user name="root" defaultAccount="true">
<property name="password">123456</property>
<!-- 添加mycatTest数据库 -->
<property name="schemas">TESTDB,mycatTest</property>
<!-- 表级 DML 权限设置 -->
<!--
<privileges check="false">
<schema name="TESTDB" dml="0110" >
<table name="tb01" dml="0000"></table>
<table name="tb02" dml="1111"></table>
</schema>
</privileges>
-->
</user>
<user name="user">
<property name="password">user</property>
<property name="schemas">TESTDB,mycatTest</property>
<property name="readOnly">true</property>
</user>
schema.xml
<schema name="mycatTest" checkSQLschema="false" sqlMaxLimit="100">
<table name="user" primaryKey="ID" dataNode="mycatTest"/>
</schema>
<dataNode name="mycatTest" dataHost="localhost1" database="mycatTest" />
<!-- 配置主机信息和用户 -->
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<!-- 心跳检测语句 -->
<heartbeat>select user()</heartbeat>
<!-- 远程数据库配置信息 -->
<writeHost host="192.168.52.131" url="192.168.52.131:3306" user="root"
password="123456">
<!-- can have multi read hosts -->
<readHost host="192.168.52.133" url="192.168.52.133:3306" user="root" password="123456" />
</writeHost>
<writeHost host="192.168.52.134" url="192.168.52.134:3306" user="root"
password="123456" />
</dataHost>
navicat建立mycat连接方便查看,mycat默认端口:8066
此时在代码进行数据库访问便是读写分离啦!