部署Mysql主从复制,读写分离
一、MySQL主从复制,读写分离概述
在实际的生产环境中,如果对数据库的读写都在同一个数据库服务器中操作,无论是在安全性、高可用性还是高并发等各个方面都是完全不能满足实际需求的,因此,一般来说都是通过主从复制(Master–Slave)的方式来同步数据,再通过读写分离来提升数据库的并发负载能力这样的方案来进行部署与实施的。
MySQL数据库自身提供的主从复制功能可以方便的实现数据的多处自动备份,实现数据库的拓展。多个数据备份不仅可以加强数据的安全性,通过实现读写分离还能进一步提升数据库的负载性能。
如图所示,一台主 MySQL 服务器带两台从 MySQL 服务器做数据复制,前端应用在进行数据库写操作时,对主服务器进行操作,在进行数据库读操作时,对两台从服务器进行操作,这样大量减轻了对主服务器的压力。
客户机写入数据时,Amoeba 会将数据路由到 Master 上进行存储,客户机读取数据时,Amoeba会将读的请求一轮询的方式发给slaves组,实现读写分离。
Master 和 Slaves 间配置了主从复制,保证了数据的一致性。
二、准备工作
主机名 | 操作系统 | IP地址 |
---|---|---|
Master | Centos7 | 192.168.1.1 |
Slave1 | Centos7 | 192.168.1.2 |
Slave2 | Centos7 | 192.168.1.3 |
Amoeba | Centos7 | 192.168.1.4 |
Client | Centos7 | 192.168.1.5 |
当做读写分离的时候才需要对Amoeba做操作,做读写分离前提需要搭建主从复制
实验要用到的软件包从下面链接下载:
https://pan.baidu.com/s/1ZzgOI339r_bj_FZlYkkHnA
提取码:wlks
1.搭建时间服务器
1)主master上安装ntp时间服务
挂载光盘,并配置yum源
[root@Master ~]# yum -y install ntp
[root@Master ~]# sed -i '/^server/s/^/#/g' /etc/ntp.conf
[root@Master ~]# cat <<END >>/etc/ntp.conf
server 127.127.1.0
fudge 127.127.1.0 stratum 8
END
[root@Master ~]# systemctl restart ntpd #重启ntpd
[root@Master ~]# systemctl enable ntpd #设置开机自启
[root@Master ~]# netstat -anpu | grep ntp #查看状态
2)在两台从slave同步时间
挂光盘,并配置yum源
[root@Slave1 ~]# yum -y install ntpdate
[root@Slave1 ~]# /usr/sbin/ntpdate 192.168.1.1
2.安装MySQL数据库
Master和两台Slave操作一致
[root@Master ~]# yum -y install ncurses-devel
[root@Master ~]# ls
anaconda-ks.cfg cmake-2.8.6.tar.gz mysql-5.6.36.tar.gz
[root@Master ~]# tar zxf cmake-2.8.6.tar.gz -C /usr/src/
[root@Master ~]# cd /usr/src/cmake-2.8.6/
[root@master cmake-2.8.6]# ./configure && gmake && gmake install
解压 MySQL 软件包,并进行配置,编译,安装
[root@Master ~]# tar zxf mysql-5.6.36.tar.gz -C /usr/src/
[root@Master ~]# cd /usr/src/mysql-5.6.36/
[root@Master ~]# cmake \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci \
-DWITH_EXTRA_CHARSETS=all \
-DSYSCONFDIR=/etc/ && make && make install
1)复制配置文件
[root@Master mysql-5.6.36]# rm -rf /etc/my.cnf
[root@Master mysql-5.6.36]# cp support-files/my-default.cnf /etc/my.cnf
2)添加为系统服务
[root@Master mysql-5.6.36]# cp support-files/mysql.server /etc/rc.d/init.d/mysqld
[root@Master mysql-5.6.36]# chmod +x /etc/rc.d/init.d/mysqld
[root@Master mysql-5.6.36]# chkconfig --add mysqld #设置为系统服务
[root@Master mysql-5.6.36]# chkconfig mysqld on #设置为开启自启
3)优化PATH路径,执行命令时方便,单引号双引号都行
[root@Master ~]# echo "export PATH=$PATH:/usr/local/mysql/bin" >>/etc/profile
[root@Master ~]# source /etc/profile #执行文件
4)初始化MySQL,创建用户,赋权
[root@Master ~]# useradd -M -s /sbin/nologin mysql #创建用户
[root@Master ~]# chown -R mysql:mysql /usr/local/mysql #赋权
[root@Master ~]# /usr/local/mysql/scripts/mysql_install_db --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data --user=mysql
5)启用MySQL数据库,并设置密码
主从密码一致即可
[root@Master ~]# /etc/init.d/mysqld start #启用mysql数据库
[root@Master ~]# mysqladmin -u root password '123' #设置密码为123
三、MySQL主从复制
MySQL 主从复制是指数据可以从一个 MySQL 数据库服务器主节点复制到一个或多个从节点。MySQL 默认采用异步复制方式,这样从节点不用一直访问主服务器来更新自己的数据,数据的更新可以在远程连接上进行,从节点可以复制主数据库中的所有数据库或者特定的数据库,或者特定的表。
1.MySQL主从复制的原因
MySQL 服务器的抗压能力有限。假设一台服务器最多能够接受的并发请求数是500个。当并发超过500的时候,很显然一台服务器就不能正常工作了,就需要更多的服务器来支持。保证服务器之间的数据及时同步,需要使用主从的技术解决方案实现数据同步。
2.MySQL主从复制原理
MySQL 的主从复制和MySQL 的读写分离 两者有着紧密联系,首先要部署主从复制,只有主从复制完成了,才能在此基础上进行数据的读写分离。
1)MySQL支持的复制类型
- 基于语句的复制:在主服务器上执行 SQL 语句,在从服务器上执行同样的语句。MySQL 默认采用基于语句的复制,效率比较高。
- 基于行的复制:把改变的内容复制过去,而不是把命令在从服务器上执行一遍。
- 混合类型的复制:默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制。
2)MySQL复制的工作过程
- 在每个事务更新数据完成之前,Master 在二进制日志记录这些改变。写入二进制日志完成后,Master 通知存储引擎提交事务。
- Slave 将 Master 的 Binary log 复制到其 中继日志。首先,Slave 开始一个工作线程—— I/O 线程,I/O 线程在 Master 上打开一个普通的连接,然后开始 Binlog dump process。Binlog dump process 从 Master 的二进制日志中读取事件,如果已经跟上 Master,它会睡眠并等待 Master 产生新的事件,I/O 线程将这些事件写入中继日志。
- SQL slave thread(SQL 从线程)处理该过程的最后一步。SQL 线程从中继日志读取事件,并重放其中的事件而更新 Slave 的数据,使其与 Master 中的数据一致。只要该线程与 I/O 线程保存一致,中继日志通常会位于 OS 的缓存中,所以中继日志的开销很小。
3.部署MySQL主从复制
1)主服务器配置
[root@Master ~]# vi /etc/my.cnf #修改mysql主配置文件
在 [mysqld] 下面添加:
server-id = 11
log-bin=master-bin #主服务器日志文件
log-slave-updates=true #从服务器更新二进制文件
[root@Master ~]# /etc/init.d/mysqld restart #重启mysql数据库
注意:如果Mysql重启较慢,可以使用kill终止掉mysql进程号,再启用
2)登陆MySQL,给从服务器权限
[root@Master ~]# mysql -u root -p123
赋予slave复制的权限:
mysql> grant replication slave on *.* to 'myslave'@'%' identified by '123';
mysql> flush privileges; #刷新权限
mysql> show master status; #查看master状态
3)从服务器配置
两台从服务器操作一致
[root@Slave1 ~]# vim /etc/my.cnf
在[mysqld]下添加:
server-id = 22
relay-log=relay-log-bin #将主服务器上同步日志文件记录到本地
relay-log-index=slave-relay-bin.index #定义relay-log的位置和名称
[root@Slave1 ~]# /etc/init.d/mysqld restart #重启mysqld服务
[root@Slave1 ~]# mysql -u root -p123
mysql> change master to
master_host='192.168.1.1',
master_user='myslave',
master_password='123',
master_log_file='master-bin.000001',
master_log_pos=400;
mysql> start slave; #启用从服务器同步功能
mysql> show slave status\G; #查看从服务器状态
这是一个易错点
当在主Mysql开启日志,并在从Mysql开启日志后,进行同步时
明明没有报错但还是同步失败
- 原因是从在向主同步时,File的及Position的值给的不对
解决方案:
先关闭slave,在重新向主服务器同步一下,将对的值写入即可
4)验证数据库是否同步
- 在主MySQL创建库
mysql> create database ceshi;
mysql> show databases;
2. 分别在两个从服务器进行查看,同步过来说明主从复制成功
mysql> show databases;
四、MySQL读写分离
为了确保数据库产品的稳定性,很多数据库拥有双机热备功能。也就是,第一台数据库服务器,是对外提供增删改业务的生产服务器;第二台数据库服务器,主要进行读的操作。
1.读写分离的原因
在开发工作中,有时候会遇见某个sql 语句需要锁表,导致暂时不能使用读的服务,这样就会影响现有业务,使用主从复制,让主库负责写,从库负责读,这样,即使主库出现了锁表的情景,通过读从库也可以保证业务的正常运作。
2.读写分离原理
简单来说,读写分离就是只在主服务器上写,只在从服务器上读。基本的原理是让主数据库处理事务性查询,而从数据库处理 select 查询。数据库复制被用来把事务性查询导致的变更同步到群集中的从数据库。
目前较为常见的 MySQL 读写分离分为两种。
- 基于程序代码内部实现:
在代码中根据 select、insert 进行路由分类,这类方法也是目前生产环境应用最广泛的。优点是性能较好,因为在程序代码中实现,不需要增加额外的设备作为硬件开支;缺点是需要开发人员来实现,运维人员无从下手。
- 基于中间代理层实现:
代理一般位于客户端和服务器之间,代理服务器接到客户端的请求后通过判断后转发到后端数据库,有两个代表性程序。
- MySQL-Proxy:MySQL-Proxy 为 MySQL 开源项目,通过其自带的 lua 脚本进行 SQL 判断,虽然是 MySQL 官方产品,但是 MySQL 官方并不建议将 MySQL-Proxy 用到生产环境。
- Amoeba(变形虫):由陈思儒开发,其曾就职于阿里巴巴。该程序用 Java 语言进行开发,阿里巴巴将其用于生产环境。它不支持事务和存储过程。
3.部署MySQL读写分离
1)在Amoeba上搭建java环境
挂光盘,并配置yum源
[root@Amoeba ~]# yum -y remove java #删除掉默认安装的java
[root@Amoeba ~]# rz #上传软件包 #如果没有rz工具需 yum -y install lrzsz 安装
z waiting to receive.**B0100000023be50
[root@Amoeba ~]# ls
amoeba-mysql-binary-2.2.0.tar.gz anaconda-ks.cfg jdk-6u14-linux-x64.bin
[root@Amoeba ~]# chmod +x jdk-6u14-linux-x64.bin #添加可执行权限
[root@Amoeba ~]# ./jdk-6u14-linux-x64.bin
一直按空格,等显示输入 yes 或 no 时输入-------- yes
[root@Amoeba ~]# mv jdk1.6.0_14/ /usr/local/jdk1.6
[root@Amoeba ~]# vim /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/bin
[root@Amoeba ~]# source /etc/profile #执行该脚本
[root@Amoeba ~]# java -version #查看java版本
2)编译安装Amoeba软件
[root@Amoeba ~]# mkdir /usr/local/amoeba #为amoeba创建目录
[root@Amoeba ~]# tar zxf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
[root@Amoeba ~]# chmod -R 755 /usr/local/amoeba/
[root@Amoeba ~]# /usr/local/amoeba/bin/amoeba
显示:amoeba start | stop 表示正确
3)配置Amoeba读写分离,两个Slave读负载均衡
- 数据授权给amoeba读写权限,因为刚刚做了主从复制,所以直接在主Mysql做就行
mysql> grant all on *.* to 'zhangsan'@'192.168.1.%' identified by '123.com';
mysql> show grants for 'ly'@'192.168.1.%';
- 修改Amoeba配置文件
[root@Amoeba ~]# vim /usr/local/amoeba/conf/amoeba.xml
- 编辑dbServers.xml配置文件
[root@Amoeba ~]# vim /usr/local/amoeba/conf/dbServers.xml
- 启动Amoeba软件,端口为8066
[root@Amoeba ~]# /usr/local/amoeba/bin/amoeba start &
[root@Amoeba ~]# netstat -anpt | grep java
4)测试读写分离
- 验证主从复制
在客户机上操作:
挂光盘,并配置yum源
[root@client ~]# yum -y install mysql #直接使用yum安装mysql就行
[root@client ~]# mysql -u amoeba -p123456 -h 192.168.1.140 -P8066 #远程登陆amoeba的数据库
MySQL [(none)]> create database zhangsan;
MySQL [(none)]> create table zhangsan.test (id int(10),name varchar(10),address varchar(20));
在从Mysql上查看结果:
[root@Slave1 ~]# mysql -u root -p123
mysql> use zhangsan
mysql> show tables;
- 分别关闭slave1,2的复制功能
mysql> stop slave;
- 在master,slave上创建不同的数据
master:
slave1:
slave2:
- 在客户端上验证读:
- 客户端上验证写
master: