MySQL 读写拆散的概述

MySQL 作为目前世界上应用最宽泛的收费数据库,置信所有从事零碎运维的工程师都肯定接触过。但在理论的生产环境中,由单台 MySQL 作为独立的数据库是齐全不能满足理论需要的,无论是在安全性,高可用性以及高并发等各个方面。

因而,一般来说都是通过主从复制(Master-Slave)的形式来同步数据,再通过读写拆散(MySQL-Proxy/Amoeba)来晋升数据库的并发负载能力,这样的计划来进行部署与施行的。

读写拆散工作原理

根本的原理是让主数据库解决事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库解决 SELECT 查问操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。

数据外部替换过程:

为什么要读写拆散

  1. 面对越来越大的拜访压力,单台的服务器的性能成为瓶颈,须要分担负载
  2. 主从只负责各自的写和读,极大水平的缓解 X(写)锁和 S(读)锁争用
  3. 从库可配置 myisam 引擎,晋升查问性能以及节约零碎开销
  4. 减少冗余,进步可用性

实现读写拆散的形式

个别有两种形式实现

  1. 应用程序层实现,网站的程序实现
    应用程序层实现指的是在应用程序外部及连接器中实现读写拆散

    长处:
    应用程序外部实现读写拆散,装置既能够应用;
    缩小肯定部署难度;
    拜访压力在肯定级别以下,性能很好。
    毛病:
    架构一旦调整,代码要跟着变;
    难以实现高级利用,如主动分库,分表;
    无奈实用大型利用场景。
  2. 中间件层实现:
    中间件层实现是指在内部中间件程序实现读写拆散

    常见的中间件程序

  3. Cobar:
    阿里巴巴 B2B 开发的关系型分布式系统,治理将近 3000 个 MySQL 实例。 在阿里禁受住了考验,前面因为作者的走开的起因 cobar 没有人保护 了,阿里也开发了 tddl 代替 cobar。
  4. MyCAT:
    社区爱好者在阿里 cobar 根底上进行二次开发,解决了 cobar 过后存在的一些问题,并且退出了许多新的性能在其中。目前 MyCAT 社区活跃度很高,曾经有一些公司在应用 MyCAT。总体来说反对度比
    较高,也会始终保护上来。
  5. OneProxy:
    数据库界大牛,前支付宝数据库团队领导楼总开发,基于 mysql 官网 的 proxy 思维利用 c 进行开发的,OneProxy 是一款商业免费的中间件,楼总舍去了一些性能点,专一在性能和稳定性上。有人测试过说在高并发下很稳固。
  6. Vitess:
    这个中间件是 Youtube 生产在应用的,然而架构很简单。 与以往中间件不同,应用 Vitess 利用改变比拟大,要应用他提供语言的 API 接口,咱们能够借鉴他其中的一些设计思维。
  7. Kingshard:
    Kingshard 是前 360Atlas 中间件开发团队的陈菲利用业余时间 用 go 语言开发的,目前参加开发的人员有 3 个左右, 目前来看还不是成熟能够应用的产品,须要在不断完善。
  8. Atlas:
  9. 团队基于 mysql proxy 把 lua 用 C 改写。原有版本是反对分表, 目前曾经放出了分库分表版本。在网上看到一些敌人常常说在高并发下会常常挂掉,如果大家要应用须要提前做好测试。
  10. MaxScale 与 MySQL Route:
    这两个中间件都算是官网的,MaxScale 是 mariadb (MySQL 原作者保护的一个版本)研发的,目前版本不反对分库分表。MySQL Route 是当初 MySQL 官网 Oracle 公司公布进去的一个中间件。

长处:
架构设计更灵便
能够在程序上实现一些高级管制,如:透明化程度拆分,failover,监控
能够依附技术手段进步 mysql 性能
对业务代码的影响小,同时也平安

毛病:
须要肯定的开发运维团队的反对。

什么是 MyCAT

一个彻底开源的,面向企业应用开发的大数据库集群;
反对事务、ACID、能够代替 MySQL 的加强版数据库;
一个能够视为 MySQL 集群的企业级数据库,用来代替低廉的 Oracle 集群;
一个交融内存缓存技术、NoSQL 技术、HDFS 大数据的新型 SQL Server;
联合传统数据库和新型分布式数据仓库的新一代企业级数据库产品;
一个新鲜的数据库中间件产品。

MyCat 服务装置与配置

MyCat 有提供编译好的安装包,反对 Windows、Linux、Mac、Solaris 等零碎上装置与运行。官网下载主页 http://www.mycat.org.cn/

架构

192.168.1.63 mycat192.168.1.64 主192.168.1.65 从

Mycat 须要装置 JDK 1.7 或者以上版:
第一步:下载 jdk-8u191-linux-x64.tar.gz 文件

[root@xuegod63 local]# wget http://download.oracle.com/otn-pub/java/jdk/8u191-b12/2787e4a523244c269598db4e85c51e0c/jdk-8u191-linux-x64.tar.gz #如果在Linux 上下载的程序包有问题,须要把链接复制到 Windows 上下载再上传到 Linux。

第二步:新建/usr/java 文件夹,将 jdk-8u191-linux-x64.tar.gz 解压到该目录中

[root@xuegod63 local]# mkdir /usr/java[root@xuegod63 local]# tar xf jdk-8u191-linux-x64.tar.gz -C /usr/java/

第三步:配置环境变量 在/etc/profile 底部退出如下内容:

[root@xuegod63 local]# vim /etc/profile.d/java.sh #/etc/profile.d/目录下创立java.sh 文件并定入如下内容JAVA_HOME=/usr/java/jdk1.8.0_191PATH=$JAVA_HOME/bin:$PATH CLASSPATH=$JAVA_HOME/jre/lib/ext:$JAVA_HOME/lib/tools.jarexport PATH JAVA_HOME CLASSPATH[root@xuegod63 local]# source /etc/profile.d/java.sh #使环境变量失效[root@xuegod63 local]# java -version#查看 java 版本java version "1.8.0_191"Java(TM) SE Runtime Environment (build 1.8.0_191-b12)Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)

装置 mycat
Linux 下能够下载 Mycat-server-xxxxx.linux.tar.gz 解压在某个目录下,留神目录不能有空格,在 Linux(Unix)下,倡议放在 usr/local/Mycat 目录下,如下:

[root@xuegod63 ~]# tar -xf Mycat-server-1.5-RELEASE-0301083012-linux.tar.gz -C /usr/local/[root@xuegod63 local]# ls /usr/local/mycat/


上面批改 MyCAT 用户明码(仅供参考):

[root@xuegod63 ~]# useradd mycat[root@xuegod63 ~]# passwd mycat #批改时输出两次明码 胜利


[root@xuegod63 ~]# chown -R mycat.mycat /usr/local/mycat #批改权限

目录解释如下:

bin 程序目录,寄存了 window 版本和 linux 版本,除了提供封装成服务的版本之外,也提供了nowrap 的 shell 脚本命令,不便大家抉择和批改,进入到 bin 目录:

Linux 下运行:./mycat console,首先要 chmod +x *

注:mycat 反对的命令{ console | start | stop | restart | status | dump }

conf 目录下寄存配置文件,server.xmlMycat 服务器参数调整和用户受权的配置文件,schema.xml 是逻辑库定义和表以及分片定义的配置文件,rule.xml 是分片规定的配置文件,分片规定的具体一些参数信息独自寄存为文件,也在这个目录下,配置文件批改,须要重启 Mycat 失效。

lib 目录下次要寄存 mycat 依赖的一些 jar 文件。

日志寄存在 logs/mycat.log 中,每天一个文件,日志的配置是在 conf/log4j.xml 中,依据本人的须要,能够调整输入级别为 debug,在 debug 级别下,会输入更多的信息,不便排查问题。

MyCat 服务启动与启动设置

MyCAT 在 Linux 中部署启动时,首先须要在 Linux 零碎的环境变量中配置 MYCAT_HOME,操作形式如下:

[root@xuegod63 local]# vim /etc/profile.d/mycat.sh #在/etc/profile.d 目录下创立mycat.sh 文件,并写入如下。MYCAT_HOME=/usr/local/mycat PATH=$MYCAT_HOME/bin:$PATH[root@xuegod63 local]# source /etc/profile.d/mycat.sh #使环境变量失效

如果是在多台 Linux 零碎中组建的 MyCAT 集群,那须要在 MyCAT Server 所在的服务器上配置对其余 IP 和主机名的映射,配置形式如下:

vi /etc/hosts 

例如:我有 3 台机器,配置如下:
IP 主机名:

192.168.1.63 xuegod63.cn 192.168.1.64 xuegod64.cn 192.168.1.65 xuegod65.cn

编辑完后,保留文件。

mycat 的用户账号和受权信息是在 conf/server.xml 文件中配置

[root@xuegod63 local]# vim /usr/local/mycat/conf/server.xml<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mycat:server SYSTEM "server.dtd"><mycat:server xmlns:mycat="http://org.opencloudb/"> <system> <property name="defaultSqlParser">druidparser</property> </system> <!--以下设置为利用拜访帐号权限 --> 34 行 <user name="root"> #定义管理员用户,也就是连贯 Mycat 的用户名 <property name="password">123456</property> #明码 <property name="schemas">ha</property> #定义一个逻辑库,与schema 配置文件对应 </user> <!--以下设置为利用只读帐号权限 --> <user name="user"> <property name="password">user</property> <property name="schemas">ha</property> <property name="readOnly">true</property> </user></mycat:server>

编辑 MyCAT 的配置文件 schema.xml,对于 dataHost 的配置信息如下:

[root@xuegod63 local]# mv /usr/local/mycat/conf/schema.xml /usr/local/mycat/conf/schema.xml.bak #备份原文件。[root@xuegod63 local]# vim /usr/local/mycat/conf/schema.xml 新建<?xml version="1.0"?><!DOCTYPE mycat:schema SYSTEM "schema.dtd"><mycat:schema xmlns:mycat="http://org.opencloudb/"> <schema name="ha" checkSQLschema="false" sqlMaxLimit="100" dataNode='dn1'> </schema> <dataNode name="dn1" dataHost="dthost" database="ha"/> <dataHost name="dthost" maxCon="500" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="-1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <writeHost host="xuegod64.cn" url="192.168.1.64:3306" user="mycat" password="123456"> </writeHost> <writeHost host="xuegod65.cn" url="192.168.1.65:3306" user="mycat" password="123456"> </writeHost> </dataHost></mycat:schema>

绿色 ha 为物理存在的数据库名
注解:
schema 标签用于定义 MyCat 实例中的逻辑库,name:前面就是逻辑库名 MyCat 能够有多个逻辑库,每个逻辑库都有本人的相干配置。能够应用 schema 标签来划分这些不同的逻辑库。

checkSQLschema 这个属性默认就是 false,官网文档的意思就是是否去掉表后面的数据库的名称,”select * from db1.testtable” ,设置为 true 就会去掉 db1。然而如果 db1 的名称不是schema 的名称,那么也不会被去掉,因而官网倡议不要应用这种语法。同时默认设置为 false。

sqlMaxLimit 当该值设置为某个数值时。每条执行的 SQL 语句,如果没有加上 limit 语句,MyCat 也会主动的加上所对应的值。例如设置值为 100,执行”select * from test_table”,则成果为
“selelct * from test_table limit 100”.

dataNode 标签定义了 MyCat 中的数据节点,也就是咱们通常说所的数据分片。一个dataNode 标签就是一个独立的数据分片.

属性阐明
Name定义数据节点的名字,这个名字须要是惟一的
dataHost该属性用于定义该分片属于哪个数据库实例
Database该属性用于定义该分片属性哪个具体数据库实例上的具体库

dataHost 该标签定义了具体的数据库实例、读写拆散配置和心跳语句

标签阐明
name惟一标识 dataHost 标签,供下层的标签应用
maxCon指定每个读写实例连接池的最大连贯。
minCon指定每个读写实例连接池的最小连贯,初始化连接池的大小。
dbType指定后端连贯的数据库类型,目前反对二进制的 mysql 协定,还有其余应用JDBC 连贯的数据库。例如:mongodb、oracle、spark 等.
dbDriver指定连贯后端数据库应用的 Driver,目前可选的值有 native 和 JDBC。应用native 的话,因为这个值执行的是二进制的 mysql 协定,所以能够应用 mysql 和 maridb。其余类型的数据库则须要应用 JDBC 驱动来反对。
switchType“-1” 示意不主动切换; “1” 默认值,主动切换; “2” 基于 MySQL 主从同步的状态决定是否切换 心跳语句为 show slave status “3” 基于MySQL galary cluster 的切换机制(适宜集群)(1.4.1)心跳语句为 show status like ‘wsrep%’.

heartbeat 标签指明用于和后端数据库进行心跳查看的语句。

writeHost /readHost 这两个标签都指定后端数据库的相干配置,用于实例化后端连接池。惟一不同的是,writeHost 指定写实例、readHost 指定读实例。 在一个 dataHost 内能够定义多个writeHost 和 readHost。然而,如果 writeHost 指定的后端数据库宕机,那么这个 writeHost 绑定的所有 readHost 都将不可用。另一方面,因为这个 writeHost 宕机,零碎会主动的检测到,并切换到备用的 writeHost 下来。这两个标签的属性雷同

属性阐明
Host用于标识不同实例,个别 writeHost 咱们应用M1,readHost 咱们用S1。
url后端实例连贯地址。Native:地址:端口 JDBC:jdbc 的 url
password后端存储实例须要的明码
user后端存储实例须要的用户名字
weight权重 配置在 readhost 中作为读节点的权重

有两个参数须要留神,balance 和 switchType。其中,balance 指的负载平衡类型,目前的取值
有 4 种:

  1. balance="0", 不开启读写拆散机制,所有读操作都发送到以后可用的 writeHost 上;
  2. balance="1",全副的 readHost 与 stand by writeHost 参加 select 语句的负载平衡,简略的
    说,当双主双从模式(M1->S1,M2->S2,并且 M1 与 M2 互为主备),失常状况下,M2、S1、S2 都
    参加 select 语句的负载平衡;
  3. balance="2",所有读操作都随机的在 writeHost、readhost 上散发;

    1. balance="3",所有读申请随机的散发到 wiriterHost 对应的 readhost 执行,writerHost 不

    累赘读压力。

switchType 指的是切换的模式,目前的取值也有 4 种:

  1. switchType='-1' 示意不主动切换;
  2. switchType='1' 默认值,示意主动切换;
  3. switchType='2' 基于 MySQL 主从同步的状态决定是否切换,心跳语句为 show slave status;
  4. switchType='3'基于 MySQL galary cluster 的切换机制(适宜集群)(1.4.1),心跳语句为show status like 'wsrep%'。

通过以上两个步骤的配置,就能够到/usr/local/mycat/bin 目录下执行 ./mycat start,即可启动mycat 服务!

[root@xuegod63 local]# /usr/local/mycat/bin/mycat start[root@xuegod63 ~]# cat /usr/local/mycat/logs/wrapper.log #查看日志,启动胜利

配置 MySQL 主从

装置 mysql
上传 mysql-5.7.tar.gz 到 xuegod64

[root@xuegod64 ~]# scp mysql-5.7.tar.gz root@192.168.1.65:/root/[root@xuegod64 ~]# tar xf mysql-5.7.tar.gz[root@xuegod64 ~]# yum install -y ./mysql*.rpm

敞开明码强度审计插件

[root@xuegod64 ~]# systemctl start mysqld[root@xuegod64 ~]# echo "validate-password=OFF">> /etc/my.cnf[root@xuegod64 ~]# systemctl restart mysqld

批改 root 用户明码

[root@xuegod64 ~]# grep "password" /var/log/mysqld.log[root@xuegod64 ~]# mysql -uroot -p'-NEjo1gbPllh'mysql> set password for root@localhost = password('123456');mysql> exit

另一台机器

[root@xuegod65 ~]# tar xf mysql-5.7.tar.gz[root@xuegod65 ~]# yum install -y ./mysql*.rpm

敞开明码强度审计插件

[root@xuegod65 ~]# systemctl start mysqld[root@xuegod65 ~]# echo "validate-password=OFF">> /etc/my.cnf[root@xuegod65 ~]# systemctl restart mysqld

批改 root 用户明码

[root@xuegod65~]# grep "password" /var/log/mysqld.log[root@xuegod65 ~]# mysql -uroot -p'%OrrfGwyM6tS'mysql> set password for root@localhost = password('123456');mysql> exit

创立数据库和测试数据

[root@xuegod64 ~]# mysql -uroot -p123456mysql> create database ha;mysql> use ha;mysql> create table test(id int,name varchar(20));mysql> insert into test values(1,'man');[root@xuegod64 ~]# mysqldump -uroot -p123456 -B ha >HA.sql #能够导出数据库

将导出的数据库传给从服务器

[root@xuegod64 ~]# scp HA.sql root@192.168.1.65:/root/

xuegod65 从服务上操作:
导入数据库和表,用于实现读操作:

[root@xuegod65 ~]# mysql -uroot -p123456<HA.sql[root@xuegod64 ~]# vim /etc/my.cnflog-bin=mysql-bin-master #启用二进制日志server-id=1 #本机数据库 ID 标示binlog-do-db=ha #能够被从服务器复制的库, 二进制须要同步的数据库名binlog-ignore-db=mysql #不能够被从服务器复制的库[root@xuegod64 ~]# systemctl restart mysqld[root@xuegod64 ~]# mysql -uroot -p'123456'

受权给 mycat 登陆数据库应用的帐号以及主从复制账号

mysql> GRANT ALL PRIVILEGES ON *.* TO 'mycat'@"%" IDENTIFIED BY "123456"; mysql> grant replication slave on *.* to slave@"192.168.1.%" identified by "123456";mysql> exit[root@xuegod65 ~]# vim /etc/my.cnflog-bin=mysql-bin-slave #启用二进制日志server-id=2 #本机数据库 ID 标示binlog-do-db=ha #能够被从服务器复制的库, 二进制须要同步的数据库名binlog-ignore-db=mysql #不能够被从服务器复制的库[root@xuegod65 ~]# systemctl restart mysqld[root@xuegod65 ~]# mysql -uroot -p'123456'

受权给 mycat 登陆数据库应用的帐号以及主从复制账号

mysql> GRANT ALL PRIVILEGES ON *.* TO 'mycat'@"%" IDENTIFIED BY "123456";mysql> grant replication slave on *.* to slave@"192.168.1.%" identified by "123456";mysql> change master to master_host='192.168.1.64',master_user='slave',master_password='123456';mysql> start slave; #启动 slavemysql> show slave status\G #查看状态 ,有两个 yes 主从同步胜利!mysql> exit

模仿 slave 故障:从服务器挂掉了

[root@xuegod65 ~]# systemctl stop mysqld

在客户端上测试读写

[root@xuegod63 ~]# mysql -uroot -p123456 -h 192.168.1.63 -P8066 mysql> use ha;mysql> select * from test;


阐明读操作的路由切换到 master 上了,对外没有任何影响!

[root@xuegod65 ~]# systemctl start mysqld

模仿 master 故障:主服务器挂掉了

[root@xuegod64 ~]# systemctl stop mysqld

在客户端上测试读写

[root@xuegod63 ~]# mysql -uroot -p123456 -h 192.168.1.63 -P8066mysql> use ha;mysql> create table test1(id int);ERROR 1184 (HY000): 回绝连贯 #主数据库进行了,是无奈写操作的,但不影响读.mysql> select * from test;

[root@xuegod64 ~]# systemctl start mysqld

只读用户登录测试

mysql -u user -puser -h 192.168.1.201 -P8066mysql> insert into test values(5,'feng');ERROR 1495 (HY000): User readonlymysql> select * from ha.test;+------+--------+| id | name |+------+--------+| 1 | cd |

实战节点宕机后主动切换 Slave 节点

配置 MM 模式主从复制环境
启用 65 为 64 的主

[root@xuegod64 ~]# mysql -uroot -p'123456'mysql> change master to master_host='192.168.1.65',master_user='slave',master_password='123456';mysql> start slave; #启动 slavemysql> show slave status\G #查看状态 ,有两个 yes 主从同步胜利!mysql> exit

mycat 配置文件优化调整。

[root@xuegod63 ~]# vim /usr/local/mycat/conf/schema.xml<?xml version="1.0"?><!DOCTYPE mycat:schema SYSTEM "schema.dtd"><mycat:schema xmlns:mycat="http://org.opencloudb/"> <schema name="ha" checkSQLschema="false" sqlMaxLimit="100" dataNode='dn1'> </schema> <dataNode name="dn1" dataHost="dthost" database="ha"/> <dataHost name="dthost" maxCon="500" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1"slaveThreshold="100"> <heartbeat>select user()</heartbeat> <writeHost host="xuegod64.cn" url="192.168.1.64:3306" user="mycat" password="123456"> </writeHost> <writeHost host="xuegod65.cn" url="192.168.1.65:3306" user="mycat" password="123456"> </writeHost> </dataHost></mycat:schema>

咱们后面配置 switchType="-1"敞开了主动切换,然而咱们在主从环境下应该防止在从节点写入数据,否则会造成主从数据库数据不统一, 如果咱们应用的是 MM 模式则主节点产生故障后会主动切换至备用节点,此时不影响数据写入。

[root@xuegod63 ~]# /usr/local/mycat/bin/mycat restart [root@xuegod64 ~]# systemctl stop mysqld[root@xuegod63 ~]# mysql -uroot -p123456 -h 192.168.1.63 -P8066MySQL [(none)]> insert into ha.test values(666,'mk');MySQL [(none)]> select * from ha.test;+------+---------+| id | name |+------+---------+| 1 | man || 666 | mk |

停主节点:

[root@xuegod64 ~]# systemctl stop mysqldMycat 端持续插入mysql> insert into test values(5,'feng');

复原主节点

[root@xuegod64 ~]# systemctl start mysqldmysql -uroot -p123456select * from ha.test;

对于应用方面的倡议,在一些 CMS(内容管理系统)零碎中底层的数据库代码曾经通过封装,此时应用 mycat 是不可取的,因为封装后的 sql 语句会和 mycat 不兼容,倡议是程序开发时应思考连贯mysql 的形式和 mycat 是互相兼容的。或者抉择其余中间件比方 mysql-proxy。

                                             想要获取原文档和学习视频加笔记                                               增加咱们小姐姐一 一获取哦!