- mycat是什么---作用:
java应用程序与数据库紧耦合-----解耦application和db
高访问量高并发对数据库压力----分库分表,多数据源整合
读写请求数据量不一致---(双主双从)读写分离(基于mysql的主从复制)
2.Mycat的安装
需要事先安装jvm环境和安装mysql(jdk采用解压缩,mysql:sudo apt install mysql-server),Mycat压缩包:Mycat-server-1.6.7.1-release-20190627191042-linux.tar.gz,解压安装(安装包通常放在/opt路径下,解压后文件通常放在/usr/local路径下)
windows文件拷贝到linux系统,pscp工具,对应命令:pscp 本地文件dir root@IP:/home/dir,随后mv移动文件到/opt路径下(pscp/scp时提示connection refused,原因可能目标linux中没有安装ssh-server或没有启动,sudo apt-get install openssh-server命令安装)
linux解压命令 tar -zxvf Mycat-server-1.6.7.1-release-20190627191042-linux.tar,随后mv文件夹到/usr/local路径下
3.mycat的配置
备份config路径下server.xml,schema.xml,rule.xml文件
修改配置文件server.xml
Mycat作为数据库中间件,要和不同地址的数据库建立访问,准备3台虚拟机数据库地址
mysql -uroot -p556600 -h 10.0.0.214 -P 3306
mysql -uroot -p556600 -h 10.0.0.212 -P 3306
mysql -uroot -p556600 -h 10.0.0.177 -P 3306
如果无权远程访问,主机间授权:grant all privileges on . to root@被受限的主机IP identified by '556600';
如果遇到报错:Can't connect to MySQL server on (111),修改mysql配置:/etc/mysql/mysql.cnf.d/mysqld.cnf,注释bind地址或者改成0.0.0.0,重启mysql服务:service mysql restart
如果遇到报错Can't connect to MySQL server on (110),需关闭防火墙,ubuntu16.04 开启/关闭防火墙:sudo ufw enable/sudo ufw disable
5.Mycat的启动/访问
linux系统中6个任意目录都可以执行的路径:bin sbin usr/bin usr/sbin usr/local/bin usr/local/sbin
控制台启动:mycat/bin目录下执行 ./mycat console(推荐)
后台启动: mycat/bin目录下执行 ./mycat start
运维登录方式访问:mysql -uuser1 -p556600 -h 10.0.0.162 -P9066
数据查询方式访问:mysql -uuser1 -p556600 -h 10.0.0.162 -P8066
注:大p和小p都要写,并且mycat服务器本分要开启远程访问,否则localhost方式只能适合访问本地mysql而不能访问mycat配置的数据库
6.mysql 一主一从搭建
1.不同于redis的主从复制,redis从头复制,替换rdb文件,而mysql从主从复制的切入点开始复制
2.从机读主机的binary log后写入自身的relay log,多次io操作,数据有延迟
主机配置-修改配置文件:vim /etc/mysql/mysql.conf.d/mysqld.cnf(提前备份)
1.主机唯一id server-id=1
2.启动二进制日志 log-bin=mysql-bin
3.设置需要复制的数据库 binlog-do-db=需要复制的主数据的名字
4.设置不需要复制的数据库 binlog-ignore-db=mysql binlog-ignore-db=information_schema
5.设置logbin格式 binlog_format=STATEMENT(默认)
从机配置-修改配置文件:vim /etc/mysql/mysql.conf.d/mysqld.cnf(提前备份)
1.从机唯一id server-id=2
2.启用中继日志
relay-log=mysql-relay
重启mysql主机从机的服务
主机从机关闭防火墙
在主机上以-hlocalhost而非主机ip方式登录,建立账户并授权salve,授权命令 GRANT REPLICATION SALVE ON . TO 'slave'@'可以以这个用户名密码访问主机的ip(%表示任意ip)' IDENTIFIED BY '556600';
查看主机状态
show master status;
从机复制主机的命令 CHANGE MASTER TO MASTER_HOST = '主机ip'
,MASTER_USER='slave'
,MASTER_PASSWORD='556600'
,MASTER_LOG_FILE='mysql-bin.具体数字'---show master status信息
,MASTER_LOG_POS=722;---show master status信息
(如果报错ERROR3021,表示已经启动了从机复制,需要stop slave(停止主从复制关系),然后reset master(重新配置主从),再执行上面的语句)
启动从机复制功能 start slave
查看从机状态
show slave status\G;---Slave_IO_Running和Slave_SQL_Running都是Yes表示主从复制搭建成功
如果MySQL报错:master and slave have equal MySQL server UUIDs 或者A slave with the same server_uuid/server_id as this slave has connected to the master,主要是因为两台虚拟服务器是经过链路复制生成的,导致auto.cnf中的UUID一样,此时vi /var/lib/mysql/auto.cnf修改auto.cnf中的UUID即可,如cd时permission denied,sudo su,cd openfiledir
注:从机一旦复制报错,就停止复制操作,即便stop后再start slave,目前验证下来有效的方式是删除库,stop slave后reset slave,start slave就可以了(实际生产环境可操作性待商榷)
验证读写分离
基于之前mycat的配置,启动mycat,进入配置的数据库TESTDB(逻辑库),use TESTDB,select * from mytbl可以查到数据
验证查询的配置的主机的数据还是从机的数据,方式:
分别在各机器的mysqll设置set @hostname=主机名,在写主机中执行insert into mytbl(1,@@hostname);在mycat中看插入数据的主机名---(@@系统变量)
结果:显然一定是查询的主机,因为需要更改<dataHost>的balance属性,通过此属性配置读写分离的类型,
为了能看到读写分离的效果,把balance设置成2,会在两个主机间切换查询,实际应用场景中使用1或者3,配置负载均衡类型,目前的取值有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 上分发。
(4)balance="3",所有读请求随机的分发到 readhost 执行,writerHost 不负担读压力
7.mysql 双主双从搭建
基于前面的一主一从的环境,首先stop slave和reset master,删除已存在各个机器上的mycat库
注:提前确保都安装了ssh,命令sudo apt-get install openssh-server
参照一主一从设置权限配置,同上修改mysql配置和主机间访问权限,其次:
对于主机M1特殊配置增加:
log-slave-updates
auto-increment-increment = 2
auto-increment-increment = 1
对于主机M2特殊配置增加:
log-slave-updates
auto-increment-increment = 2
auto-increment-increment = 2
s1机器reset master to m1,s2机器reset master to m2,m1机器reset master to m2,m2机器reset master to m1,命令如change master to master_host = '192.168.0.11',master_user='slave',master_password='556600',master_log_file='mysql-bin.000001',master_log_pos=154;具体master_log_file和master_log_pos以主机show master status信息为准
各主机登录mysql,授权从机拷贝主机数据,命令grant replication slave on . to slave@从机IP identified by ‘556600’;
各从机start slave,查看slave状态
双主双重读写分离
修改schema.xml配置,其中
balance="1": 全部的readHost与stand by writeHost参与select语句的负载均衡
writeType="0": 所有写操作发送到配置的第一个writeHost,第一个挂了切到还生存的第二个
writeType="1",所有写操作都随机的发送到配置的 writeHost,1.5 以后废弃不推荐
启动mycat
分库(启动15,16两台机器,各权限和数据库配置等配置同上)
客户表 rows:20万
CREATE TABLE customers(
id INT AUTO_INCREMENT,
NAME VARCHAR(200),
PRIMARY KEY(id)
);
订单表 rows:600万
CREATE TABLE orders(
id INT AUTO_INCREMENT,
order_type INT,
customer_id INT,
amount DECIMAL(10,2),
PRIMARY KEY(id)
);
最后验证,只有customers表创建在了userdb,其余表创建在了orderdb,分库成功
分表-水平(启动15,16两台机器,各权限和数据库配置等配置同上,删除orders表)
修改schema.xml配置:为 orders 表设置数据节点为 dn1、dn2,并指定分片规则为 mod_rule(自定义的名字)重启mycat并创建orders表
插入数据(插入字段必须写明):INSERT INTO orders(id,order_type,customer_id,amount) VALUES (1,101,100,100100);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(2,101,100,100300);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(3,101,101,120000);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(4,101,101,103000);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(5,102,101,100400);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(6,102,100,100020);
在mycat、dn1、dn2中查看orders表数据(插入的几条数据落在了dn1和dn2各自的orders表)
mycat查询验证:
select * from orders;发现结果不是有序的,原因数据落在不同的dn节点,分别查询不同节点后对结果集合并,需要写明order by
分表-水平-join操作
由于对orders表进行了水平分表,对其关联表orders_detail也要进行水平分表,否则分落在不同dn上的order的数据只能关联上某一个dn上的表数据,而关联不上的那部分order数据进行join orders_detail数据时报错
CREATE TABLE orders_detail(
id INT AUTO_INCREMENT,
detail VARCHAR(2000),
order_id INT,
PRIMARY KEY(id));
插入数据INSERT INTO orders_detail(id,detail,order_id) values(1,'detail1',1);
INSERT INTO orders_detail(id,detail,order_id) VALUES(2,'detail1',2);
INSERT INTO orders_detail(id,detail,order_id) VALUES(3,'detail1',3);
INSERT INTO orders_detail(id,detail,order_id) VALUES(4,'detail1',4);
INSERT INTO orders_detail(id,detail,order_id) VALUES(5,'detail1',5);
INSERT INTO orders_detail(id,detail,order_id) VALUES(6,'detail1',6);
在mycat、dn1、dn2中运行两个表join语句
Select o.*,od.detail from orders o inner join orders_detail od on o.id=od.order_id;
分表-水平-全局表
CREATE TABLE dict_order_type(
id INT AUTO_INCREMENT,
order_type VARCHAR(200),
PRIMARY KEY(id)
);
然后插入数据:
INSERT INTO dict_order_type(id,order_type) VALUES(101,'type1');
INSERT INTO dict_order_type(id,order_type) VALUES(102,'type2');
在Mycat、dn1、dn2中查询表数据(dn1和dn2的dict_order_type都有数据且完全一致)
常用分片规则-枚举
修改partition-hash-int.txt
重启mycat并创建表CREATE TABLE orders_ware_info
(
id
INT AUTO_INCREMENT comment '编号',
order_id
INT comment '订单编号',
address
VARCHAR(200) comment '地址',
areacode
VARCHAR(20) comment '区域编号',
PRIMARY KEY(id)
);
插入数据
INSERT INTO orders_ware_info(id, order_id,address,areacode) VALUES (1,1,'北京','110');
INSERT INTO orders_ware_info(id, order_id,address,areacode) VALUES (2,2,'天津','120');
INSERT INTO orders_ware_info(id, order_id,address,areacode) VALUES (3,3,'苏州','130');
结果dn1存放北京数据,dn2存放天津数据,非配置的北京和天津的数据默认落在dn1(问题点:物理库还没有创建表的时候,虚拟库通过show tables可以看到配置的表信息)
常用分片规则-范围,此分片适用于,提前规划好分片字段某个范围属于哪个分片
修改schema,rule和配置文件
重启mycat并创建支付信息表
CREATE TABLE payment_info
(
id
INT AUTO_INCREMENT comment '编号',order_id
INT comment '订单编号',payment_status
INT comment '支付状态',PRIMARY KEY(id)
);
插入数据
INSERT INTO payment_info (id,order_id,payment_status) VALUES (1,101,0);
INSERT INTO payment_info (id,order_id,payment_status) VALUES (2,102,1);
INSERT INTO payment_info (id,order_id ,payment_status) VALUES (3,103,0);
INSERT INTO payment_info (id,order_id,payment_status) VALUES (4,104,1);
INSERT INTO payment_info (id,order_id,payment_status) VALUES (5,-1000,1);
INSERT INTO payment_info (id,order_id,payment_status) VALUES (6,1000,1);
结果dn1存放0-102数据,dn2存放102-200数据,非配置的区间段里的数据落到默认dn1(问题点:物理库还没有创建表的时候,虚拟库通过show tables可以看到配置的表信息)
常用分片规则-日期
修改schema,rule配置
sPartionDay :分区天数,即默认从开始日期算起,分隔 2 天一个分区
重启mycat并创建login_info表
CREATE TABLE login_info
(
id
INT AUTO_INCREMENT comment '编号',user_id
INT comment '用户编号',login_date
date comment '登录日期',PRIMARY KEY(id)
);
插入数据:
INSERT INTO login_info(id,user_id,login_date) VALUES (1,101,'2019-01-01');
INSERT INTO login_info(id,user_id,login_date) VALUES (2,102,'2019-01-02');
INSERT INTO login_info(id,user_id,login_date) VALUES (3,103,'2019-01-03');
INSERT INTO login_info(id,user_id,login_date) VALUES (4,104,'2019-01-04');
INSERT INTO login_info(id,user_id,login_date) VALUES (5,105,'2019-01-05');
INSERT INTO login_info(id,user_id,login_date) VALUES (6,106,'2019-01-06');
INSERT INTO login_info(id,user_id,login_date) VALUES (7,107,'2019-01-07');
结果dn1存放1,2,5,6数据,dn2存放3,4,7数据(问题点:物理库还没有创建表的时候,虚拟库通过show tables可以看到配置的表信息)
全局序列--数据库方式
在 dn1 上创建全局序列表和创建全局序列所需函数(直接在dn1上操作,未验证配置mycat后重新,通过mycat创建是否有效)
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;
DELIMITER
DELIMITER
DELIMITER
初始化序列表记录
INSERT INTO MYCAT_SEQUENCE(NAME,current_value,increment) VALUES ('ORDERS', 400000,100);
修改 Mycat 配置
sequence_db_conf:
插入数据:
insert into orders(id,amount,customer_id,order_type) values(next value for
MYCATSEQ_ORDERS,1000,101,102);验证id从400100开始
基于 HA 机制的 Mycat 高可用(4台机器,10,20,15,16)
15安装 HAProxy:
1准备好HAProxy安装包,传到/opt目录下
2解压到/usr/local/src
sudo tar -zxvf haproxy-1.5.18.tar.gz -C /usr/local/src
3进入解压后的目录,查看内核版本,进行编译
cd /usr/local/src/haproxy-1.5.18
uname -r
sudo make TARGET=linux310 PREFIX=/usr/local/haproxy ARCH=x86_64
TARGET=linux310,内核版本,使用uname -r查看内核,如:3.10.0-514.el7,此时该参数就为linux310;
ARCH=x86_64,系统位数;
PREFIX=/usr/local/haprpxy #/usr/local/haprpxy,为haprpxy安装路径
make视情况按需安装(sudo apt install make)
4编译完成后,进行安装
sudo make install PREFIX=/usr/local/haproxy
5安装完成后,创建目录、创建HAProxy配置文件
mkdir -p /usr/data/haproxy/
sudo vim /usr/local/haproxy/haproxy.conf
6向配置文件中插入以下配置信息,并保存
global
log 127.0.0.1 local0
maxconn 4096
chroot /usr/local/haproxy
pidfile /usr/data/haproxy/haproxy.pid
uid 99
gid 99
daemon
defaults
log global
mode tcp
option abortonclose
option redispatch
retries 3
maxconn 2000
timeout connect 5000
timeout client 50000
timeout server 50000
listen proxy_status
bind :48066
mode tcp
balance roundrobin
server mycat_1 192.168.0.10:8066 check inter 10s
server mycat_2 192.168.0.20:8066 check inter 10s
frontend admin_stats
bind :7777
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
7启动HAProxy
sudo /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/haproxy.conf
8查看haproxy进程 ps -ef|grep haproxy
9打开浏览器访问 http://192.168.0.15:7777/admin,在弹出框输入用户名:admin密码:123123
10验证mycat的高可用和haproxy负载均衡:通过HAProxy访问Mycat:mysql -uuser1 -p556600 -h192.168.0.15 -P 48066
安装配置keepalived此处暂时省略//todo
user 标签权限控制
在 user 标签下的 privileges 标签可以对逻辑库(schema)、表(table)进行精细化的 DML 权限控制
privileges 标签下的 check 属性,如为 true 开启权限检查,为 false 不开启,默认为 false
由于 Mycat 一个用户的 schemas 属性可配置多个逻辑库(schema) ,所以privileges 的下级
SQL拦截
firewall 标签用来定义防火墙,其下
白名单:可以通过设置白名单,实现某主机某用户可以访问 Mycat,而其他主机用户禁止访问
黑名单;可以通过设置黑名单,实现 Mycat 对具体 SQL 操作的拦截,如增删改查等操作的拦截
Mycat-web 配置使用(10号机器)
1.Mycat-web 配置使用
下载安装包http://zookeeper.apache.org/,安装包拷贝到Linux系统/opt目录下,并解压tar -zxvf zookeeper-3.4.11.tar.gz到/usr/local路径下
进入ZooKeeper解压后的配置目录(conf),复制配置文件并改名
cp zoo_sample.cfg zoo.cfg
进入ZooKeeper的命令目录(bin),运行启动命令sudo ./zkServer.sh start
ZooKeeper服务端口为2181,查看服务已经启动
netstat -ant | grep 2181
如报错nohup: 无法运行命令'java': 没有那个文件或目录,把JAVA_HOME配置到zkEnv.sh文件里(JAVA_HOME="/usr/local/.....")
2.Mycat-web 安装
下载安装包http://www.mycat.io/,安装包拷贝到Linux系统/opt目录下,并解压
tar -zxvf Mycat-web-1.0-SNAPSHOT-20170102153329-linux.tar.gz到/usr/local目录下
进入mycat-web的目录下运行启动命令./start.sh &
Mycat-web服务端口为8082,查看服务已经启动
netstat -ant | grep 8082
通过地址访问服务
http://192.168.0.10:8082/mycat/
--最后插一句:如果schema配置文件没有配置表创建在哪个dn数据节点上,默认第一个,其他的不创建该表
---END