分类: LINUX
2018-09-05 09:20:38
通过amoeba实现mysql 读写分离
Mysql作为目前世界上使用最广泛的免费数据库,相信我们都有所了解。但在实际的生产环境中,由单台Mysql作为独立的数据库是完全不能满足实际需求的,无论是在安全性,高可用性以及高并发等各个方面。因此,一般来说都是通过 主从复制(Master-Slave)的方式来同步数据,再通过读写分离(MySQL-Proxy)来提升数据库的并发负载能力 这样的方案来进行部署与实施的。为了确保数据库产品的稳定性,很多数据库拥有双机热备功能。也就是,第一台数据库服务器,是对外提供增删改业务的生产服务器;第二台数据库服务器,主要进行读的操作。
读写分离的原理:
让主数据库(master)处理事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库(slave)处理SELECT查询操作。
2、为什么使用读写分离
为了确保数据库产品的稳定性,很多数据库拥有双机热备功能。也就是,第一台数据库服务器,是对外提供增删改查业务的生产服务器;第二台数据库服务器,仅仅接收来自第一台服务器的备份数据(注意,不同数据库产品,第一台数据库服务器,向第二台数据库服务器发送备份数据的方式不同)。当第一台数据库崩溃后,第二台数据库服务器,可以立即上线来代替第一台数据库服务器,并且,在第一台数据库服务器崩溃后,宝贵的数据,依然会存在于第二台数据库服务器里(根据目前业界的备份数据发送方式来看,当第一台数据库崩溃后,第一台数据库里的仍然会有少量的新数据,没能来得及被发送到第二台数据库服务器,所以,这部分数据就丢失了)。
一般来说,为了配置方便,以及稳定性,这两台数据库服务器,都用的是相同的配置(思考一下,如果两台服务器的配置不同,会导致什么结果)。
在实际运行中,第一台数据库服务器的压力,远远大于第二台数据库服务器。因此,很多人希望合理利用第二台数据库服务器的空闲资源。那么,第二台数据库服务器能做些什么事情呢?
从数据库的基本业务来看,数据库的操作无非就是增删改查这4个操作。但对于“增删改”这三个操作,如果是双机热备的环境中做,一台机器做了这三个操作的某一个之后,需要立即将这个操作,同步到另一台服务器上。单向的同步,不复杂。但如果两台机器都需要向对方进行同步,那逻辑就非常复杂,而且还会大大降低性能。(从保证ACID特性的角度,思考一下为什么双向同步会非常复杂且低性能?而单向同步却不会?)出于这个原因,第二台备用的服务器,就只做了查询操作。进一步,为了降低第一台服务器的压力,干脆就把查询操作全部丢给第二台数据库服务器去做,第一台数据库服务器就只做增删改了。
到这一步,就实现了所谓的读写分离。这样做,缺点也非常明显了。本来第二台数据库服务器,是用来做热备的,它就应该在一个压力非常小的环境下,保证运行的稳定性。而读写分离,却增加了它的压力,也就增加了不稳定性。因此,读写分离,实质上是一个在资金比较缺乏,但又需要保证数据安全的需求下,在双机热备方案上,做出的一种折中的扩展方案。
3、实现MySQL主从读写分离的方案
(1)通过程序实现读写分离(性能和效率最佳,推荐)
PHP和Java程序都可以通过设置多个连接文件轻松地实现对数据库的读写分离,即当语句关键字为select时,就去连接读库的连接文件,若为update、insert、delete时,则连接写库的连接文件。
通过程序实现读写分离的缺点就是需要开发人员对程序进行改造,使其对下层不透明,但是这种方式更容易开发和实现,适合互联网业务场景。
通过开源的软件实现读写分离
MySQL-proxy、Amoeba等代理软件也可以实现读写分离功能,这些软件的稳定性和功能一般,不建议生产使用。绝大多数公司常用的还是在应用端开发程序实现读写分离。
大型门户独立开发DAL层综合软件
百度、阿里等大型门户都有牛人开发,会花大力气开发合适自己业务的读写分离、负载均衡、监控报警、自动扩容、自动收缩等一系列功能的DAL层软件。
MySQL读写分离
--------client--------------amoeba-------------主MySQL----------------从MySQL------------从MySQL---------
192.168.1.10 192.168.1.100 192.168.1.200 192.168.1.201 192.168.1.202
构建步骤:
一、在amoeba服务器中:
安装java环境
1、安装java
[root@localhost ~]# chmod +x jdk-6u14-linux-x64.bin
[root@localhost ~]# ./jdk-6u14-linux-x64.bin //输yes,按回车
[root@localhost ~]# mv jdk1.6.0_14/ /usr/local/java
[root@localhost ~]# rm -rf /usr/bin/java //删除原有的java
[root@localhost ~]# rm -rf /usr/bin/javac //删除原有的javac
[root@localhost ~]# ln -s /usr/local/java/bin/* /usr/bin/java 没有mkdir创建jav
[root@localhost ~]# 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/bin:$PATH:$JAVA_HOME/bin
export AMOEBA_HOME=/usr/local/amoeba
export PATH=$PATH:$AMOEBA_HOME/bin
[root@localhost ~]# source /etc/profile
[root@localhost ~]# java -version
[root@localhost ~]# java -version
java version "1.6.0_14"
Java(TM) SE Runtime Environment (build 1.6.0_14-b08)
Java HotSpot(TM) 64-Bit Server VM (build 14.0-b16, mixed mode)
2、安装amoeba(变形虫)
[root@localhost ~]# mkdir /usr/local/amoeba
[root@localhost ~]# tar -zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
[root@localhost ~]# chmod 755 /usr/local/amoeba/ -R
[root@localhost ~]# /usr/local/amoeba/bin/amoeba //验证amoeba是否安装成功
[root@localhost ~]# /usr/local/amoeba/bin/amoeba start & //启动amoeba
[root@localhost ~]# netstat -anpt | grep java
3、配置Amoeba(实现读写分离,两个Slave读负载均衡)
1)主MySQL服务器、从MySQL服务器(3台)开放权限
[root@localhost ~]# mysql -u root -p redhat
mysql> grant all on *.* to 'root'@'192.168.1.%' identified by 'redhat';
mysql> flush privileges; 主 从 从都要给权限
2)修改amoeba配置文件
[root@localhost ~]# vim /usr/local/amoeba/conf/amoeba.xml
修改:
3)修改dbServer.xml配置文件
[root@localhost ~]# vim /usr/local/amoeba/conf/dbServers.xml
修改:
...部分省略....
wq!
[root@localhost ~]# /usr/local/amoeba/bin/amoeba stop
[root@localhost ~]# /usr/local/amoeba/bin/amoeba start & 后台运行
[root@localhost ~]# netstat -anpt | grep java 检测
二、MySQL数据库服务器中(三台):
1、在主数据库上安装ntp时间服务
[root@localhost ~]# yum -y install ntp
[root@localhost ~]# vim /etc/ntp.conf
添加:
server 127.127.1.0
fudge 127.127.1.0 stratum 8
[root@localhost ~]# service ntpd restart
2、在从数据库上安装ntp时间服务
[root@localhost ~]# yum -y install ntpdate
[root@localhost ~]# ntpdate 192.168.1.1
3、安装MySQL服务(三台数据库服务器安装保持一致)
1)安装cmake软件
[root@localhost ~]# tar -zxvf cmake-2.8.6.tar.gz -C /usr/src/
[root@localhost ~]# cd /usr/src/cmake-2.8.6/
[root@localhost cmake-2.8.6]# ./configure && gmake && gmake install
2)安装mysql软件
[root@localhost ~]# tar -zxvf mysql-5.5.22.tar.gz -C /usr/src/
[root@localhost ~]# cd /usr/src/mysql-5.5.22/
[root@localhost mysql-5.5.22]# cmake -
DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DDEFAULT_CHARSET=utf8 -
DDEFAULT_COLLATION=utf8_general_ci -DSYSCONFDIR=/etc -
DWITH_EXTRA_CHARSETS=all
[root@localhost mysql-5.5.22]# make && make install
[root@localhost ~]# cp /usr/src/mysql-5.5.22/support-files/my-
medium.cnf /etc/my.cnf
[root@localhost ~]# cp /usr/src/mysql-5.5.22/support-files/mysql.server
/etc/init.d/mysqld
[root@localhost ~]# chmod +x /etc/init.d/mysqld
[root@localhost ~]# chown -R mysql:mysql /usr/local/mysql
[root@localhost ~]# ln -s /usr/local/mysql/bin/* /usr/local/bin/
[root@localhost ~]# /usr/local/mysql/scripts/mysql_install_db --
user=mysql --basedir=/usr/local/mysql/ --datadir=/usr/local/mysql/data/
[root@localhost ~]# service mysqld restart
[root@localhost ~]# chkconfig --add mysqld
[root@localhost ~]# chkconfig mysqld on
验证:
[root@localhost ~]# mysqladmin -u root password 'redhat'
[root@localhost ~]# mysql -u root -p
4、主从配置
1)主数据库服务器配置
[root@localhost ~]# vim /etc/my.cnf
添加:
server-id=11 //修改
log-bin=master-bin //修改
log-slave-updates=true //添加
[root@localhost ~]# service mysqld restart
[root@localhost ~]# mysql -u root -p
mysql> grant replication slave on *.* to 'slave'@'192.168.1.%' identified by 'redhat';
mysql> flush privileges;
mysql> show master status;
mysql> quit
2)从数据库服务器配置
[root@localhost ~]# vim /etc/my.cnf
添加:
server-id=22 //修改
relay-log=relay-log-bin //添加
relay-log-index=slave-relay-bin.index //添加
注意:主—从的ID不能相同。
[root@localhost ~]# service mysqld restart
[root@localhost ~]# mysql -u root -p
mysql> change master to
master_host='192.168.1.200',
master_user='slave',
master_password='redhat',
master_log_file='master-bin.000001',
master_log_pos=336;
mysql> start slave;
mysql> show slave status\G; //结尾不能加; 否则或报错。
Slave_IO_Running: Yes //确保为YES
Slave_SQL_Running: Yes //确保为YES
mysql> quit
问题说明:
1、如果出现ERROR: No query specified
则:原因是语法错误,去掉语句后的;号。
2、如果bin-log日志不更新,或者无法进行数据同步,
则:删除bin-log日志,重新启动服务即可。
3、导致lave_IO_Running 为connecting 的原因主要有以下 3 个方面:
1)网络不通
2)密码不对
3)pos不对
4、验证:
1)主数据库服务器:
[root@localhost ~]# mysql -u root -p
mysql> show databases;
mysql> create database masterdb;
mysql> show databases;
mysql> use masterdb;
mysql> create table count (id int(5),name char(12));
mysql> show tables;
mysql> quit
2)从数据库服务器:
[root@localhost ~]# mysql -u root -p
mysql> show databases;
mysql> show databases;
mysql> use masterdb
mysql> show tables;
mysql> quit
三、验证:
1、在client上:
[root@localhost ~]# mysql -u amoeba -predhat -h 192.168.1.100 -P8066
mysql> use masterdb;
mysql> create table biao1 (id int(5),name char(10),address char(10));
2、在主MySQL服务器上:
mysql> insert into biao1 values(1,'hehe','master');
3、在2台从MySQL服务器上:
slave1:
mysql> stop slave;
mysql> insert into biao1 values(2,'hehe','slave1');
slave2:
mysql> stop slave;
mysql> insert into biao1 values(3,'hehe','slave2');
4、在客户端测试:
查询biao1:
mysql> select * from biao1;
+------+------+---------+
| id | name | address |
+------+------+---------+
| 1 | hehe | slave1 |
+------+------+---------+
1 row in set (0.00 sec)
mysql> select * from biao1;
+------+------+---------+
| id | name | address |
+------+------+---------+
| 3 | hehe | slave2 |
+------+------+---------+
1 row in set (0.00 sec)
mysql> select * from biao1;
+------+------+---------+
| id | name | address |
+------+------+---------+
| 2 | hehe | slave1 |
+------+------+---------+
1 row in set (0.00 sec)
mysql> select * from biao1;
+------+------+---------+
| id | name | address |
+------+------+---------+
| 3 | hehe | slave2 |
+------+------+---------+
1 row in set (0.01 sec)
查到记录,说明记录分别从两台从MySQL数据库读取
插入一条记录:
mysql> insert into biao1 values(4,'hehe','write_zhu');
Query OK, 1 row affected (0.01 sec)
mysql> select * from biao1;
+------+------+---------+
| id | name | address |
+------+------+---------+
| 3 | hehe | slave2 |
+------+------+---------+
1 row in set (0.01 sec)
mysql> select * from biao1;
+------+------+---------+
| id | name | address |
+------+------+---------+
| 2 | hehe | slave1 |
+------+------+---------+
1 row in set (0.01 sec)
没有查到记录,说明这条记录只写入主MySQL数据库中
错误代码2006解决方案
mysql> set global max_allowed_packet=1024*1024*16;