Mycat的读写分离、分表分库

Mycat是数据库中间件。

使用场景:

  • 高可用性与Mysql读写分离
  • 业务数据分级存储
  • 大表水平拆分,集群并行计算
  • 数据库连接池
  • 整合多个数据源整合

安装

下载地址:http://dl.mycat.org.cn

安装Mycat之前,需要安装Mysql、JDK,安装Mycat稳定版是1.6.7.1。

下载好的安装包文件 (Mycat-xxx-linux.tar.gz),上传Linux服务器上,一般安装在/usr/local下,进行解压

tar -zxvf Mycat-xxx-linux.tar.gz

安装成功,进入mycat目录,能看到

  • bin:命令文件
  • catlet:空的,扩展
  • conf:配置文件(server.xml,schema.xml,rule.xml等)
  • lib:依赖的jar包

核心概念

分片

我们将存放同一个数据库中数据分散到多个数据库中,达到单台设备负载效果。当数据库量超过800万,需要做分片处理。

数据库切分:

  • 垂直拆分:如果因为表多导致数据多,使用垂直切分,根据业务切分成不同的库;
  • 横向拆分:如果因为单张表的数据量太大,使用水平切分。分库分表的顺序应该是先垂直分,后水平分。
垂直拆分:
  • 垂直分表:大表拆小表,一般是表中的字段较多,将不常用的,数据较大,长度较长字段的拆分到“扩展表。
  • 垂直分库:针对系统中的不同业务进行拆分,比如用户User一个库,商品Producet一个库,订单Order一个库。 切分后,放在多个服务器上。在高并发场景下,垂直分库一定程度上能够突破IO、连接数及单机硬件资源的瓶颈。
水平拆分:
  • 水平分表:针对数据量大的单张表,按照某种规则(RANGE,HASH取模等),切分到多张表里面去。 但是这些表还是在同一个库中,所以库级别的数据库操作还是有IO瓶颈。不建议采用。
  • 水平分库分表:将单表的数据切分到多个服务器上,每个服务器具有相应的库与表,只是表中数据集合不同。 切分规则:1. 从0到10000一个表,10001到20000一个表;2. HASH取模; 3. 地理区域。

逻辑库

Mycat是数据库中间件,可以被看做一个/多个数据库集群构成的逻辑库。然后下面的逻辑表,读写数据的表就是逻辑表。

ER表

表的记录与所有关联的父表记录存放同一个数据分片中,保证数据关联查询不会垮库操作。

全局表

类似于数据字典表,把这些冗余数据定义为全局表。

分片节点

数据切分,一个大表被分到不同的分片数据库上,每个表分片所在数据库就是分片节点。

分片主机

同一机器上存在多个分片数据库,这个分片节点所在的机器是节点主机。

常用命令

启动Mycat:

bin/mycat start
bin/mycat stop
bin/mycat status

查看Mycat:

连接命令:连接端口号:8066

mysql -h (IP地址) -P 8066 -u root -p

连接管理命令:连接端口号:9066

mysql -h (IP地址) -P 9066 -u root -p

配置server.xml

常用系统配置

  • charset 值 utf8 字符集
  • useSqlStat 值 0 1 开启实时统计 0 关闭
  • sqlExecuteTimeout 值 1000 SQL语句超时时间
  • processors 值1,2… 指定线程数量
  • txIsolation 值1,2,3,4 事务的隔离级别
  • serverPort 值8066 使用端口号
  • mangerPort 值9066 管理端口号

user 标签定义登录Mycat用户和权限:

<user name="mycat用户名2">
	<property name="password">密码</property>
	<property name="schemas">逻辑库名</property>
	<property name="readOnly">true(是否只读)</property>
	<property name="benchmark">1000(连接数,0代表不限制)</property>
	<property name="usingDecrypt">1(是否加密,1加密)</property>
	<!--权限设置-->
	<privileges check="true">
		<schema name="逻辑库名" dml="0000">
			<table name="逻辑表" dml="0000"></table>
			<table name="逻辑表" dml="0000-代表增改查删的权限,1代表有,0没有"></table>
		</schema>
	</privileges>
</user>
# 注意
# 设置了密码加密,需要在/lib目录下执行
java -cp Mycat-server-xxx.release.jar io.maycatutil.DecryptUtil 0:root:密码
# 然后得到加密的密码,然后在配置文件密码改成加密后的密码

firewall标签定义防火墙:

<firewall>
	<!--白名单-->
	<whitehost>
		<host user="root" host="IP地址"></host>
	</<whitehost>
	<!--黑名单  这个用户有哪些SQl的权限-->
	<blacklist check="true">
		<property name="selelctAllow">true</property>
		<property name="deleteAllow">false</property>
	</<blacklist>
</firewall>

配置schema.xml

配置逻辑库、逻辑表、分片、分片节点。

  • schema 逻辑库,可以有多个
  • table 逻辑表,它属性:rult:分片规则名 type:类型(全局表、普通表)
  • dataNode 定义数据节点,不能重复
  • dataHost 具体的数据库实例,节点主机
  • database 定义分片所属的数据库

dataHost 标签节点主机:

  • name 节点名称
  • maxCon 最大连接数
  • minCon 最小连接数
  • balance 负载均衡类型 0,1,2,3
  • writeType 写操作分发方式 0:读写操作都是第一台writeHost 1:随机发送writeHost 上
  • switchType 数据库切换测试 -1.1,2,3

writeHost 、readHost标签读写主机:

  • host 实例主机标识
  • url 数据库连接地址
  • weight 权重
  • usingDecrypt 密码加密 0否1是
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
	<schema name="逻辑库名" checkSQLschema="false" sqlMaxLimit="100">
		<!-- name:这张表进行分库,使用数据节点 -->
		<table name="逻辑表" dataNode="数据节点d1,数据节点d2,数据节点d3" rule="分片规则"></table>
	</schema>
	
	<!-- dataNode:数据结点 dataHost:主机名 database:分库的名字的数据库名字 -->
	<dataNode name="数据节点d1" dataHost="host1" database="数据库1" />
	<dataNode name="数据节点d2" dataHost="host2" database="数据库1" />
	<dataNode name="数据节点d3" dataHost="host3" database="数据库1" />
	
	<dataHost name="host1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql"       dbDriver="native" switchType="1" slaveThreshold="100" >
		<heartbeat>select user()</heartbeat>
	   	<writeHost host="hostM1" url="地址1:3306" user="root" password="123123"></writeHost>         </dataHost>
	...
</mycat:schema>

配置rule.xml

定义拆分表的规则

tableRule 标签:

  • name 分片名称
  • rule 分片具体算法
  • columns 分片列名
  • algoorithm 算法方法名

function 标签:

  • name 算法名称
  • class 具体类
<tableRule name="mod_rule">
  <rule>
   	 <columns>customer_id</columns>
   	 <algorithm>mod-long</algorithm>
  </rule>
   ...
</tableRule>
<!--函数算法,这个算法是根据选中的字段进行取模的规则进行拆分-->
<function name="mod-long" class="io.mycat.route.function.PartitionByMod" >
  <property name="count">2</property>
</function>

配置sequence.xml

原有的主键自增不满足集群中主键唯一约束,mycat提供全局序列,保证全局唯一。

  • 本地文件方式
  • 数据库方式
  • 本地时间戳
  • 其他方式
  • 自增长主键

分片

架构演变:单机数据库-由于越来越多的请求,我们将数据库进行读写分离,主机负责写,从机负责读,从库可以水平扩展,所以更多的读请求不成问题。当数据量增大后,写请求越来越多,就需要用到分库分表,对写操作进行切分。

单库太大:单个数据库处理能力有限;解决方法:切分成更多更小的库

单表太大:CRUD都成问题;索引膨胀,查询超时;解决方法:切分成多个数据集更小的表。

分库分表的方式方法:

分为 垂直切分 和 水平切分,如果因为表多导致数据多,使用垂直切分,根据业务切分成不同的库;如果因为单张表的数据量太大,使用水平切分。分库分表的顺序应该是先垂直分,后水平分。

垂直拆分

演示:当一个数据库数据量很大,对这些表进行分片处理,把一个数据库拆分多个数据库,分为用户库、订单库、信息表…

步骤1:

准备3个数据库实例,分别创建属于自己的库(用户库、订单库…)

配置server.xml (配置用户、字符集、逻辑库名)

<user name="mycat用户名">
	<property name="password">密码</property>
	<property name="schemas">逻辑库名</property>
</user>

步骤2:

配置schema.xml

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
	<schema name="逻辑库名" checkSQLschema="false" sqlMaxLimit="100">
		<table name="用户表1" dataNode="d1" primaryKey="主键ID"></table>
		<table name="用户表2" dataNode="d1" primaryKey="主键ID"></table>
		<table name="用户表3" dataNode="d1" primaryKey="主键ID"></table>
		<table name="字典表1" dataNode="dn1,dn2" type="global" ></table>
		
		<table name="订单表1" dataNode="d2" primaryKey="主键ID"></table>
		<table name="订单表2" dataNode="d2" primaryKey="主键ID"></table>
		<table name="订单表3" dataNode="d2" primaryKey="主键ID"></table>
	</schema>
	
	<dataNode name="d1" dataHost="host1" database="用户库" />
	<dataNode name="d2" dataHost="host2" database="订单表" />
	
	<dataHost name="host1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql"       dbDriver="native" switchType="1" slaveThreshold="100" >
		<heartbeat>select user()</heartbeat>
	   	<writeHost host="hostM1" url="地址1:3306" user="root" password="123123"></writeHost>         </dataHost>
	<dataHost name="host2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql"       dbDriver="native" switchType="1" slaveThreshold="100" >
		<heartbeat>select user()</heartbeat>
	   	<writeHost host="hostM1" url="地址2:3306" user="root" password="123123"></writeHost>         </dataHost>
</mycat:schema>

步骤3:

在不同的数据库创建数据,如果有字典表,把字典表分别在不同的数据库进行创建,避免垮库查询

备份命令:mysqldump -uroot -pitcast 库名 表名 > 文件名

把备份出的字典表数据,分别在其他数据库里创建,并配置schema.xml,增加全局表(global)

字典表和关联子表配置

<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
	<table name="customer" dataNode="dn2" ></table>
	<table name="orders" dataNode="dn1,dn2" rule="mod_rule">
		<!-- childTable:关联子表 primaryKey:子表主键 joinKey:关联字段 parentKey:父表的关联字段-->
		<childTable name="orders_detail" primaryKey="id" joinKey="order_id" parentKey="id" />
	</table>
	
	<!--例如字典表,需要在host1 host2 主键都创建,type:定义global 全局表 -->
	<table name="dict_order_type" dataNode="dn1,dn2" type="global" ></table>
</schema>
<dataNode name="dn1" dataHost="host1" database="数据库1" />
<dataNode name="dn2" dataHost="host2" database="数据库2" />

启动Mycat,配置完成。

水平拆分

将同一个表中数据按某种规则拆分到多台数据库主机上。

演示:当一个张表数据量很大,对这些表进行分片处理,拆分3台数据库主机上。

步骤1:

准备3个数据库实例,分别创建属于自己的库(用户库)

配置server.xml (配置用户、字符集、逻辑库名)

步骤2:

配置schema.xml

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
	<schema name="逻辑库名" checkSQLschema="false" sqlMaxLimit="100">
		<table name="用户表1" dataNode="d1,d2,d3" primaryKey="主键ID" rule="mod_rule(取模分片)">	
		</table>
	</schema>
	
	<dataNode name="d1" dataHost="host1" database="用户库" />
	<dataNode name="d2" dataHost="host2" database="用户库" />
	<dataNode name="d3" dataHost="host3" database="用户库" />
	
	<dataHost name="host1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql"       dbDriver="native" switchType="1" slaveThreshold="100" >
		<heartbeat>select user()</heartbeat>
	   	<writeHost host="hostM1" url="地址1:3306" user="root" password="123123"></writeHost>         </dataHost>
	<dataHost name="host2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql"       dbDriver="native" switchType="1" slaveThreshold="100" >
		<heartbeat>select user()</heartbeat>
	   	<writeHost host="hostM1" url="地址2:3306" user="root" password="123123"></writeHost>         </dataHost>
	<dataHost name="host3" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql"       dbDriver="native" switchType="1" slaveThreshold="100" >
		<heartbeat>select user()</heartbeat>
	   	<writeHost host="hostM1" url="地址3:3306" user="root" password="123123"></writeHost>         </dataHost>
</mycat:schema>

步骤3:

配置rule.xml

<tableRule name=“mod_rule“>
   <rule>
   	    <columns>customer_id</columns>
   	    <algorithm>mod-long</algorithm>
   </rule>
   ...
</tableRule>

<!--函数算法,这个算法是根据选中的字段进行取模的规则进行拆分-->
<function name=“mod-long” class=“io.mycat.route.function.PartitionByMod” >
    <property name="count">3</property>
</function>

步骤4:

启动Mycat,在Mycat下创建表结构,然后其他数据库也就创建表结构数据。

进行测试,我们创建一些数据,然后根据分片规则,在对应的数据库创建对应的数据。

分片规则:

  • mod-long 取模分片

  • auto-sharding-long 范围分片

    # 配置 autopartition-long.txt文件
    # M=10000 k=1000
    0-500M=0
    500M-1000M=1
    1000M-1500M=2
    
  • sharding-by-intfile 枚举分片 本规则适合省份、状态拆分数据

    <tableRule name=“sharding-by-intfile“>
       <rule>
       	    <columns>status</columns>
       	    <algorithm>hash-int</algorithm>
       </rule>
    </tableRule>
    <function name=hash-int” class=“io.mycat.route.function.ParitionByFileMap” >
        <property name="mapFile">partition-hash-int.txt</property>
        <property name="type">0</property>
        <property name="defaultNode">0 (默认的节点)</property>
    </function>
    # partition-hash-int.txt
    1=0
    2=1
    3=2
    # 根据状态status字段进行拆分,值1为第一个数据库,值2为第二个数据库,值3为第三个数据库
    
  • auto-sharding-rang-mod 范围分片(先进行范围分片,计算分组,再进行组内求模)

    <tableRule name=“auto-sharding-rang-mod“>
       <rule>
       	    <columns>id</columns>
       	    <algorithm>rang-mod</algorithm>
       </rule>
    </tableRule>
    <function name=“rang-mod” class=“io.mycat.route.function.PartitionByRangeMod” >
        <property name="mapFile">autopartition-range-mod.txt</property>
        <property name="defaultNode">0 (默认的节点)</property>
    </function>
    # autopartition-range-mod.txt
    0-500M=1
    500M1-200M=2
    # M=10000 2是2个节点
    
  • sharding-by-long-hash 固定分片hash算法

  • sharding-by-prefixpattern 字符串hash求模范围算法

  • sharding-by-murmur 一致性hash算法

    # 有效解决分布式数据的拓容问题,均匀的分散到数据库节点上
    <tableRule name=“sharding-by-murmur“>
       <rule>
       	    <columns>id</columns>
       	    <algorithm>murmur</algorithm>
       </rule>
    </tableRule>
    <function name=“murmur” class=“io.mycat.route.function.PartitionByMurmurHash” >
        <property name="seed">0</property>
        <property name="count">3(要分片的数据库节点)</property>
        <property name="virtualBucketTimes">160</property>
    </function>
    
  • sharding-by-date 日期分片算法

  • sharding-by-month 自然月分片算法

全局序列:

一旦分库,在不同机器上部署mysql,新增数据,表的主键肯能出现相等状况,为了避免这个设置全局序列。

  • 本地文件:不推荐,一旦mycat挂了,本地文件也访问不到。
  • 数据库方式:利用数据库一个表 来进行计数累加。mycat会预加载一部分号段到mycat的内存中,这样大部分读写序列都是在内存中完成的。如果内存中的号段用完了 mycat会再向数据库要一次。
  • 时间戳方式:默认的,但是时间戳格式长,性能不好。
  • 自主生成:根据业务逻辑组合,需要改Java代码。

设置数据库方式:

# 1.创建表
CREATE TABLE MYCAT_SEQUENCE (
	NAME VARCHAR(50) NOT NULL,
	current_value INT NOT NULL,
    increment INT NOT NULL DEFAULT 100, 
    PRIMARY KEY(NAME)
) ENGINE=INNODB;

# 2.创建3个函数
DELIMITER $$
CREATE FUNCTION mycat_seq_currval(seq_name VARCHAR(50)) RETURNS VARCHAR(64)
	DETERMINISTIC  
	BEGIN
	DECLARE retval VARCHAR(64);
	SET retval="-999999999,null";
	SELECT CONCAT(CAST(current_value AS CHAR),",",CAST(increment AS CHAR)) INTO retval FROM
	MYCAT_SEQUENCE WHERE NAME = seq_name;
	RETURN retval;
END $$
DELIMITER;

DELIMITER $$
CREATE FUNCTION mycat_seq_setval(seq_name VARCHAR(50),VALUE INTEGER) RETURNS VARCHAR(64)
	DETERMINISTIC
	BEGIN
	UPDATE MYCAT_SEQUENCE
	SET current_value = VALUE
	WHERE NAME = seq_name;
	RETURN mycat_seq_currval(seq_name);
END $$
DELIMITER;

DELIMITER $$
CREATE FUNCTION mycat_seq_nextval(seq_name VARCHAR(50)) RETURNS VARCHAR(64) 
	DETERMINISTIC
	BEGIN
	UPDATE MYCAT_SEQUENCE
	SET current_value = current_value + increment WHERE NAME = seq_name;
	RETURN mycat_seq_currval(seq_name);
END $$
DELIMITER;

# 3 插入序列的表,初始化MYCAT_SEQUENCE数据
字段1:全局序列名字,字段2:多少号开始,字段3:一次性给多少
SELECT * FROM MYCAT_SEQUENCE
INSERT INTO MYCAT_SEQUENCE(NAME,current_value,increment) VALUES ('ORDERS', 400000,100);

# 4 更改mycat配置:
修改这个文件:sequence_db_conf.properties
把要改的表,如order表改成 = dn1 结点

# 5 更改server.xml文件:
把下面的类型改成1 的类型是数据库方式,更改完进行重启
...
<property name="sequnceHandlerType">1</property>

# 6 执行新增操作 增加要用的序列
insert into `orders`(id,amount,customer_id,order_type) values(
    next value for MYCATSEQ_ORDERS
    ,1000,101,102);

性能监控

Mycat-web

帮助我们统计任务和配置管理任务。可以统计SQL并分析慢SQL和高频SQL,为优化SQL提供依据。

安装 Mycat-web

步骤1:

安装Mycat-web之前,需要安装JDK,zookeeper,官方地址:http://zookeeper.apache.org

安装zookeeper:下载好的安装包文件 (zookeepe-xxx.tar.gz),上传Linux服务器上,一般安装在/usr/local下,进行解压

tar -zxvf zookeeper-xxx.tar.gz

解压完,在当前目录(/usr/loca/zookeeper)创建data目录,切换到conf目录下,修改配置文件 zoo_sample.cfg 重命名为 zoo.cfg,修改完进行编辑这个文件

dataDir=/usr/loca/zookeeper/data

启动zookeeper

bin/zkServer.sh start

步骤2:

安装Mycat-web ,下载地址:http://dl.mycat.org.cn

选择mycat-web目录下文件进行下载,下载好的安装包文件,上传Linux服务器上,一般安装在/usr/local下,进行解压

tar -zxvf Mycat-web-xxx-linux.tar.gz

解压完,在当前目录(/usr/loca/mycat-web),如果多个,启动程序:

sh start.sh

启动程序,访问http://ip地址:8082/mycat,通过这个网址进行监控Mycat。

步骤3:

配置Mycat,打开网址,菜单栏 - mycat服务管理 - 新增 (新增要监控的Mycat)注意:管理端口9066 服务端口8066

读写分离

复制的基本原理

主从复制是用来建立一个和主数据库完全一样的数据库环境,称为从数据库,主数据库只有一个。而其它服务器充当从服务器。此时主服务器会将更新信息写入到一个特定的二进制文件中。并会维护文件的一个索引用来跟踪日志循环。这个日志可以记录并发送到从服务器的更新中去。

主从复制配置

步骤1:主机配置

找到Mysql配置文件,[mysqld] 下修改下面内容

...
[mysqld]
server-id = 1  # 主服务器唯一ID

log-bin=自己本地的路径/data/mysqlbin  # 启用二进制日志,日志的存放地址
log-err=自己本地的路径/data/mysqlerr  # 启用二进制日志,错误日志存放地址
# basedir="D:/devSoft/MySQLServer5.5/" # 根目录 (可选填写)

# 设置logbin格式 有3种 默认 STATEMENT(函数支持不好) ROW(行模式大量修改效率不行) MIXED (综合)
binlog_format=STATEMENT  # 二进制日志格式

read-only=0 # 主机,1 只读 0 读写

binlog-ignore-db=mysql # 设置不要复制的数据库
binlog-do-db=需要复制的主数据库名字  # 设置需要复制的数据库

步骤2:从机配置

修改my.cnf配置文件

[mysqld]
server-id = 2  # 从服务器唯一ID
log-bin=自己本地的路径/data/mysqlbin  # 启用二进制日志,日志的存放地址
relay-log=mysql-relay # 开启中继日志

步骤3:重启服务、关闭防火墙

更改配置文件后,重启Mysql服务

关闭防火墙 systemctl stop firewalld

步骤4:创建用户并授权给从机

主机创建用户:

GRANT REPLICATION SLAVE ON *.* TO '用户名'@'从机器数据库IP 或者 % 所有' IDENTIFIED BY '密码';
flush privileges;

查询主机的状态:

show master status;
# 执行上面命令,得到 File(binlog日志) Position(接入点) Binlog_Do_DB(要复制的数据库) Binlog_IgnoreDB()

从机操作:

在从机Mysql命令行上执行。

主机用户,是刚才在主机创建的用户和密码;

binlog日志名字在主机状态里查看,进行赋值;

CHANGE MASTER TO MASTER_HOST='主机IP',MASTER_USER='主机用户',MASTER_PASSWORD='主机密码',
MASTER_LOG_FILE='binlog日志名字',MASTER_LOG_POS=具体的接入点值;

如果操作失败,需要重新配置,执行下面2个命令

stop slave;    # 停止同步操作
reset master;  # 重置主从配置

然后执行下面命令,开启同步

start slave;

步骤5:检查是否成功

show slave status\G;  # 检查状态
# 如果结果下面的字段为Yes 代表配置成功
- Slave_IO_Running: Yes
- Slave_SQL_Running: Yes

检查Mycat的主从复制是否正常

一主一从配置

首先配置数据库的主从复制

步骤1 更改server.xml文件:

设置mycat的用户名和密码,schemas部分设置mycat的逻辑库名。

<user name="mycat用户名">
	<property name="password">密码</property>
	<property name="schemas">TESTDB</property>
</user>

步骤2 更改schema.xml 文件:

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

	<schema name="逻辑库名" checkSQLschema="false" sqlMaxLimit="100">
		<table name="表1" dataNode="dn1" primaryKey="主键ID"></table>
	</schema>
	
	<dataNode name="dn1" dataHost="host1" database="数据库名" />
	
	<!-- dataHost:主机名 balance: 负载均衡类型 0 不开启 1 双主双从 2 随机分发 3 主写从读  -->
	<dataHost name="host1" maxCon="1000" minCon="10" balance="3" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100" >
		<heartbeat>select user()</heartbeat>
		
		<!-- 配置写主机 host:写主机名字,url:主机的地址 user:主机的用户名 password:主机密码 -->
	   	<writeHost host="hostm1" url="192.168.67.1:3306" user="root" password="123123">
	   		<!-- 配置从机 读库(从库)的配置 -->
	    	<readHost host="hosts1" url="192.168.67.131:3306" user="root" password="123123">
	    	</readHost>
	    </writeHost>                                                                               
	</dataHost>
</mycat:schema>

步骤3 验证数据库访问情况:

mysql -u root -p 密码 -h 远程访问的Id地址 -P 3306端口号

步骤5 配置Mycat日志:

在/usr/local/mycat/conf配置,修改log4j2.xml

<asyncRoot level="debug" includeLocation="true">...<asyncRoot>
日志修改为debug模式

步骤6 启动Mycat

# 方式1 - 控制台启动 :去mycat/bin 目录下 执行 mycat console
[root@... bin]# ./mycat console

# 方式2 - 后台启动 :去mycat/bin 目录下 mycat start
[root@... bin]# ./mycat start

如果启动失败,报错域名解析失败

解决:修改 /etc/hosts ,在 127.0.0.1 后面增加你的机器名,修改后,重启服务 service network restart

启动成功,登录MyCat:

# 后台管理的窗口:
mysql -uroot -p 密码 -h 192.168.67.131 -P 9066
# 数据窗口窗口:
mysql -uroot -p 密码 -h 地址 -P 8066
# 登录后,查询库
show databases;

配置完成,进行演示,

在/usr/local/mycat/log查看日志信息,方便看走的哪个数据库

tail -f mycat.log  # 查看日志

双主双从配置

首先配置数据库的主从复制,4个数据库,2主机,2从机

步骤1:主机配置

找到Mysql配置文件,[mysqld] 下修改下面内容

[mysqld]
server-id = 1  # 主服务器唯一ID

log-bin=自己本地的路径/data/mysqlbin  # 启用二进制日志,日志的存放地址

binlog_format=STATEMENT  # 二进制日志格式

binlog-ignore-db=mysql # 设置不要复制的数据库

binlog-do-db=需要复制的主数据库名字1  # 设置需要复制的数据库
binlog-do-db=需要复制的主数据库名字2  # 设置需要复制的数据库
binlog-do-db=需要复制的主数据库名字3  # 设置需要复制的数据库

log-slave-updates # 在作为从数据库的时候,有写入操作也要更新二进制日志文件

另一个主机也这样配置,注意server-id 不能重复

步骤2:从机配置

修改my.cnf配置文件

...
[mysqld]
server-id = 2  # 从服务器唯一ID

relay-log=mysql-relay # 开启中继日志

另一个从机也这样配置,注意server-id 不能重复

步骤3:重启服务、关闭防火墙

更改配置文件后,重启Mysql服务

关闭防火墙 systemctl stop firewalld

步骤4:创建用户并授权给从机

在2个主机上创建用户:

GRANT REPLICATION SLAVE ON *.* TO '用户名'@'从机器数据库IP 或者 % 所有' IDENTIFIED BY '密码';
flush privileges;

查询主机的状态:

show master status;
# 执行上面命令,得到 File(binlog日志) Position(接入点) Binlog_Do_DB(要复制的数据库) Binlog_IgnoreDB()

在从机上配置需要复制的主机

从机1复制主机1,从机2复制主机2,

从机1执行:

CHANGE MASTER TO MASTER_HOST='主机1IP',MASTER_USER='主机用户',MASTER_PASSWORD='主机密码',
MASTER_LOG_FILE='binlog日志名字',MASTER_LOG_POS=具体的接入点值;

从机2执行:

CHANGE MASTER TO MASTER_HOST='主机2IP',MASTER_USER='主机用户',MASTER_PASSWORD='主机密码',
MASTER_LOG_FILE='binlog日志名字',MASTER_LOG_POS=具体的接入点值;

如果操作失败,需要重新配置,执行下面2个命令

stop slave;    # 停止同步操作
reset master;  # 重置主从配置

然后两个从机执行下面命令,开启同步

start slave;

步骤5:两个主机互相复制

主机1执行

CHANGE MASTER TO MASTER_HOST='主机2IP',MASTER_USER='主机用户',MASTER_PASSWORD='主机密码',
MASTER_LOG_FILE='binlog日志名字',MASTER_LOG_POS=具体的接入点值;

主机2执行

CHANGE MASTER TO MASTER_HOST='主机1IP',MASTER_USER='主机用户',MASTER_PASSWORD='主机密码',
MASTER_LOG_FILE='binlog日志名字',MASTER_LOG_POS=具体的接入点值;

然后分别执行:

start slave;

步骤6:检查是否成功

show slave status\G;  # 检查状态
# 如果结果下面的字段为Yes 代表配置成功
- Slave_IO_Running: Yes
- Slave_SQL_Running: Yes

检查Mycat的主从复制是否正常,主机1创建数据,从机1。主机2 都有复制成功。

步骤7:配置读写分离

通过Mycat配置读写分离,更改server.xml文件:

设置mycat的用户名和密码,schemas部分设置mycat的逻辑库名。

步骤8 更改schema.xml 文件:

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

	<schema name="逻辑库名" checkSQLschema="false" sqlMaxLimit="100">
		<table name="表1" dataNode="dn1" primaryKey="主键ID"></table>
	</schema>
	
	<dataNode name="dn1" dataHost="host1" database="数据库名" />
	
	<!-- dataHost:主机名 balance: 负载均衡类型 0 不开启 1 双主双从 2 随机分发 3 主写从读  -->
	<!-- writeType 0写操作在第一主机,如果挂掉,会连接第二主机 1随机发送主机上 -->
	<!-- writeType -1不自动切换 1自动切换 2基于心跳状态决定-->
	<dataHost name="host1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100" >
		<heartbeat>select user()</heartbeat>
		
		<!-- 配置写主机 host:写主机名字,url:主机的地址 user:主机的用户名 password:主机密码 -->
	   	<writeHost host="hostm1" url="主机1:3306" user="root" password="123123">
	    	<readHost host="hosts1" url="从机1:3306" user="root" password="123123">
	    	</readHost>
	    </writeHost> 
        
        <writeHost host="hostm2" url="主机2:3306" user="root" password="123123">
	    	<readHost host="hosts2" url="从机2:3306" user="root" password="123123">
	    	</readHost>
	    </writeHost> 
	</dataHost>
</mycat:schema>

步骤3 验证数据库访问情况:

mysql -u root -p 密码 -h 远程访问的Id地址 -P 3306端口号

步骤5 配置Mycat日志:

在/usr/local/mycat/conf配置,修改log4j2.xml

<asyncRoot level="debug" includeLocation="true">...<asyncRoot>
日志修改为debug模式

步骤6 启动Mycat

# 方式1 - 控制台启动 :去mycat/bin 目录下 执行 mycat console
[root@... bin]# ./mycat console

# 方式2 - 后台启动 :去mycat/bin 目录下 mycat start
[root@... bin]# ./mycat start

启动成功,登录MyCat,配置完成,进行演示。

集群搭建

搭建高可用集群,2台HAProxy 可实现Mycat多节点的集群高可用和负载均衡,而HAProxy 的高可用,由Keepalived来实现。Keepalived负责为该台服务器抢占vip(虚拟IP),抢到后对该主机访问。
image-20210726152209264

搭建高可用集群:

上图,我们要安装的集群架构,mysql 2台、Mycat 2台、HAProxy 2台

步骤1:安装mysql、Mycat

安装并配置数据库的主从配置,配置Mycat的读写分离。安装与上面读写分离步骤一致。

步骤2:安装HAProxy

HAProxy

下载地址:https://src.fedoraproject.org/repo/pkgs/haproxy

下载好的安装包文件 (haproxy-xxx.tar.gz),上传Linux服务器上,一般安装在/usr/local/src下,进行解压

tar -zxvf haproxy-1.5.16.tar.gz

解压完成后,查看内核版本,进行编译

cd /usr/local/src/haproxyc  # 切换目录
uname -r   # 查看内核版本 (得到 2.6.43-431.e16.x86_64)

# HAProxy是C语言开发,需要编译,进行编译命令
make TARGET=linux2643 PREFIX=/usr/local/haproxy ARCH=x86_64
# TARGET=linux内核版本,uname -r命令前几位就是内核版本
# PREFIX haproxyc安装路径
# ARCH 系统位数

编译后,进行安装

make install PREFIX=/usr/local/haproxy

安装成功后,创建目录 (haproxy数据存放的目录)

mkdir -p /usr/data/haproxy/

创建HAProxy配置文件

vim /usr/local/haproxy/haproxy.conf

配置文件:

global
	log 127.0.0.1 local0 
	maxconn 4096 
	chroot /usr/local/haproxy 
	pidfile /usr/data/haproxy/haproxy.pid
	uid 99
	gid 99
	daemon
	node mysql-haproxy-01
	description mysql-haproxy-01
defaults
	log global
	mode tcp
	option abortonclose
	option redispatch
	retries 3
	maxconn 2000
	timeout connect 50000ms
	timeout client 50000ms
	timeout server 50000ms
listen proxy_status
	bind 0.0.0.0:48066
		mode tcp
		balance roundrobin
		server mycat_1 mycat1地址:8066 check
		server mycat_2 mycat2地址:8066 check
frontend admin_stats
	bind 0.0.0.0:8888
		mode http
		stats enable
		option httplog
		maxconn 10
		stats refresh 30s
		stats uri /admin
		stats auth admin:123123
		stats hide-version
		stats admin if TRUE

内容解析:

#global 配置中的参数为进程级别的参数,通常与其运行的操作系统有关
global
	#定义全局的syslog服务器, 最多可定义2个; local0 是日志设备, 对应于/etc/rsyslog.conf中的配置 , 默认收集info级别日志
	log 127.0.0.1 local0 
	#log 127.0.0.1 local1 notice
	#log loghost local0 info
	#设定每个haproxy进程所接受的最大并发连接数 ;
	maxconn 4096 
	#修改HAproxy工作目录至指定的目录并在放弃权限之前执行chroot操作, 可以提升haproxy的安全级别
	chroot /usr/local/haproxy 
	#进程ID保存文件
	pidfile /usr/data/haproxy/haproxy.pid
	#指定用户ID
	uid 99
	#指定组ID
	gid 99
	#设置HAproxy以守护进程方式运行
	daemon
	#debug
	#quiet
	node mysql-haproxy-01  ## 定义当前节点的名称,用于 HA 场景中多 haproxy 进程共享同一个 IP 地址时
	description mysql-haproxy-01 ## 当前实例的描述信息
	
#defaults:用于为所有其他配置段提供默认参数,这默认配置参数可由下一个"defaults"所重新设定
defaults
	#继承global中的log定义
	log global
	#所使用的处理模式(tcp:四层 , http:七层, health:状态检查,只返回OK)
	### tcp: 实例运行于纯 tcp 模式,在客户端和服务器端之间将建立一个全双工的连接,且不会对 7 层报文做任何类型的检查,此为默认模式
	### http:实例运行于 http 模式,客户端请求在转发至后端服务器之前将被深度分析,所有不与 RFC 模式兼容的请求都会被拒绝
	### health:实例运行于 health 模式,其对入站请求仅响应“OK”信息并关闭连接,且不会记录任何日志信息 ,此模式将用于相应外部组件的监控状态检测请求
	mode tcp
	#当服务器负载很高的时候,自动结束掉当前队列处理时间比较长的连接
	option abortonclose
		
	#当使用了cookie时,haproxy将会将请求的后端服务器的serverID插入到cookie中,以保证会话的session持久性,而此时,后端服务器宕机,但是客户端的cookie不会刷新,设置此参数,将会将客户请求强制定向到另外一个后端server上,以保证服务的正常。
	option redispatch
	retries 3
	# 前端的最大并发连接数(默认为 2000)
	maxconn 2000
	# 连接超时(默认是毫秒,单位可以设置 us,ms,s,m,h,d)
	timeout connect 5000
	# 客户端超时时间
	timeout client 50000
	# 服务器超时时间
	timeout server 50000

#listen: 用于定义通过关联“前端”和“后端”一个完整的代理,通常只对 TCP 流量有用
listen proxy_status
	bind 0.0.0.0:48066 # 绑定端口
		mode tcp
		balance roundrobin # 定义负载均衡算法,可用于"defaults"、"listen"和"backend"中,默认为轮询
		#格式: server <name> <address> [:[port]] [param*]
		# weight : 权重,默认为 1,最大值为 256,0 表示不参与负载均衡
        # backup : 设定为备用服务器,仅在负载均衡场景中的其他 server 均不可以启用此 server
        # check  : 启动对此 server 执行监控状态检查,其可以借助于额外的其他参数完成更精细的设定
        # inter  : 设定监控状态检查的时间间隔,单位为毫秒,默认为 2000,也可以使用 fastinter 和 downinter 来根据服务器端专题优化此事件延迟
        # rise   : 设置 server 从离线状态转换至正常状态需要检查的次数(不设置的情况下,默认值为 2)
        # fall   : 设置 server 从正常状态转换至离线状态需要检查的次数(不设置的情况下,默认值为 3)
        # cookie : 为指定 server 设定 cookie 值,此处指定的值将会在请求入站时被检查,第一次为此值挑选的 server 将会被后续的请求所选中,其目的在于实现持久连接的功能
        # maxconn: 指定此服务器接受的最大并发连接数,如果发往此服务器的连接数目高于此处指定的值,其将被放置于请求队列,以等待其他连接被释放
		server mycat_1 192.168.192.157:8066 check inter 10s
		server mycat_2 192.168.192.158:8066 check inter 10s

# 用来匹配接收客户所请求的域名,uri等,并针对不同的匹配,做不同的请求处理
# HAProxy 的状态信息统计页面
frontend admin_stats
	bind 0.0.0.0:8888
		mode http
		stats enable
		option httplog
		maxconn 10
		stats refresh 30s
		stats uri /admin
		stats auth admin:123123
		stats hide-version
		stats admin if TRUE

启动HAProxy

/usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/haproxy.conf

查看进程

ps -ef|grep haproxy

访问地址:http://IP地址:8888/admin (监控地址)

通过haproxy访问Mycat

mysql -h ip地址 -P 48066 -u mycat用户名 -p 密码;

步骤3:安装Keepalived

Keepalived

下载地址:https://www.keepalived.org/download.html

下载好的安装包文件 (Keepalived-xxx.tar.gz),上传Linux服务器上,一般安装在/usr/local/src下,进行解压

tar -zxvf keepalived-1.4.5.tar.gz

解压完成后,安装依赖插件

yum install -y gcc openssl-devel popt-devel

进入解压后的目录,进行配置,进行编译

cd /usr/local/src/keepalived-1.4.5
 
./configure --prefix=/usr/local/keepalived

完成后进行安装

make && make install

运行前配置

cp /usr/local/src/keepalived-1.4.5/keepalived/etc/init.d/keepalived /etc/init.d/
mkdir /etc/keepalived
cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
cp /usr/local/src/keepalived-1.4.5/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
cp /usr/local/keepalived/sbin/keepalived /usr/sbin/

修改配置文件 /etc/keepalived/keepalived.conf

Master:

global_defs {
	notification_email {
		javadct@163.com
	}
	notification_email_from keepalived@showjoy.com
	smtp_server 127.0.0.1
	smtp_connect_timeout 30
	router_id haproxy01
	vrrp_skip_check_adv_addr
	vrrp_garp_interval 0
	vrrp_gna_interval 0
}

vrrp_script chk_haproxy {
	script "/etc/keepalived/haproxy_check.sh"
	interval 2
	weight 2
}

vrrp_instance VI_1 {
	#主机配MASTER,备机配BACKUP
	state MASTER
	#所在机器网卡
	interface eth1
	virtual_router_id 51
	#数值越大优先级越高
	priority 120
	advert_int 1
	authentication {
		auth_type PASS
		auth_pass 1111
	}
	## 将 track_script 块加入 instance 配置块
    track_script {
    	chk_haproxy ## 检查 HAProxy 服务是否存活
    }
	virtual_ipaddress {
		#虚拟IP
		192.168.192.200
	}
}

BackUP:

global_defs {
	notification_email {
		javadct@163.com
	}
	notification_email_from keepalived@showjoy.com
	smtp_server 127.0.0.1
	smtp_connect_timeout 30
	#标识本节点
	router_id haproxy02
	vrrp_skip_check_adv_addr
	vrrp_garp_interval 0
	vrrp_gna_interval 0
}

# keepalived 会定时执行脚本并对脚本执行的结果进行分析,动态调整 vrrp_instance 的优先级
vrrp_script chk_haproxy {
	# 检测 haproxy 状态的脚本路径
	script "/etc/keepalived/haproxy_check.sh"
	#检测时间间隔
	interval 2
	#如果条件成立,权重+2
	weight 2
}

vrrp_instance VI_1 {
	#主机配MASTER,备机配BACKUP
	state BACKUP
	#所在机器网卡
	interface eth1
	virtual_router_id 51
	#数值越大优先级越高
	priority 100
	advert_int 1
	authentication {
		auth_type PASS
		auth_pass 1111
	}
	## 将 track_script 块加入 instance 配置块
    track_script {
    	chk_haproxy ## 检查 HAProxy 服务是否存活
    }
	virtual_ipaddress {
		#虚拟IP
		192.168.192.200
	}
}

编写检测haproxy的shell脚本 haproxy_check.sh

在/etc/keepalived/目录,创建haproxy_check.sh脚本文件

#!/bin/bash

A=`ps -C haproxy --no-header | wc -l`

if [ $A -eq 0 ];then

  /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/haproxy.conf

  echo "haproxy restart ..." &> /dev/null

  sleep 1

  if [ `ps -C haproxy --no-header | wc -l` -eq 0 ];then

    /etc/init.d/keepalived stop

    echo "stop keepalived" &> /dev/null

  fi

fi

启动测试

service keepalived start

登录验证

# 访问的是Vip (虚拟ip)
mysql -uMycat用户名 -p密码 -h 192.168.192.200 -P 48066

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值