MySQL主从复制与读写分离
一、简介
MySQL主从复制和读写分离两者有着紧密的联系,只有部署好主从复制了,才能在此基础上进行数据库的读写分离。
1.MySQL支持的复制类型
a.基于语句的复制。
b.基于行的复制。
c.混合类型的复制。默认基于语句复制,当基于语句的复制无法精确复制时,就会采用基于行的复制。
2.读写分离
只在主服务器上写,从服务器上读。基本原理就是让主数据库处理事务性查询,而从服务器处理select查询。set global read_only=0;
目前常见的MySQL读写分离有两种:
a.基于程序代码内部实现
在代码中根据select、insert进行路由分类。有点是性能好,不需要增加额外的设备作为硬件开支;缺点是需要开发人员实现,运维人员无从下手。
b.基于中间代理实现
1)MySQL-Proxy。
2)Amoeba,由陈思儒开发,作者曾就职阿里巴巴,阿里巴巴将其应用于生产环境中。这个软件致力于mysql的分布式数据库前端代理层,它主要为应用层访问mysql的时候充当sql路由功能,并具备有负载均衡、高可用性、sql过滤、读写分离、可路由相关的到目标数据库,可并发请求多台数据库,不过它不支持事务和存储过程。
二、案例环境
系统:CentOS 6.5-64
主机:
master 192.168.0.100 cmake mysql
slave1 192.168.0.101 cmake mysql
slave2 192.168.0.102 cmake mysql
Amoeba 192.168.0.110 amoeba jdk
client 192.168.0.111
三、环境准备
1.配置主机名和ip地址
root@localhost #hostname master
root@master #vim /etc/hosts
192.168.0.100 master
192.168.0.101 slave1
192.168.0.102 slave2
192.168.0.110 amoeba
192.168.0.111 client
root@master #vim /etc/sysconfig/network
HOSTNAME=master
root@master #ifconfig -a //查询所有网卡
root@master #vim /etc/sysconfig/network-scripts/ifcfg-eth2
DEVICE=eth2
HWADDR=00:0C:29:49:0F:81
TYPE=Ethernet
UUID=d97bca82-0440-41f9-9cd0-02fe0909cee6
ONBOOT=yes
NM_CONTROLLED=yes
BOOTPROTO=static
IPADDR=192.168.0.10
NETMASK=255.255.255.0
root@master #service network restart
2.安装NTP
NTP时间同步服务器,在主节点上搭建,主节点可以是单独一台服务器,也可以是master,或者Amoeba服务器
root@master #mount /dev/cdrom /media/
root@master #rm -fr /etc/yum.repos/*
root@master #cat >/etc/yum.repos/local.repo<<end
>[local]
>name=cjenlet
>baseurl=file:///media/
>enabled=1
>gpgcheck=0
>end
root@master #yum -y install ntp
root@master #vim /etc/ntp.conf
server 127.127.1.0
fudge 127.127.1.0 stratum 8
root@master #service ntpd restart
root@master #service iptables stop
root@master #chkconfig iptables off
root@master #setenforce 0
root@master #vim /etc/selinux/config
SELINUX=disabled
从节点上安装ntpdate,每台需要同步时间的服务器都要安装
root@localhost ~#service iptables stop
root@master #chkconfig iptables off
root@localhost ~#setenforce 0
root@localhost ~#vim /etc/selinux/config
SELINUX=disabled
root@localhost ~#yum -y install ntpdate
root@localhost ~#/usr/sbin/ntpdate 192.168.0.100 //指向NTP服务器的ip地址
四、安装MySQL数据库
1.在master,slave1,slave2上安装mysql
[root@master ~]# yum -y install ncurses-devel
[root@master ~]# tar xvf cmake_2_.tgz
[root@master ~]# cd cmake-2.8.6/
[root@master cmake-2.8.6]# ./configure
[root@master cmake-2.8.6]#gmake
[root@master cmake-2.8.6]#gmake install
[root@master ~]# tar xvf mysql_5_.tgz
[root@master ~]# cd mysql-5.5.22/
[root@master mysql-5.5.22]# cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DWITH_EXTRA_CHARSETS=all -DSYSCONFDIR=/etc
[root@master mysql-5.5.22]#make &&make install
2.优化调整,master,slave1,slave2都要优化
[root@master mysql-5.5.22]# cp support-files/my-medium.cnf /etc/my.cnf
[root@master mysql-5.5.22]# cp support-files/mysql.server /etc/rc.d/init.d/mysqld
[root@master mysql-5.5.22]# chmod +x /etc/rc.d/init.d/mysqld
[root@master mysql-5.5.22]# chkconfig --add mysqld
[root@master mysql-5.5.22]# cat >>/etc/profile<<end
PATH=$PATH:/usr/local/mysql/bin
end
[root@master mysql-5.5.22]# . /etc/profile
3.初始化数据库
[root@master mysql-5.5.22]# groupadd mysql
[root@master mysql-5.5.22]# useradd -M -s /sbin/nologin mysql -g mysql
//-M不创建家目录;-s指定shell环境;-g指定组
[root@master mysql-5.5.22]# chown -R mysql.mysql /usr/local/mysql/
[root@master mysql-5.5.22]# /usr/local/mysql/scripts/mysql_install_db --basedir=/usr/local/mysql/ --datadir=/usr/local/mysql/data/ --user=mysql
//本人不小心漏打了- -user=mysql,后来重新把整条命令完整执行一遍,这样是不对的,到时候启动数据库的时候会启动失败,建议把/usr/local/mysql/data/目录下的所有东西删掉,然后再完整执行这条命令
4.启动mysql服务
[root@slave1 mysql]# service mysqld start
[root@master mysql-5.5.22]# chkconfig mysqld on
[root@master mysql-5.5.22]# mysqladmin -u root password 'abc123.' //为root用户设置密码
五、规划配置主从服务器,验证主从复制。
1.配置mysql master主服务器
[root@master mysql-5.5.22]# vim /etc/my.cnf
log-bin=master-bin //修改
log-slave-updates=true //增加
server-id=11 //修改
[root@master mysql-5.5.22]# service mysqld restart
//重启服务
[root@master mysql-5.5.22]# mysql -uroot -pabc123. //登录数据库
mysql> grant replication slave on *.* to myslave@'192.168.0.%' identified by 'abc123.';
// 意思是,在mysql数据库user表中创建myslave用户,允许其能够以密码‘abc123.’从
//网段为192.168.0.%访问数据库时有复制的权限
//夺权:
revoke replication slave on *.* from myslave@'192.168.0.%'
//mysql> grant replication slave on *.* to myslave@192.168.0.102 identified by 'abc123.';
//只给单个ip赋予权限,给ip地址改成主机名,建议先把user表的myslave对应的host改成///slave1
mysql>update user set host='slave1' where user='myslave';
mysql> flush privileges; //跟新用户列表
mysql> show master status;
2.配置mysql slave从服务器
a. [root@slave1 mysql]# vim /etc/my.cnf
server-id = 22
//修改,server-id不能与服务器相同
relay-log=relay-log-bin
//增加
relay-log-index=slave-relay-bin.index
//增加
b. [root@slave1 mysql]# service mysqld restart //重启服务
c. 登录从服务器mysql数据库,配置同步
[root@slave1 mysql]# mysql -uroot -pabc123.
mysql> change master to master_host='192.168.0.100',master_user='myslave',master_password='abc123.',master_log_file='master-bin.000001',master_log_pos=488;
//注意单引号要打全,每次设置都要先回到master主机show master status;
//在slave2从服务器上只需把上面这条命令中的slave1改为slave2,执行
d. mysql> start slave; //启动同步
mysql> show slave status\G;
//查看slave状态,确保以下两个值为yes
3.验证主从复制效果
mysql> create database cjenlet;
//主服务器上创建cjenlet数据库
mysql> show databases;
//master,slave1,slave2,上分别查看,的到的结果是一样的,都有新建的cjenlet数据库存在
六、搭建mysql读写分离
1.环境准备,在amoeba主机上安装java环境
[root@amoeba ~]# cp jdk_6u14.bin /usr/local/
[root@amoeba ~]#cd /usr/local
[root@amoeba local]# chmod +x /usr/local/jdk_6u14.bin
[root@amoeba local]# ./jdk_6u14.bin //按enter继续
[root@amoeba local]# vim /etc/profile
export JAVA_HOME=/usr/local/java
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin:$PATH:$HOME/bin
export AMOEBA_HOME=/usr/local/amoeba/
export PATH=$PATH:$AMOEBA_HOME/bin
[root@amoeba local]# vim /etc/profile
[root@amoeba local]# java -version
2.安装amoeba
[root@amoeba ~]# mkdir /usr/local/amoeba
[root@amoeba ~]# tar xvf amoeba_m.tgz -C /usr/local/amoeba/
[root@amoeba ~]# chmod -R 755 /usr/local/amoeba/
[root@amoeba ~]# /usr/local/amoeba/bin/amoeba
//显示如下图则成功
3.配置amoeba读写分离,两个slave读负载均衡
master:
mysql> grant all on *.* to test@'amoeba' identified by 'abc123.';
//只在master上给创建test用户就可以了,因为slave1和slave2都会同步的。
//只赋予amoeba具有代理的权限,以test用户管理数据库,通过代理,其没有创建用户和给//用户赋权的权限
4.编辑amoeba.xml配置文件
[root@amoeba ~]# vim /usr/local/amoeba/conf/amoeba.xml
//修改下图中红框的地方,这是设置amoeba管理密码
//修改下图红框的地方,这是规划读写分离
5.配置dbServer.xml配置文件
[root@amoeba ~]# vim /usr/local/amoeba/conf/dbServers.xml
6.启动amoeba
[root@amoeba ~]#/usr/local/amoeba/bin/amoeba start&
//后台运行,没有‘&’是前台运行的意思
[root@amoeba ~]#netstat -anpl|grep java
//可以查看到amoeba的监听端口,默认为8066,可以在amoeba.xml文件中修改端口
七、测试读写分离
1.客户机通过端口访问代理登陆mysql
cjenlet@cjenlet-u:~$ mysql -uamoeba -pabc123. -h 192.168.0.110 -P 8066
//确保客户端有mysql客户端工具,能够与整个网络互通,其他的不需要
注意:指定端口的P是大写的,否则永远过不去。
2.创建数据
a.本地登陆master主机mysql数据库,创建表cjenDB
mysql> use cjenlet;
mysql> create table cjenDB (id int(10),name varchar(10),address varchar(20));
mysql> describe cjenDB; //查看表结构
//这时slave1和slave2都会同步这份数据,在它们上显示的结果是一样的
b.制造差异,以便后面区分读写分离的效果
先关掉slave1和slave2的slave功能
slave1:
mysql>stop slave;
slave2:
mysql>stop slave;
master,slave1和slave2上分别在表cjenDB上插入不同的数据
master:
mysql> insert into cjenDB values('1','cjenlet','this_is_master');
slave1:
mysql> insert into cjenDB values('2','cjenlet','this_is_slave1');
slave2:
mysql> insert into cjenDB values('3','cjenlet','this_is_slave2');
3.客户端访问数据库
a.负载均衡:
mysql>use cjenlet;
mysql>select * from cjenDB;
//如果没有出错的话,第一次查到的结果是slave1上表cjenDB的数据
//第二次查到的结果是slave2上表cjenDB的数据,方正多次查询结果是不一样的,分别是slave1和slave2上的数据,这就是amoeba实现mysql负载均衡的体现。
//不过本人实现的过程中却没有这一现象出现,一直都是slave2的数据,不知道问题出在哪里
解决:
查看对比slave1和slave2的相关配置文件
发现slave1的/etc/hosts文件有一条打错,导致没有amoeba主机的ip记录
本机的ip地址配置文件/etc/sysconfig/network-scripts/ifcfg-eth2中的DEVICE=eth2也打成DEVICE=eth2: ,多打了一个冒号
把这些弄号后,发现还是client还是select不到slave1的数据
后来推断应该是之前的ip地址和hosts文件的出错导致主从同步时,master主机创建test用户时,slave1没有同步过来,所以只要在slave1上重新创建一次test用户即可
b.读写分离:
在客户端执行
mysql>insert into cjenDB values('4','cjenletC','this_is_client');
mysql>select * from cjenDB;
//这时客户端查到的结果是没有这一行内容的,而master主机上查到的结果是有的。