Mysql主从架构搭建、及读写分离策略的实现

Mysql主从架构搭建、及读写分离

单机存储MySQL/Oracle有哪些缺点?

1)数据存储不安全-缺少备份机制

2)单个节点-连接数有限(修改-插入|更新|删除、查询)

连接分流:将修改操作发送给指定一个机器(称为主机master、Leader)、其他机器(slave、follower)负责同步master|Leader的操作。

Master数据和Slave节点数据 最终一定是一致的。

注意:Leader或者Master 可以读、可以写

           slave或者follower 只可以读

优点:对主机实行 连接分流(将读操作从Master分离)

      从机 负责系统所有的读操作(多个从机共同承担 读 负载)

系统而言:读、写

(*本次搭建结构为一主二从)

192.168.199.128 master

192.168.199.129 slave

192.168.199.130 slave

搭建步骤:

1)主机和从机安装mysql(centos为例)

安装mysql

[root@CentOSX ~]# yum install -y mysql-server
附:MySQL卸载步骤
[root@CentOSX ~]# yum remove mysql-server
[root@CentOSX ~]# rm -rf /var/lib/mysql

配置用户root

[root@CentOSX ~]# service mysqld start
[root@CentOSX ~]# mysqladmin -u root password 'root'

远程登录授权

[root@CentOSX ~]# mysql -u root -proot
mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT
OPTION;
mysql> FLUSH PRIVILEGES;
mysql> use mysql;
mysql> delete from user where password ='';
mysql>commit;
mysql>exit

说明:机器A作为MySQL的主机(Master )、机器B作为MySQL的从机(Slave),两台机 器均已经关闭防火墙。

2)主从配置

机器A(主机)配置

修改/etc/my.cnf文件

[root@CentOSA ~]# vim /etc/my.cnf
server-id=1
log-bin=mysql-bin
binlog-do-db=test
binlog-ignore-db=mysql
expire_logs_days=10
auto_increment_increment=2
auto_increment_offset=1
...

重启mysql服务

[root@CentOSA ~]# service mysqld restart

登录MySQL查看主机状态

[root@CentOSA ~]# mysql -u root -proot
mysql> show master status\G;
*************************** 1. row ***************************
File: mysql-bin.000001
Position: 106
Binlog_Do_DB: test
Binlog_Ignore_DB: mysql
1 row in set (0.00 sec)
ERROR:
No query specified

注意:这里需要记录  File: mysql-bin.000001
                                  Position: 106

机器B(从机)配置(C机器同B机器,只需要向server-id修改为3)

修改/etc/my.cnf文件

[mysqld]
server-id=2
log-bin=mysql-bin
replicate-do-db=test
replicate-ignore-db=mysql
auto_increment_increment=2
auto_increment_offset=2
...

重启MySQL服务

[root@CentOSB ~]# service mysqld restart

登录MySQL配置从机查看状态(使用刚才记录的值

[root@CentOSB ~]# mysql -u root -proot
mysql> stop slave;
mysql>change master to master_host='192.168.199.128',master_user='root',master_password='root',master_log_file='mysql-bin.000001',master_log_pos=106;
mysql> start slave;
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.199.128
Master_User: root
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 106
......
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: test
Replicate_Ignore_DB: mysql
......

在查看从机状态的时候如 果处出现了红色字体的信息,说明MySQL的主从搭建成功了。

 

路由中间件设计(实现读写分离)(示意)

 

<bean id ="masterDataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
		<property name="url" value="jdbc:mysql://192.168.199.128:3306/test"/>
		<property name="username" value="root"/>
		<property name="password" value="root"/>
</bean>

<bean id = "slaveDataSource1" class= "org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
		<property name="url" value="jdbc:mysql://192.168.199.129:3306/test"/>
		<property name="username" value="root"/>
		<property name="password" value="root"/>
</bean>

<bean id = "slaveDataSource2" class= "org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
		<property name="url" value="jdbc:mysql://192.168.199.130:3306/test"/>
		<property name="username" value="root"/>
		<property name="password" value="root"/>
</bean>

 

//设置状态标识类 用来表示读写状态
public interface Status {
	String READ = "read";
	String WRITE = "write";
}

 

public class MyThreadLocal {
	private static final ThreadLocal<String> TL = new ThreadLocal<String>();
	public static void setStatus(String str){
		TL.set(str);
	}
	
	public static String getStatus(){
		return TL.get();
	}
	
	public static void remove(){
		TL.remove();
	}
}

利用Spring AOP通过方法环绕通知获取调用的方法 

import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class ReadWriteMethodInterceptor implements MethodInterceptor{
	@Override
	public Object invoke(MethodInvocation arg0) throws Throwable {
		Method method = arg0.getMethod();
		String name = method.getName();
		
		//匹配以query开头的方法
		if(name.matches("^query.*")){
			MyThreadLocal.setStatus(Status.READ);
		}else{
			MyThreadLocal.setStatus(Status.WRITE);
		}
		Object proceed = arg0.proceed();
		MyThreadLocal.remove();
		return proceed;
	}
}

创建自定义路由实现

import java.util.Random;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class ReadWriteDataSource extends AbstractRoutingDataSource{
	//xml中配置的mysql数据源
	private static final String[] s = {"slaveDataSource1","slaveDataSource2"};
	@Override
	protected Object determineCurrentLookupKey() {
		String status = MyThreadLocal.getStatus();
		//System.out.println(status);
		if(status==null){//默认使用主库
			return "masterDataSource";
		}else{
			if("read".equals(status)){
                        //这里以随机来作为自己的路由策略 后续可以自定义路由策略
				return s[new Random().nextInt(s.length)];
			}else{
				return "masterDataSource";
			}
		}
	}
}

配置自己的路由策略到spring工厂中

到此,就完成了mysql读写分离的路由实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值