在实际生产环境中,如果对数据库的读和写都在同一个数据库服务器中操作,无论是在安全性,高可用性,还是高并发等各方面都是完全不能满足实际需求的,因此一般来说都是通过主从复制(Master-Slave)的方式来同步数据,再通过读写分离来提升数据库的并发负载能力这样的方案来进行部署与实施。
如下图所示, 一台 主mysql带两台从mysql进行了数据复制,前端应用在进行数据库写操作时,对主设备进行操作,在进行数据库读操作时,对两台从设备进行操作,这样大量减轻了对主设备的压力。
mysql主从复制原理
mysql的主从复制和mysql的读写分离有着紧密的联系,首先要部署主从复制,只有主从复制完成了,才能在此基础上进行数据的读写分离
mysql复制的工作过程详解
1)在每个事务更新数据完成之前,Master在二进制日志记录这些变化。写入二进制日志完成后,Master通知存储引擎提交事务
2)Slave将Master的Binary log复制到其中继日志。首先,Slave开始一个工作线程---I/O线程,I/O线程在Master上打开一个普通的连接,然后开始Binlog dump process。Binlog dump process从Master的二进制日志中读取事件,如果已经跟上Master,它会睡眠并等待Master产生新的事件。I/O线程将这些事件写入中继日志。
3)SQL slave thread(SQL从线程)处理该过程的最后一步。SQL线程从中继日志读取事件,并重放其中的事件而更新Slave的数据,使其与Master中的数据一致。只要该线程与I/O线程保持一致,中继日志通常会位于OS的缓存中,所以中继日志的开销很小
mysql读写分离原理
mysql读写分离的实现方式:
主从复制与读写分离实验拓扑,这里有三个身份授权验证的地方需要搞清楚
1)mysql数据库服务器master-slave身份验证,设置主从同步之间的身份授权验证
2)amoeba--->mysql,设置amoeba代理服务访问mysql服务的身份授权验证
3)client---->amoeba,设置前端客户client访问amoeba代理服务的身份授权验证
案例环境部署;
主机 操作系统 IP地址 安装软件
Master CentOS7 192.168.30.55 mysql-5.5.24.tar.gz
Slave1 CentOS7 192.168.30.10 mysql-5.5.24.tar.gz
Slave2 CentOS7 192.168.30.50 mysql-5.5.24.tar.gz
Amoeba CentOS6.5 192.168.30.15 jdk-6u14-linux-x64.bin, amoeba-mysql-binary-2.2.0.tar.gz
Client CentOS6.5 192.168.30.99 使用yum安装mysql进行远程测试
百度云盘免费提供安装包:
mysql-5.5.24.tar.gz:https://pan.baidu.com/s/1T3fEFotFL9jevFIOfQpOTA
jdk-6u14-linux-x64.bin:https://pan.baidu.com/s/1Y9HAPrSg2nVKeQbA-BTYmQ
amoeba-mysql-binary-2.2.0.tar.gz:https://pan.baidu.com/s/1ymFNDm84u5k09sEBE4SMMw
搭建mysql主从复制
建立时间同步环境,NTP时间同步协议图解:
1)主服务器master设置
yum install ntp -y
vim /etc/ntp.conf
server 127.127.30.0 //本地是时钟源//
fudge 127.127.30.0 stratum 8 //设置时间层级为8//service ntpd start
2)从节点slave上进行时间同步
yum install ntp ntpdate -y
service ntpd start
/usr/sbin/ntpdate 192.168.30.55 //进行时间同步//
所有的主机都关闭防火墙,关闭增强型功能
systemctl stop firewalld.service
setenforce 0
手工编译安装mysql数据库。在Master,Slave1,Slave2上安装。步骤如下:
(关于数据库mysql-5.5.24的安装步骤详解可以参考之前写过的文章”CentOS7LNMP架构部署“,下面只提供操作步骤)
1)编译安装mysql
yum -y install ncurses-devel cmake gcc gcc-c++ ncurses bison libaio-devel //ncurses是字符终端下屏幕控制的基本库//
tar xzvf mysql-5.5.24.tar.gz
cd mysql-5.5.24
cmake \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci \
-DWITH_EXTRA_CHARSETS=all \
-DSYSCONFDIR=/etc \
-DMYSQL_DATADIR=/home/mysql/ \
-DMYSQL_UNIX_ADDR=/home/mysql/mysql.sock \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_ARCHIVE_STORAGE_ENGINE=1 \
-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_SSL=system \
-DMYSQL_TCP_PORT=3306 \
-DENABLE_DOWNLOADS=1 \
-DWITH_SSL=bundled
make && make install
2)优化调整
cp support-files/my-medium.cnf /etc/my.cnf
cp support-files/mysql.server /etc/init.d/mysqld
chmod +x /etc/init.d/mysqld
chkconfig --add mysqld
chkconfig --level 35 mysqld on
echo "PATH=$PATH:/usr/local/mysql/bin/" >> /etc/profile
. /etc/profile (注意:"."后面有空格)
3)初始化数据库
useradd -s /sbin/nologin mysql
chown -R mysql.mysql /usr/local/mysql
/usr/local/mysql/scripts/mysql_install_db \
--user=mysql \
--ldata=/var/lib/mysql \
--basedir=/usr/local/mysql \
--datadir=/home/mysql
ln -s /var/lib/mysql/mysql.sock /home/mysql/mysql.sock
vi /etc/init.d/mysqld
basedir=/usr/local/mysql
datadir=/home/mysql
4)启动mysql服务,设置mysql用户密码
service mysqld start
mysqladmin -uroot -p password 'abc123'
mysql主服务器配置
在配置文件中修改或增加以下选项
vim /etc/my.cnf
server-id = 11 //修改id
log-bin=master-bin //增加主服务器日志文件//
log-slave-updates=true //增加从服务器更新二进制日志//service mysqld restart
登录mysql程序,给从服务器授权
grant replication slave on *.* to 'myslave'@'192.168.30.%' identified by 'abc123'; #进行授权
flush privileges; //刷新授权设置
其中file列显示日志名,position列显示偏移量,这两个值在后面配置从服务器的时候会用到。Slave应从该点在master上进行新的更新
mysql从服务器配置
在配置文件中修改或增加以下选项
vim /etc/my.cnf
[mysqld]
server-id = 22 #另一台id不一样
relay-log=relay-log-bin //从主服务器上同步日志文件记录到本地//
relay-log-index=slave-relay-bin.index //定义relay-log的位置和名称//
service mysqld restart
登录mysql配置同步
按主服务器结果更改下面命令中的master_log_file和master_log_pos的参数
change master to master_host='192.168.30.55',master_user='myslave',master_password='abc123',master_log_file='mysql-bin.000011',master_log_pos=267;
start slave; //启动同步
show slave status \G; //查看slave状态,确保以下两个值为yes
.............
Slave_IO_Running: Yes #这两个必须为yes
Slave_SQL_Running: Yes
验证主从复制效果
1)在主,从服务器上登录mysql,查看数据库,
2)在 主服务器上新建数据库school, 在主,从服务器上分别查看数据库,都可以看到master新建的数据库school,则主从复制成功
搭建mysql读写分离
amoeba服务器配置
(1)在主机amoeba上安装java环境
因为amoeba是基于jdk1.5开发的,所以官方推荐使用jdk1.5或1.6版本,高版本不建议使用。
service iptables stop
setenforce 0
cp jdk-6u14-linux-x64.bin /usr/local/
./jdk-6u14-linux-x64.binyes
按entermv jdk1.6.0_14/ /usr/local/jdk1.6
(2)添加java环境变量
vi /etc/profile
export JAVA_HOME=/usr/local/jdk1.6
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/binsource /etc/profile
(3)安装并配置amoeba软件
mkdir /usr/local/amoeba
tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
chmod -R 755 /usr/local/amoeba/
/usr/local/amoeba/bin/amoeba
显示amoeba start|stop说明安装成功
(4)配置amoeba读写分离,两个slave读负载均衡
在master,slave1,slave2上登录mysql添加权限开放给amoeba访问
grant all on *.* to test@'192.168.30.%' identified by '123.com';
(5)回到amoeba服务器,编辑amoeba.xml配置文件,设置前端客户client访问amoeba代理服务的身份授权验证
cd /usr/local/amoeba修改后的内容为带加粗的部分,注意删除注释
vim conf/amoeba.xml---30行--
<property name="user">amoeba</property>
----32行---------
<property name="password">123456</property>---117-去掉注释-
<property name="defaultPool">master</property>
<property name="writePool">master</property>
<property name="readPool">slaves</property>
编辑dbServers.xml 配置文件,设置amoeba代理服务访问mysql服务的身份授权验证
vim conf/dbServers.xml
--26-29--去掉注释--
<property name="user">test</property>
<property name="password">123.com</property>-----42-主服务器地址---
<dbServer name="master" parent="abstractServer">
<property name="ipAddress">192.168.30.55</property>
--52-从服务器主机名-
<dbServer name="slave1" parent="abstractServer">
--55-从服务器地址-
<property name="ipAddress">192.168.30.10</property><dbServer name="slaves" virtual="true">
<poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">--末尾--
<property name="poolNames">slave1,slave2</property>
</poolConfig>配置无误后,可以启动amoeba软件,其默认端口为tcp 8066
/usr/local/amoeba/bin/amoeba start&
netstat -anpt | grep java
测试实验结果
在Client主机上进行测试
yum install -y mysql
mysql -u amoeba -p123456 -h 192.168.30.15 -P8066 //通过amoeba代理访问mysql
在master上创建一个表info,同步到各从服务器上,然后关闭各从服务器的slave功能,再插入区别语句
在master上
mysql> use school;
mysql> create table info (id int,name char(10));
mysql> insert into info values (1,'master');
从服务器slave2
mysql> stop slave;
mysql> insert into info values (3,'slave2');
从服务器slave1
mysql> stop slave;
mysql> insert into info values (2,'slave1');
测试读操作
在client上第一次查询结果
mysql> select * from info;
+------+--------+
| id | name |
+------+--------+
| 2 | slave1 |
+------+--------+
1 row in set (0.02 sec)第二次查询结果
mysql> select * from info;
+------+--------+
| id | name |
+------+--------+
| 3 | slave2 |
+------+--------+
1 row in set (0.00 sec)第三次查询结果
mysql> select * from info;
+------+--------+
| id | name |
+------+--------+
| 2 | slave1 |
+------+--------+
1 row in set (0.02 sec)
测试写操作
在client主机上插入一条语句
mysql> insert into info values (4,'client');
Query OK, 1 row affected (0.01 sec)
但在client,slave1,slave2上查询不到,最终只有在master上才能查看到这条语句内容,说明写操作在master服务器上
由此验证,已经实现了mysql读写分离,目前所有的写操作全部在master主服务器上,用来避免数据的不同步;所有的读操作都分摊给了slave从服务器,用来分担数据库的压力。