MySQL主从复制、Amoeba读写分离

壹、主从复制

备份

  1. 冷备份,手动的执行dump(mysql导出纯文件sql语句,oracle是dump二进制,大字段)
  2. 热备份,自动定时的执行job。(全量)每个1天,习惯凌晨2点,1小时(增量)
  3. 实时备份,mysql自身支持

一、 主从复制工作原理

主从复制工作原理

  1. 必须两台服务器,master主服务器,slave从服务器
  2. 在主服务器,开启二进制日志写,动态写一个二进制日志文件log-bin。写类型SQL语句(创建表,修改表结构,insert/update/delete)(默认:关闭)
  3. 从服务器开启两个线程:I/O线程:从主服务器上读取二进制日志文件,从中读取同步的SQL语句,然后写入本地的中继日志RelayLog;SQL线程:读取本地的中继日志,然后执行这些SQL语句,写入数据库。
  4. 编程:功能高聚合,单一。两个线程并发,互相影响小。

二、配置步骤

  1. Linux+PersonaMysql(mysql5.5分支)微信16.10开源mysql集群(数据一致性)基于persona
  2. 复制master虚拟机,编程slave
  3. 主my.cnf,开启二进制日志配置,server-id=1
  4. 从my.cnf,server-id=2;复制的节点auto.cnf就是一个uuid,修改下;找到master需要6个参数:ip+port+username+password+bin-log+pos(show master status)挂钩change master to。。。启动从服务
  5. 验证:show slave status,两个YES出现即可,如果不是两个没有配置成功,重新配置即可

安装mysql看另一篇,此处略:
http://blog.csdn.net/Donzch/article/details/78948229

三、虚拟机配置MySQL主从服务器

开启多个CentOS虚拟机

1.配置主服务器

设置静态ip

编辑主master服务器配置文件/etc/my.cnf
在[mysqld]节点下加入两句话
server-id=1
log-bin=mysql-bin #启用二进制日志;

打开端口
/sbin/iptables -I INPUT -p tcp –dport 3306 -j ACCEPT
修改生效
/etc/rc.d/init.d/iptables save
查看配置
/etc/init.d/iptables status

启动服务
service mysql start

登录mysql:mysql –uroot -proot

开启远程访问权限:
语法:
grant [权限] on [数据库名].[表名] to [‘用户名’]@[‘web服务器的ip地址’] identified by [‘密码’];

mysql> grant all on . to ‘root’@’%’ identified by ‘root’;
Query OK, 0 rows affected (0.00 sec)
service mysql restart #重启服务

2.配置从服务器

设置静态ip

修改/etc/my.cnf增加一行
server-id=2

然后找到uuid修改uuid,主从uuid不能一样,如果要求格式,想办法生成一个uuid,只要 和主不一样就行了
uuid

打开端口
/sbin/iptables -I INPUT -p tcp –dport 3306 -j ACCEPT
修改生效
/etc/rc.d/init.d/iptables save

这里我是新装的CentOS7_1708(不是CentOS7的就忽略这段代码)
报错!
-bash: /etc/rc.d/init.d/iptables: No such file or directory
显示没有这个文件
因为CentOS7 防火墙不是这样设置的(如果是CentOS7以下所有端口都按次方式开启)

查询端口号是否开启:
firewall-cmd --query-port=3306/tcp
查询端口号3306 是否开启!

开启永久端口号:
firewall-cmd --add-port=3306/tcp --permanent
这里把3306替换为需要开的端口号, --permanent是指永久的意思。

一行命令开多个端口号:
开启永久端口号:firewall-cmd --add-port=3306/tcp --permanent&&firewall-cmd --add-port=3307/tcp --permanent

查看配置
/etc/init.d/iptables status

启动服务
service mysql start

在主服务器查询
show master status;
这里写图片描述

通过mysql命令配置同步日志的指向:

changemastertomaster_host=’192.168.166.10’,master_port=3306,master_user=’root’,master_password=’root’,master_log_file=’mysql-bin.000001’,master_log_pos=120;

master_host 主服务器的IP地址
master_port 主服务器的PORT端口
master_log_file 和主服务器show master status中的File字段值相同
master_log_pos 和主服务器show master status中的Position字段值相同

start slave; #stop slave;停止服务,出错时先停止,再重新配置
show slave status\G; #查看SLAVE状态,\G结果纵向显示。必须大写
这里写图片描述

开启远程访问权限:
语法:
grant [权限] on [数据库名].[表名] to [‘用户名’]@[‘web服务器的ip地址’] identified by [‘密码’];

mysql> grant all on . to ‘root’@’%’ identified by ‘root’;
Query OK, 0 rows affected (0.00 sec)

#mysql>flush tables with read lock; #数据库锁表,不让写数据
#mysql>showmasterstatus; #查看MASTER状态(这两个值File和Position)
#mysql>unlock tables; #从启动好后,记得要解除锁定

3.测试主从复制

在主服务器上创建一个数据库,过几秒在从服务器上再查询一下,发现从服务器也出现了这个数据库。

测试主从复制

主库增删改查,从库也跟着增删改查

主从复制的缺点

  1. 主从复制,从节点如果改变了数据,就会造成数据的不一致。数据的一致性就被破坏。
    Error ‘Duplicate entry ‘4’ for key ‘PRIMARY” on query. Default database: ‘aaa’. Query: ‘insert into aaa.t1(t1,t2) values ( NULL,’444’)’
    冲突后,从服务无法继续执行。
    如果是写的操作只能写主库,从库不许写操作,
  2. 事务,海量数据insert,这种业务不适合搭建主从复制。
  3. 多个从,10+100+,3台以内(一主二从/一组一中)。

分布式数据库,事务不是很好解决,只能打补丁,允许业务的一定延迟,不是一个强一致性的,而是满足最终一致性。

订单,MQ消息队列,提醒:您的订单已经成功,请稍后查询您的订单,如果有问题,随时拨打客服电话。

说明,没有真正入库,在消息队列中。

重新配置

1) 把主库全量备份,从库删除之前的,然后执行source demo.sql。第一次必须全库还原一次。
2) 停止从服务
3) 重新配置,同步的文件位置发生变化,重新定位

在主服务器查询
show master status;

master_log_file和master_log_pos可能会改变,必须先查然后下面再配置

这里写图片描述

changemastertomaster_host=’192.168.166.10’,master_port=3306,master_user=’root’,master_password=’root’,master_log_file=’mysql-bin.000001’,master_log_pos=120;

start slave;

四、一主两从(一主多从类似)

一组多从

主从从方式无法实现:运行时,有个特殊的情况下,数据不会更新。master的有写入的操作,slave1跟着变化,但是slave2不会变。
如果slave1有写入操作,slave2会变化。

slave1是在什么时候才会去写二进制日志文件,人工(程序)操作。

一主多从方式能实现:再按原来的方法配置一个从服务器即可

停掉slave1的mysql服务,克隆这个slave1虚拟机,新增一个slave2的虚拟机

然后停掉mysql的服务,再启动
ps -ef|grep mysql
kill …
service mysql start

登录mysql
mysql -uroot -proot

检查从节点状态:
show slave status\G;

这里写图片描述

vim /etc/my.cnf
将server.id=2
改为server.id=3

vim /var/lib/mysql/auto.cnf
将uuid换一个,可以试试最后一个数字改动一下,不行就想办法生成uuid

然后打开3306端口
略。。

配置完成后重启mysql服务

登录mysql
mysql -uroot -proot
配置
changemastertomaster_host=’192.168.166.10’,master_port=3306,master_user=’root’,master_password=’root’,master_log_file=’mysql-bin.000001’,master_log_pos=2753;

启动从服务
start slave;

检查从节点状态:
show slave status\G;

测试一主两从

在住数据库中新建一个数据库,刷新看两个从服务器是否也更新,更新就证明没问题了

主从复制引出读写分离

主从的复制,实现了数据实时的备份,不再担心数据丢失,数据就安全了。但是从1,从2这两台跟服务器没有得到充分利用。如果主服务器不坏的情况,这两台没太大作用。
在实际项目部署时,数据库所用的服务器是最好的,把两个最好的服务器闲置,资源及其浪费。

在主从复制基础上,有多台机器,来实现一个读写分离。master负责写操作,所有的slave节点都复制读操作,当然如果写的操作比较少,也让master负责少量的读操作。

优点:
1. 资源得到充分利用
2. 并发能力提升,a.服务器数量增加 b.读操作(不加事物,写操作不能并行,读的操作不影响写的操作)
总结:读写分离目标:提高性能。

贰、Amoeba读写分离

最常见在mysql层实现读写分离

1. MySQL Proxy+(Linux Shell)python,业界很少用
2. Amoeba 变形虫 ,国人
3. MyCat alibaba 阿里,国人
4. Atlas 360,国人

一、概念

Amoeba是一个以MySQL为底层数据存储,并对应用提供MySQL协议接口的proxy。它集中地响应应用的请求,依据用户事先设置的规则,将SQL请求发送到特定的数据库上执行。基于此可以实现负载均衡、读写分离、高可用性等需求。与MySQL官方的MySQL Proxy相比,作者强调的是amoeba配置的方便(基于XML的配置文件,用SQLJEP语法书写规则,比基于lua脚本的MySQL Proxy简单)。
Amoeba相当于一个SQL请求的路由器,目的是为负载均衡、读写分离、高可用性提供机制,而不是完全实现它们。用户需要结合使用MySQL的 Replication等机制来实现副本同步等功能。amoeba对底层数据库连接管理和路由实现也采用了可插拨的机制,第三方可以开发更高级的策略类来替代作者的实现。这个程序总体上比较符合KISS原则的思想。
注:KISS原则,keep it simple and stupid ,简单的理解这句话就是,要把一个系统做的连白痴都会用。这就是用户体验的高层境界了,好听的说法也是有的,简单就是美。

二、优势

Amoeba主要解决以下问题:
a). 数据切分后复杂数据源整合
b). 提供数据切分规则并降低数据切分规则给数据库带来的影响
c). 降低数据库与客户端连接
d). 读写分离路由

三、指南

Amoeba 的详细使用说明请参见:http://docs.hexnova.com/amoeba/

四、配置JDK

Amoeba首先需要安装jdk环境。
yum -y install glibc.i686 #jdk依赖glibc
mkdir /usr/local/src/java #按习惯用户自己安装的软件存放到/usr/local/src目录下
rz 上传jdk tar包 #利用xshell的rz命令上传文件
tar -xvf jdk-7u80-linux-x64.tar.gz #解压压缩包
配置环境变量
1)vi /etc/profile
2)在尾行添加


export JAVA_HOME=/usr/java/jdk1.7.0_80
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin

保存退出
3)source /etc/profile 使更改的配置立即生效
4)java -version 查看JDK版本信息。如显示1.7.0证明成功。

注意:如果测试java已经可以,但运行./amoeba start却报错找不到JAVA_HOME。就自己指定一个JAVA_HOME变量极其路径。

五、安装配置Amoeba

下载地址:
https://sourceforge.net/projects/amoeba/files/

创建目录
cd /usr/local/src/
mkdir amoeba

下载的是zip ,
amoeba-mysql-3.0.5-RC-distribution.zip

将压缩包复制进去,然后解压

1、安装支持ZIP的工具
yum install -y unzip zip
2、解压zip文件
unzip 文件名.zip
3、压缩一个zip文件
zip 文件名.zip 文件夹名称或文件名称

unzip amoeba-mysql-3.0.5-RC-distribution.zip

cd amoeba-mysql-3.0.5-RC-distribution

mv amoeba-mysql-3.0.5-RC ../

cd ..

rm -rf amoeba-mysql-3.0.5-RC-distribution

cd amoeba-mysql-3.0.5-RC

cd conf

将配置文件ser复制出来,编辑后再复制进去
amoeba.xml
dbServers.xml

amoeba.xml文件内容如下:

<?xml version="1.0" encoding="gbk"?>

<!DOCTYPE amoeba:configuration SYSTEM "amoeba.dtd">
<amoeba:configuration xmlns:amoeba="http://amoeba.meidusa.com/">

    <proxy>

        <!-- service class must implements com.meidusa.amoeba.service.Service -->
        <service name="Amoeba for Mysql" class="com.meidusa.amoeba.mysql.server.MySQLService">
            <!-- port -->
            <property name="port">8066</property>

            <!-- bind ipAddress -->
            <!-- 
            <property name="ipAddress">127.0.0.1</property>
             -->

            <property name="connectionFactory">
                <bean class="com.meidusa.amoeba.mysql.net.MysqlClientConnectionFactory">
                    <property name="sendBufferSize">128</property>
                    <property name="receiveBufferSize">64</property>
                </bean>
            </property>

            <property name="authenticateProvider">
                <bean class="com.meidusa.amoeba.mysql.server.MysqlClientAuthenticator">

                    <property name="user">root</property>

                    <property name="password"></property>

                    <property name="filter">
                        <bean class="com.meidusa.toolkit.net.authenticate.server.IPAccessController">
                            <property name="ipFile">${amoeba.home}/conf/access_list.conf</property>
                        </bean>
                    </property>
                </bean>
            </property>

        </service>

        <runtime class="com.meidusa.amoeba.mysql.context.MysqlRuntimeContext">

            <!-- proxy server client process thread size -->
            <property name="executeThreadSize">128</property>

            <!-- per connection cache prepared statement size  -->
            <property name="statementCacheSize">500</property>

            <!-- default charset -->
            <property name="serverCharset">utf8</property>

            <!-- query timeout( default: 60 second , TimeUnit:second) -->
            <property name="queryTimeout">60</property>
        </runtime>

    </proxy>

    <!-- 
        Each ConnectionManager will start as thread
        manager responsible for the Connection IO read , Death Detection
    -->
    <connectionManagerList>
        <connectionManager name="defaultManager" class="com.meidusa.toolkit.net.MultiConnectionManagerWrapper">
            <property name="subManagerClassName">com.meidusa.toolkit.net.AuthingableConnectionManager</property>
        </connectionManager>
    </connectionManagerList>

        <!-- default using file loader -->
    <dbServerLoader class="com.meidusa.amoeba.context.DBServerConfigFileLoader">
        <property name="configFile">${amoeba.home}/conf/dbServers.xml</property>
    </dbServerLoader>

    <queryRouter class="com.meidusa.amoeba.mysql.parser.MysqlQueryRouter">
        <property name="ruleLoader">
            <bean class="com.meidusa.amoeba.route.TableRuleFileLoader">
                <property name="ruleFile">${amoeba.home}/conf/rule.xml</property>
                <property name="functionFile">${amoeba.home}/conf/ruleFunctionMap.xml</property>
            </bean>
        </property>
        <property name="sqlFunctionFile">${amoeba.home}/conf/functionMap.xml</property>
        <property name="LRUMapSize">1500</property>
        <property name="defaultPool">multiPool</property>

        <!--
        <property name="writePool">server1</property>
        <property name="readPool">server1</property>
        -->
        <property name="needParse">true</property>
    </queryRouter>
</amoeba:configuration>

dbServers.xml文件内容如下

<?xml version="1.0" encoding="gbk"?>

<!DOCTYPE amoeba:dbServers SYSTEM "dbserver.dtd">
<amoeba:dbServers xmlns:amoeba="http://amoeba.meidusa.com/">

        <!-- 
            Each dbServer needs to be configured into a Pool,
            If you need to configure multiple dbServer with load balancing that can be simplified by the following configuration:
             add attribute with name virtual = "true" in dbServer, but the configuration does not allow the element with name factoryConfig
             such as 'multiPool' dbServer   
        -->

    <dbServer name="abstractServer" abstractive="true">
        <factoryConfig class="com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory">
            <property name="connectionManager">${defaultManager}</property>
            <property name="sendBufferSize">64</property>
            <property name="receiveBufferSize">128</property>

            <!-- mysql port -->
            <property name="port">3306</property>

            <!-- mysql schema -->
            <property name="schema">test</property>

            <!-- mysql user -->
            <property name="user">test111</property>

            <property name="password">111111</property>
        </factoryConfig>

        <poolConfig class="com.meidusa.toolkit.common.poolable.PoolableObjectPool">
            <property name="maxActive">500</property>
            <property name="maxIdle">500</property>
            <property name="minIdle">1</property>
            <property name="minEvictableIdleTimeMillis">600000</property>
            <property name="timeBetweenEvictionRunsMillis">600000</property>
            <property name="testOnBorrow">true</property>
            <property name="testOnReturn">true</property>
            <property name="testWhileIdle">true</property>
        </poolConfig>
    </dbServer>

    <dbServer name="server1"  parent="abstractServer">
        <factoryConfig>
            <!-- mysql ip -->
            <property name="ipAddress">127.0.0.1</property>
        </factoryConfig>
    </dbServer>

    <dbServer name="server2"  parent="abstractServer">
        <factoryConfig>
            <!-- mysql ip -->
            <property name="ipAddress">127.0.0.1</property>
        </factoryConfig>
    </dbServer>

    <dbServer name="multiPool" virtual="true">
        <poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">
            <!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA-->
            <property name="loadbalance">1</property>

            <!-- Separated by commas,such as: server1,server2,server1 -->
            <property name="poolNames">server1</property>
        </poolConfig>
    </dbServer>

</amoeba:dbServers>

dbServers.xml 要修改的地方有:

这里写图片描述

amoeba.xml要修改的地方有:

这里写图片描述

这里写图片描述

备份好原有配置文件

然后将配好的文件覆盖到服务器上

打开8066端口号(CentOS7)
firewall-cmd –add-port=8066/tcp –permanent

(CentOS6)
/sbin/iptables -I INPUT -p tcp –dport 8066 -j ACCEPT
/etc/rc.d/init.d/iptables save #修改生效
/etc/init.d/iptables status #查看配置

运行amoeba服务
cd /usr/local/src/amoeba/amoeba-mysql-3.0.5-RC/bin

启动amoeba
./amoeba start 或 ./amoeba start &(低版本)
./laucher start 或 ./laucher start &(高版本)

停止amoeba
./amoeba stop(低版本)
./laucher stop(高版本)

如果启动出现报错:
这里写图片描述
java栈设置小
默认配置Xss比较小128k,启动时提示太小,则修改/amoeba/bin/amoeba文件,修改为256k即可。
DEFAULT_OPTS=”-server -Xms256m -Xmx256m -Xss256k”

vim laucher
配置启动参数
DEFAULT_OPTS=”.server -Xms256m -Xmx256m -Xss256k”
这里写图片描述

./laucher start &

初步测试是否可以从amoeba服务器上连接数据库,可以用工具连接,具体不知道连接的哪个服务器。

测试是否成功

项目数据库配置要修改:

这里写图片描述

重启项目

看是否能加载数据,能出来证明和amoeba连上了

测试写操作。
添加内容

在另外两个数据库查询数据是否也增加上了

修改类似

要测试是否轮询,要将三个数据库手动修改内容,刷新测试

当然修改后把三个数据库再保持一致

总结:

  • 主从复制,利用mysql自身提供主从复制功能,实现master上数据有写操作,slave节点会自动同步它的数据
  • 配置,在mster开启二进制日志文件功能,默认不开启,设置server-id=1,从节点挂钩到主的节点上,change master to,启动从服务,必须看到两个YES,如果有一个NO,找到错误原因,修改完成,重复上面的过程。
  • 两次操作,第一次全库备份然后导入demo.sql,然后开启从服务
  • 主从复制解决数据备份,实时备份。
  • 读写分离:MySQL proxy,后三者amoeba,mycat,atlas在mysql proxy基础上实行的。都是通过配置文件来配置的,配置虚拟的server,指定谁负责读multPool(slave1,slave2,master),谁负责写master

读写分离,充分利用服务器资源,master负责写操作,slave复制读操作,slave资源得到利用。减轻整个系统的数据库访问压力,增加了一台服务器。让写操作也比穿让一个数据库的方式快。

原来读写并存,如果写时,悲观锁锁表,即使乐观锁锁行,但是读写还是有冲突。只能读的操作等着,等着操作完成,才能读,效率低。

新的方式,写的操作在master,没有人跟它冲突,因为读的操作都被所有的从的节点来接受,两个机器,两个物理链路。性能快。

读写在一起有事务,就慢。

如果只是读,读就不需要事务,性能更高。提升整个架构30%。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值