首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往
清单首页dba文章详情

mysql 高可用技术

MHA原理

mha启动是通过 masterha_manger

1监控 是通过masterha_master_monitor

通过ping_intrval值调整

2选主

判断

先生节点的数组

alive slave 存活 数组

lastest slave 最接近主的数组

candidate slave 备选数组

bad slave 损坏节点

1判断 在最接近主的数组和备选数同出现不在损坏节点 优先选为主节点

2判断 在 最接近主的数组不在损坏节点 选为主节点

3判断 在备选数组不在损坏节点 选为主节点‘

4判断 在存活数组 不在损坏节点选为主节点

3数据补偿

1原主库ssh能连接,截取缺失部分日志scp到各个从库(/var/tmp/xxxx)调用save_binary_logs

2原主库不能ssh 两个从库之间做diff app_diff_relay_logs

4切换

masterha_master_switch

1原来的主从关系要解除

2构建新的主从关系

5应用透明vip 单独去做

master_ip_failover

6故障节点剔除集群

masterha_conf_host

7故障提醒 单独去做

mha搭建

代码语言:javascript
复制
1node软件包要在主从所有节点安装
2mha-manager需要在别的机器安装

1配置关键程序软连接(在mha脚本内调用的是绝对路径所以要做软连接)

ln -s /usr/local/mysql-80/bin/mysqlbinlog /usr/bin/mysqlbinlog

ln -s /usr/local/mysql-80/bin/mysql /usr/bin/mysql

2配置ssh

在主库配置

代码语言:javascript
复制
rm -rf /root/.ssh
ssh-keygen
cd /root/.ssh
mv id_rsa.pub authorized_keys
scp -r /root/.ssh 10.0.0.52:/root
scp -r /root/.ssh 10.0.0.53:/root

各个节点测试不需要输入密码

代码语言:javascript
复制
ssh 10.4.7.11 date
ssh 10.4.7.12 date
ssh 10.4.7.13 date

下载软件

代码语言:javascript
复制
下载mha软件
mha官网:https://code.google.com/archive/p/mysql-master-ha/
github下载地址:https://github.com/yoshinorim/mha4mysql-manager/wiki/Downloads

分版本 主流版本 0.56 0.57 0.58 针对不同的版本mysql

所有节点上传node软件安装和依赖包

代码语言:javascript
复制
yum install perl-DBD-MySQL -y
rpm -ivh mha4mysql-node*.rpm

manage软件安装和依赖包

代码语言:javascript
复制
yum install -y perl-Config-Tiny epel-release perl-Log-Dispatch perl-ParallelForkManager perl-Time-HiRes
rpm -ivh mha4mysql-manager*.rpm

配置manager配置文件

代码语言:javascript
复制
创建目录
mkdir -p /etc/mha 配置文件目录
mkdir -p /var/log/mha/app1
 日志目录
vim /etc/mha/app1.cnf 增加配置文件
[server default] manager 服务相关 
manager_log=/var/log/mha/app1/manager 主程序日志文件
manager_workdir=/var/log/mha/app1  工作路径保存状态和日志文件
master_binlog_dir=/data/binlog/  主库的binlog位置
user=mha  mha内部监控需要创建 数据库用户
password=mha
ping_interval=2 心跳检测,每隔多少秒
repl_password=123 复制用户的用户名和密码
repl_user=repl
ssh_user=root ssh互信
[server1]节点信息 如果好多节点满足条件会按照数字的顺序从小到大选
hostname=10.0.0.51
port=3306
[server2]
hostname=10.0.0.52
candidate_master=1  是否是被选主
port=3306
[server3]
hostname=10.0.0.53
port=3306

创建mha用户
create user mha@'10.4.7.%' identified with mysql_native_password by 'mha';
grant all privileges on *.* to mha@'10.4.7.%';

状态检查
互信检测
masterha_check_ssh --conf=/etc/mha/app1.cnf
主从状态检测
masterha_check_repl --conf=/etc/mha/app1.cnf
启动mha
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null> /var/log/mha/app1/manager.log 2>&1 &
查看mha状态
masterha_check_status --conf=/etc/mha/app1.cnf

mha组件介绍

代码语言:javascript
复制
manager 组件
masterha_manger 启动MHA
masterha_check_ssh 检查MHA的SSH配置状况
masterha_check_repl 检查MySQL复制状况
masterha_master_monitor 检测master是否宕机
masterha_check_status 检测当前MHA运行状态
masterha_master_switch 控制故障转移(自动或者手动)
masterha_conf_host 添加或删除配置的server信息
node 组件
save_binary_logs 保存和复制master的二进
master_ip_failover制日志
apply_diff_relay_logs 识别差异的中继日志事件并将其差异的事件应用于其他的
purge_relay_logs 清除中继日志(不会阻塞SQL线程)

mha配合应用透明

master_ip_failover脚本

代码语言:javascript
复制
需要修改的地方
my $vip = '10.4.7.55/24';
my $key = '1';
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down";
my $ssh_Bcast_arp= "/sbin/arping -I eth0 -c 3 -A 10.4.7.55";
修改mha配置文件
master_ip_failover_script=/usr/local/bin/master_ip_failover
重启mha
masterha_stop --conf=/etc/mha/app1.cnf
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null> /var/log/mha/app1/manager.log 2>&1 &

第一次需要在主库手工设置上vip

代码语言:javascript
复制
ifconfig  eth0:1 10.4.7.51/24
ifconfig  eth0:1 10.4.7.51/24 down 如果不想要基于可以down掉

生产注意:

1. 自带脚本,不能跨网段的,必须在局域网中应用。打通二层网络。而且不是特别稳定。

2. 如果需要跨网段,推荐使用智能DNS。

3. 可以配合ProxySQL类似的中间件,就可以不使用VIP了。

故障提醒send_report脚本

代码语言:javascript
复制
#new_master_host and new_slave_hosts are set only when recovering master succeeded
my ( $dead_master_host, $new_master_host, $new_slave_hosts, $subject, $body );
my $smtp='smtp.qq.com'; 发件箱
my $mail_from='22654481@qq.com';
my $mail_user='22654481';
my $mail_pass='gemghsvgkeyzcagh';
#my $mail_to=['to1@qq.com','to2@qq.com'];
my $mail_to='410846191@qq.com';收件箱

修改mha配置文件
report_script=/usr/local/bin/send_report
重启mha
代码语言:javascript
复制
修复mha
启动原主库
备份新主库数据 然后做主从
CHANGE MASTER TO 
MASTER_HOST='10.4.7.12',
MASTER_USER='repl', 
MASTER_PASSWORD='123', 
MASTER_PORT=3306, 
MASTER_AUTO_POSITION=1;
hma不支持级联主从
需要在mha配置文件把原来的主库加回来mha切换之后会把原来主库信息删除
状态检查
互信检测
masterha_check_ssh --conf=/etc/mha/app1.cnf
主从状态检测
masterha_check_repl --conf=/etc/mha/app1.cnf
启动mha
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null> /var/log/mha/app1/manager.log 2>&1 &
查看mha状态
masterha_check_status --conf=/etc/mha/app1.cnf

mha不会管从节点down不down

日志补偿冗余方案

在异步复制中能规避一定风险

找一台新的节点

会源源不断的拉取主库的日志因为从库会发生业务

binlogserver将近实时拉去主库日志

可以从当前从库的起点拉取就好

查看从库当前拉取的位置

代码语言:javascript
复制
mysql -e "show slave status \G" |grep "Master_Log"

在我们创建好的路径下手动拉取

代码语言:javascript
复制
mysqlbinlog -R --host=主库地址 --user=拉取用户 --paseword= --raw  --stop-never mysql-bin.0002 &

也是异步的过程,理论上是比从库快

配置MHA

代码语言:javascript
复制
vim /etc/mha/app1.cnf
[binlog1] 新增一个标签
no_master=1 不能参与选主
hostname=10.0.0.53 那台机器拉取的
master_binlog_dir=/data/binlog_server/ 拉取的日志路径

重启mha。。。。

binlog server不是100%可靠的 他是模拟io线程的功能异步

代替方案 5.7+gtid+增强半同步

MHA自愈思路

MHA在线手工切换

代码语言:javascript
复制
1先把mha停下来
masterha_stop --conf=/etc/mha/app1.cnf
配置master_ip_online_change_script功能实现
功能: 在线切换时,自动锁原主库,VIP自动切换

修改mha配置文件
master_ip_online_change_script=/usr/local/bin/master_ip_online_change
只切换角色
masterha_master_switch --conf=/etc/mha/app1.cnf --master_state=alive --new_master_host=10.4.7.11 --orig_master_is_new_slave --running_updates_limit=10000
注意提示
FLUSH NO_WRITE_TO_BINLOG TABLES在老主库上执行下可以保证已经提交的日志刷新一边 不在写新的日志
一路yes就好了
后续如果有binlog-server需要重构binlog-server从新主库取日志
启动mha
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null>/var/log/mha/app1/manager.log 2>&1 &
检测mha状态


mha如何防止脑裂

什么是脑裂

多个节点争抢主库角色

网络故障,默认manager是单一心跳检测

读写分离

可以把读的压力分担到从库

proxysql

在应用程序和数据库之间加了一层代理可以把流量转发

在互联网企业读写一般是73分读的请求比较大

一般配合高可用一起用

代码语言:javascript
复制
# 下载proxySQL 
https://proxysql.com/ 
https://github.com/sysown/proxysql/releases

proxysql可以在线操作不需要重启服务

proxysql启动会给我们启动两个端口

代码语言:javascript
复制
tcp        0      0 0.0.0.0:6032  内部管理,通过6032端口           0.0.0.0:*               LISTEN      88723/proxysql      
tcp        0      0 0.0.0.0:6033  对外通过服务,应用服务连接6033端口         0.0.0.0:*               LISTEN      88723/proxysql 

连接proxysql

代码语言:javascript
复制
mysql -uadmin -h127.0.0.1 -padmin -P6032
代码语言:javascript
复制
proxysql库说明
mysql> show databases;
+-----+---------------+-------------------------------------+
| seq | name          | file                                |
+-----+---------------+-------------------------------------+
| 0   | main          |    核心配置库                                 |
| 2   | disk          | /var/lib/proxysql/proxysql.db       | 持久化磁盘的配置
| 3   | stats         |                                     | 统计信息汇总
| 4   | monitor       |                                     | 监控信息收集
| 5   | stats_history | /var/lib/proxysql/proxysql_stats.db |手机的内部功能的历史指标
+-----+---------------+-------------------------------------+

main库核心表

代码语言:javascript
复制
show tables;
+----------------------------------------------------+
| tables                                             |
+----------------------------------------------------+
| global_variables                                   | 系统总配置
| mysql_aws_aurora_hostgroups                        |
| mysql_collations                                   |
| mysql_firewall_whitelist_rules                     |
| mysql_firewall_whitelist_sqli_fingerprints         |
| mysql_firewall_whitelist_users                     |
| mysql_galera_hostgroups                            |
| mysql_group_replication_hostgroups   节点分组信息  把后端服务器分组   简单理解读组写组         |
| mysql_query_rules   指定不同的查询路由到后端不同的服务器列表                                |
| mysql_query_rules_fast_routing                     |
| mysql_replication_hostgroups                       |
| mysql_servers  后端可以连接 mysql服务器的列表                                    |
| mysql_users    配置后端数据库的账号和监控账号                                    |
| proxysql_servers                                   |
| restapi_routes                                     |
| runtime_checksums_values                           |
| runtime_global_variables                           |
| runtime_mysql_aws_aurora_hostgroups                |
| runtime_mysql_firewall_whitelist_rules             |
| runtime_mysql_firewall_whitelist_sqli_fingerprints |
| runtime_mysql_firewall_whitelist_users             |
| runtime_mysql_galera_hostgroups                    |
| runtime_mysql_group_replication_hostgroups         |
| runtime_mysql_query_rules                          |
| runtime_mysql_query_rules_fast_routing             |
| runtime_mysql_replication_hostgroups               |
| runtime_mysql_servers                              |
| runtime_mysql_users                                |
| runtime_proxysql_servers                           |
| runtime_restapi_routes                             |
| runtime_scheduler                                  |
| scheduler                                          |
+----------------------------------------------------+
实际分为两大类 runtime开头是运行时正在用的  不是runtime开头的是可以被修改的

配置流程

配置是分层管理的

分为三层配置结构

runtime 当前在使用的,不可被修改

memory 是runtime的快照 可以被修改

disk 持久化存储

cfg 配置文件

一般都针对memory修改 如何让我们修改的生效呢load加载一下就可以runtime最后还需要save保存

配置

1先去配置一个组

代码语言:javascript
复制
insert into
mysql_replication_hostgroups
(writer_hostgroup, reader_hostgroup, comment)
values (10,20,'proxy');
配置完成后 需要保存一下和加载一下
load mysql servers to runtime;
save mysql servers to disk;

代码语言:javascript
复制
proxysql如何区分是主库和从库呢是通过read_only
需要在加节点之前需要将从库的read_only参数设置上
set global super_read_only=1;
set global super__read_only=1;

添加主机到proxysql

代码语言:javascript
复制
insert into mysql_servers(hostgroup_id,hostname,port) values
(10,'10.4.7.11',3306);
insert into mysql_servers(hostgroup_id,hostname,port) values
(20,'10.4.7.12',3306);
insert into mysql_servers(hostgroup_id,hostname,port) values
(20,'10.4.7.13',3306);
因为我们之前设置了两个组一个读组一个写组
加完之后需要保存一下和加载一下

需要配置一个专用的账号

代码语言:javascript
复制
mysql做
create user monitor@'%' identified with mysql_native_password by '123';
grant replication client on *.* to monitor@'%';

proxysql设置监控用户

代码语言:javascript
复制
set mysql-monitor_username='monitor';
set mysql-monitor_password='123';
做一下配置完成后 需要保存一下和加载一下
load mysql servers to runtime;
save mysql servers to disk;

查询proxysql监控日志

代码语言:javascript
复制
select * from mysql_server_connect_log;查看监控信息
select * from mysql_server_ping_log; 心跳探测
select * from mysql_server_read_only_log; 查看后端那些节点是读节点
select * from mysql_server_replication_lag_log;

配置业务用户需要配置一个业务用户,去数据库上执行相应的操作

代码语言:javascript
复制
数据库配置
create user root@'%' identified with mysql_native_password by '123';
grant all on *.* to root@'%';
insert into mysql_users(username,password,default_hostgroup) values('root','123',10);
proxysql需要配置业务用户,需要配置一个默认组,将来不配置读写分离的规则默认走默认组
insert into mysql_users(username,password,default_hostgroup)
values('root','123',10);
做一下配置完成后 需要保存一下和加载一下
load mysql servers to runtime;
save mysql servers to disk;

早期版本,需要开启事务持续化。 update mysql_users set transaction_persistent=1 where username='root';

load mysql users to runtime;

save mysql users to disk;

需要配置事务走主库

代码语言:javascript
复制
实用的读写规则
insert into
mysql_query_rules(rule_id,active,match_pattern,destination_hostgroup,apply)
values
(1,1,'^select.*for update$',10,1);
insert into
mysql_query_rules(rule_id,active,match_pattern,destination_hostgroup,apply)
values
(2,1,'^select',20,1);
load mysql query rules to runtime;
save mysql query rules to disk;
注: select … for update规则的rule_id必须要小于普通的select规则的rule_id,ProxySQL是根
据rule_id的顺序进行规则匹配。
规则其实就是if的判断从上到下去匹配规则找不到规则默认走detination组
可以写任何的正则
可以将危险操作定义到30号组 一个不存在的组 这样就可以规避一些危险操作
测试
mysql -uroot -p123 -P 6033 -h 127.0.0.1 -e "begin;select @@server_id;commit"

mysql ionndb cluster

mha高可用技术前端会配合proxysql

代码语言:javascript
复制
架构
mysql router 代理路由
mysql shell 集群的管理和配置
mysql group replication mysql计算节点
三个组件组合到一起形成一个集群
计算节点 mysql mysqlsh
管理节点 mysql shell mysql router

数据库分布式架构

代码语言:javascript
复制
1
nginx+php+mysql
2
nginx+php拆分mysql
3访问量上来了
有多套应用连接一套数据库(使用的仍然是一套库)
nginx+php=mysql
nginx+php=mysql
4做高可用架构mha读写分离
主库提供写入,从库提供读取 
5演变单业务单数据库服务(垂直拆分)
应用端拆分不同服务,有不同数据库服务
逻辑拆分
6单业务变得非常高,基于每个业务拆分数据库的热表,每个热表拆分到多个库中
前面加个mycat/shardingjdbc
应用层和数据库之间加入
这种技术检查基于表的垂直拆分
如果单表,较大可以把单表拆分多份,分布到不同的数据库实例(基于表的水平拆分)
维护难度较大,分片较多,扩容新的分片要重新做

mycat

代码语言:javascript
复制
10.4.7.11 3307《---》10.4.7.12 3307
10.4.7.11 3309----》10.4.7.11 3307
10.4.7.12 3309----》10.4.7.12 3307
10.4.7.12:3308 <-----> 10.4.7.11:3308
 10.4.7.12:3310 -----> 10.4.7.12:3308
 10.4.7.11:3310 -----> 10.4.7.11:3308

1安装java环境

代码语言:javascript
复制
yum install -y java

2mycat下载

代码语言:javascript
复制
Mycat-server-xxxxx.linux.tar.gz
http://dl.mycat.org.cn/
解压就用
配置环境变量
export PATH=/data/mycat/bin:$PATH

3mycat配置

代码语言:javascript
复制
mycat start启动
tcp6       0      0 :::8066 对外提供服务端口
tcp6       0      0 :::9066 管理端口
连接
mysql -uroot -p123456 -h 127.0.0.1 -P8066
注: Mycat中使用的是MySQL 5.1版本驱动,连接8.0时
将会失败。
解决方案:
1. 下载更新客户端程序
https://downloads.mysql.com/archives/cj/
2. 连接时添加auth=mysql_native_password参
数
mysql -uroot -p123456 -h10.4.7.11 -P8066 --default-auth=mysql_native_password
3. 更新MySQL客户端命令为8.0之前版

默认只有一个库
show databases;
+----------+
| DATABASE |
+----------+
| TESTDB   |
+----------+

mycat配置

代码语言:javascript
复制
所有的配置都在conf目录
-rwxrwxrwx 1 root root   92 Oct 22  2019 autopartition-long.txt 分片策略传参时候用
-rwxrwxrwx 1 root root   51 Oct 22  2019 auto-sharding-long.txt
-rwxrwxrwx 1 root root   67 Oct 22  2019 auto-sharding-rang-mod.txt
-rwxrwxrwx 1 root root  340 Oct 22  2019 cacheservice.properties
-rwxrwxrwx 1 root root 3338 Oct 22  2019 dbseq.sql
-rwxrwxrwx 1 root root 3532 Oct 22  2019 dbseq - utf8mb4.sql
-rwxrwxrwx 1 root root  446 Oct 22  2019 ehcache.xml
-rwxrwxrwx 1 root root 2454 Dec 30  2019 index_to_charset.properties 将来做从新分片用的
-rwxrwxrwx 1 root root 1285 Oct 22  2019 log4j2.xml
-rwxrwxrwx 1 root root  183 Oct 22  2019 migrateTables.properties
-rwxrwxrwx 1 root root  271 Nov 26  2019 myid.properties
-rwxrwxrwx 1 root root   16 Oct 22  2019 partition-hash-int.txt
-rwxrwxrwx 1 root root  108 Oct 22  2019 partition-range-mod.txt
-rwxrwxrwx 1 root root 5423 Oct 22  2019 rule.xml   分片策略定制
-rwxrwxrwx 1 root root 3080 Dec 30  2019 schema.xml 分片的定制节点配置
-rwxrwxrwx 1 root root  440 Oct 22  2019 sequence_conf.properties
-rwxrwxrwx 1 root root   79 Oct 22  2019 sequence_db_conf.properties
-rwxrwxrwx 1 root root   29 Oct 22  2019 sequence_distributed_conf.properties
-rwxrwxrwx 1 root root   28 Oct 22  2019 sequence_http_conf.properties
-rwxrwxrwx 1 root root   53 Oct 22  2019 sequence_time_conf.properties
-rwxrwxrwx 1 root root 6392 Dec 30  2019 server.xml 是mycat程序配置文件
-rwxrwxrwx 1 root root   18 Oct 22  2019 sharding-by-enum.txt
-rwxrwxrwx 1 root root 4251 Jan  5  2020 wrapper.conf
drwxrwxrwx 2 root root 4096 Mar 26 18:04 zkconf 和zk结合时候用的
drwxrwxrwx 2 root root   36 Mar 26 18:04 zkdownload

日志
-rw-r--r-- 1 root root 119725 Mar 26 18:27 mycat.log 工作过程中出现问题看这个日志
-rw-r--r-- 1 root root      7 Mar 26 18:20 mycat.pid
-rw-r--r-- 1 root root     96 Mar 26 18:20 switch.log
-rw-r--r-- 1 root root    488 Mar 26 18:20 wrapper.log 启动相关日志

mycat读写分离配置文件

代码语言:javascript
复制
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schemaxmlns:mycat="http://io.mycat/">
简称逻辑库应用永远访问的是testdb这个库 应用访问到这个库就会给转接到分片
<schema name="TESTDB"checkSQLschema="false" sqlMaxLimit="100"dataNode="dn1">
1</schema> 三部分构成
2简称分片 对于那个库的读走哪里
<dataNode name="dn1"dataHost="localhost1" database= "world" />
3配置节点信息表示后端节点有那些
<dataHost name="localhost1"maxCon="1000" minCon="10" balance="1"writeType="0" dbType="mysql"dbDriver="native" switchType="1">
<heartbeat>select user()</heartbeat>
配置写节点 虽然有多喝writhost也只有1个提供服务平常作为读操作
<writeHost host="db1"url="10.0.0.51:3307" user="root"password="123">
配置读节点 可以配置多个
<readHost host="db2"url="10.0.0.51:3309" user="root"password="123" />
</writeHost>
</dataHost>
</mycat:schema>

如果写入节点主库宕机从库也不能提供读的服务, 如果故障节点短时间恢复了就会变成被主状态

<dataHost name="localhost1"maxCon="1000" minCon="10" balance="1"writeType="0" dbType="mysql"dbDriver="native" switchType="1">

balance="1" 指的是读操作的负载均衡 默认是轮询

0不开启代表所有操作都在写节点做

2所有读的操作会在读写节点随机

writeType="0" 写的负载均衡

设置为1所有节点都会写入

0只有一台主机会被被写入

switchType="1"

-1代表不自动切换

1默认切换

2 基于mysql主从同步的状态决定是否切换

3基于 pxc mgc 切换机制

minCon="10" mycat在启动后,会在后端节点自动开启连接线程

maxCon="10" 最大并发连接数

sqlMaxLimit="100"仅限于启用,分片之后限制最大查询

代码语言:javascript
复制
mycat垂直分表
test库中有三张表巨大,把这三张表放到单独的分片
当我们访问a表mycat给我们路由到一个分片
当我们访问b表mycat给我们路由到一个分片
当我们访问c表mycat给我们路由到一个分片
简称垂直分表

需要加入两个datahost

代码语言:javascript
复制
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schemaxmlns:mycat="http://io.mycat/">
<schema name="TESTDB"checkSQLschema="false" sqlMaxLimit="100"dataNode="sh1">
查询user表,路由到sh1分片
<table name="user" dataNode="sh1"/>
当问order_t表,路由到sh2分片
<table name="order_t"dataNode="sh2"/>
</schema>
两个分片访问sh1分片路由到oldguo1
<dataNode name="sh1" dataHost="oldguo1"database= "taobao" />
<dataNode name="sh2" dataHost="oldguo2"database= "taobao" />
<dataHost name="oldguo1" maxCon="1000"minCon="10" balance="1" writeType="0"
dbType="mysql" dbDriver="native"switchType="1">
<heartbeat>select user()
</heartbeat>
<writeHost host="db1"url="10.0.0.51:3307" user="root"password="123">
<readHost host="db2"url="10.0.0.51:3309" user="root"password="123" />
</writeHost>
<writeHost host="db3"url="10.0.0.52:3307" user="root"password="123">
<readHost host="db4"url="10.0.0.52:3309" user="root"password="123" />
</writeHost>
</dataHost>
<dataHost name="oldguo2" maxCon="1000"minCon="10" balance="1" writeType="0"dbType="mysql" dbDriver="native"switchType="1">
<heartbeat>select user()
</heartbeat>
<writeHost host="db1"url="10.0.0.51:3308" user="root"password="123">
<readHost host="db2"url="10.0.0.51:3310" user="root"password="123" />
</writeHost>
<writeHost host="db3"url="10.0.0.52:3308" user="root"password="123">
<readHost host="db4"url="10.0.0.52:3310" user="root"password="123" />
</writeHost>
</dataHost>
</mycat:schema>

单表数据巨大水平拆分

把一张完整的表拆成多份,放到不同的分片上

代码语言:javascript
复制
分片策略
范围分片
取模
枚举
日期
hash
分片键 作为分片条件的列
1要选一个分片键,能够使得数据按照这个分片键均匀的分布到分片上
2要看拿什么列做查询多

比如说t3表

1行数比较多 2000w (1-1000wsh1分片 1000w01-2000wsh2分片)

代码语言:javascript
复制
范围分片
1修改schema.xml
加到
按照后面的auto-sharding-long 范围分片 mycat内部定制
<table name="t3" dataNode="sh1,sh2"rule="auto-sharding-long" />
rule.xml 在这个文件里面定制
vim rule.xml
<tableRule name="auto-sharding-long">
<rule>
<columns>id</columns> 分片键
<algorithm>rang-long</algorithm> 算法
</rule>
定制的方法
<function name="rang-long"class="io.mycat.route.function.AutoPartitionByLong">
<property name="mapFile">autopartition.long.txt</property> 定制如何分片
</function> 

vim autopartition-long.txt
如果数字太大
k可以表示1000
可以表示10000
0-10=0 0-10到0号分片
10-20=1 10-20到1号分片

重启mycat
数据需要在两张表都有,只是有不同分段的数据
痛点访问有可能会集中在一个分片上会造成热点分片

取模分片

和分片个数有关

取模是数字列

当前分片键和节点数量取模

取余分片方式:分片键(一个列)与节点数量进行取余,得 到余数,将数据写入对应节点

代码语言:javascript
复制
1修改配置文件
<table name="t4" dataNode="sh1,sh2"rule="mod-long" />
2如何使用看rule.xml
vim rule.xml
<tableRule name="auto-sharding-long">
<rule>
<columns>id</columns> 分片键
<algorithm>mod-long</algorithm> 算法
</rule>
算法和几去取模,就是你的分片有几个
<property name="count">2</property
3重启mycat
mycat restart

月份分片

代码语言:javascript
复制
按照每个月分片
1要在配置文件中加一个
<table name="t4" dataNode="sh1,sh2"rule="sharding-by-month"" />
2查看rule.xml配置文件
<tableRule name="sharding-by-month">
<rule>
<columns>create_time</columns> 分片键
<algorithm>partbymonth</algorithm> 算法
</rule>
</tableRule>


<function name="partbymonth"
class="io.mycat.route.function.PartitionByMonth">
<property name="dateFormat">yyyy-MM-dd</property> 日期格式
<property name="sBeginDate">2020-01-01</property> 设定开始时间
</function>
3各个数据库创建表
4重启mycat

枚举分片(区域分片)
有一列专门存省的
没有定制策略的可以走默认分片
默认只能给数字列做为分片
1vim schema.xml
<table name="t5" dataNode="sh1,sh2"rule="sharding-by-intfile" />

2vim rule.xml
<tableRule name="sharding-by-intfile">
<rule>
<columns>name</columns> 那一列作为分片键
<algorithm>hash-int</algorithm>
</rule>
</tableRule>

<function name="hash-int"class="org.opencloudb.route.function.PartitionByFileMap">
<property name="mapFile">partition-hash-int.txt</property>定制如何分片
<property name="type">1</property> 加这一行就能支持字符串的
</function>

3vim partition-hash-int.txt 配置:
bj=0 北京的走0号分片
sh=1 上海的走1号分片
DEFAULT_NODE=1 来了别的可以走默认分片

4重启mycat


mycat全局表

有一张表会和其他表join

两个表的数据在不同分片会把两个表的数据拿到mycat在进行join

最好设置成全局表

a表做了分片要和t表进行join t表在每个节点是全量的数据

数据库的节点能帮我们做一波join操作会把有关联的数据拿到mycat

带来的压力

存储压力

数据量比较小的表

配置

代码语言:javascript
复制
vim schema.xml
<table name="t_area" primaryKey="id"type="global" dataNode="sh1,sh2" />  设置t_area分布到所有节点类型为全局

er分片

两个表要join按照分片的分片的表去走

b表的数据跟a表指定分片规则走

代码语言:javascript
复制
1vim schema.xml
<table name="a" dataNode="sh1,sh2"rule="mod-long"> 如过调用过需要改个名字
<childTable name="b" joinKey="aid"parentKey="id" />
</table>
2自定制规则
修改rule.xml mod-log分片策略:
vim rule.xml
<tableRule name="mod-long_oldguo"> 如过调用过需要改个名字
<rule>
<columns>id</columns>
<algorithm>modlong_oldguo</algorithm>
</rule>
</tableRule>
<function name="mod-long_oldguo"class="io.mycat.route.function.PartitionByMod"> 如果调用过需要修改名字
<!-- how many data nodes -->
<propertyname="count">2</property> 自己定制方法
</function>

管理类操作

代码语言:javascript
复制
show @@help 查看帮助
在线重新加载配置
reload @@config : schema.xml
reload @@config_all : 所有配置重新加载
sql监控功能 会记录到日志里面
reload @@sqlstat=open | Open real-time sql stat analyzer
reload @@sqlstat=close | Close
real-time sql stat analyzer
查看mycat服务情况
show @@server ;
查看分片DN节点信息
show @@datanode;
show @@datanode where schema = ?;
查看后端节点
show @@datasource
show @@datasource where datanode=sh1;
报告心跳信息
show @@heartbeat
show @@heartbeat.detail where name=?
RS_CODE :
-1:连接失败
1 :连接正常
-2:连接超时
0 :初始化状态
如果节点故障,会有5次检测,失败后则状态为-1。
查看连接信息
show @@connection
关闭连接
kill @@connection id1,id2,...
查看后端连接
show @@backend
查看sql统计

mysql> show @@sql;
mysql> show @@sql_slow;
mysql> show @@sql.sum

日志管理

代码语言:javascript
复制
<asyncRoot level="info"includeLocation="true">
级别:All < Trace < Debug < Info < Warn <Error < Fatal < OFF
调试建议使用 Debug 级别,生产上一般使用 Info级别

vim server.xml

代码语言:javascript
复制
该属性用于字符集设置。
<system>
<property
name="charset">utf8</property>
</system> 按照数据库端设置就行

processors 属性:

代码语言:javascript
复制
该属性主要用于指定系统可用的线程数,默认值为机器
CPU 核心线程数。主要影响 processorBufferPool、
processorBufferLocalPercent、
processorExecutor 属性。NIOProcessor 的个数也
是由这个属性定义的,所以调优的时候可以适当的调高这个
属性
mycat本身可以连接的线程数

processorBufferChunk 属性:

代码语言:javascript
复制
该属性指定每次分配 Socket Direct Buffer 的
大小,默认是 4096 个字节。这个属性也影响 buffer
pool 的长度。如果一次性获取的数过大 buffer 不够用
会经常出现警告,此时可以适当调大。

processorBufferPool 属性:

代码语言:javascript
复制
该属性指定 bufferPool 计算比例值。由于每次执行
NIO 读、写操作都需要使用到 buffer,系统初始化的时
候会建立一定长度的 buffer 池来加快读、写的效率,减
少建立 buffer 的时间。Mycat 中有两个主要的buffer 池:
BufferPool:BufferPool 由
ThreadLocalPool 组合而成,每次从 BufferPool 中
获取 buffer 都会优先获取ThreadLocalPool 中的
buffer,未命中之后才会去获取 BufferPool 中的
buffer。也就是说 ThreadLocalPool 是作为
BufferPool 的二级缓存,每个线程内部自己使用的。
BufferPool 上的 buffer 则是每个 NIOProcessor
都共享的。这个属性的默认值为:
默认bufferChunkSize(4096) * processors属
性 * 1000
BufferPool 的总长度 = bufferPool /
bufferChunk。
若 bufferPool 不是 bufferChunk 的整数倍,
则总长度为前面计算得出的商 + 1
假设系统线程数为 4,其他都为属性的默认值,则:
bufferPool = 4096 * 4 * 1000
BufferPool 的总长度 : 4000 = 16384000 / 4096

processorBufferLocalPercent 属性:

代码语言:javascript
复制
前面提到了 ThreadLocalPool。这个属性就是用来
控制分配这个 pool 的大小用的,这个属性默认值为100。
线程缓存百分比 = bufferLocalPercent /
processors 属性。
例如,系统可以同时运行 4 个线程,使用默认值,则
根据公式每个线程的百分比为 25。最后根据这个百分比来
计算出具体的 ThreadLocalPool 的长度公式如下:
ThreadLocalPool 的长度 = 线程缓存百分比 *
BufferPool 长度 / 100
假设 BufferPool 的长度为 4000,其他保持默认值。
那么最后每个线程建立上的 ThreadLocalPool 的长
度为: 1000 = 25 * 4000 / 100

心跳属性

代码语言:javascript
复制
mycat 中有几个周期性的任务来异步的处理一些我需要的
工作。这些属性就在系统调优的过程中也是比不可少的。
processorCheckPeriod :
清理 NIOProcessor 上前后端空闲、超时和关闭连
接的间隔时间。默认是 1 秒,单位毫秒。
dataNodeIdleCheckPeriod :
对后端连接进行空闲、超时检查的时间间隔,默认是
300 秒,单位毫秒。
dataNodeHeartbeatPeriod :
对后端所有读、写库发起心跳的间隔时间,默认是 10
秒,单位毫秒。

服务相关属性

代码语言:javascript
复制
bindIp :
mycat 服务监听的 IP 地址,默认值为 0.0.0.0。
serverPort :
定义 mycat 的使用端口,默认值为 8066。
managerPort :
定义 mycat 的管理端口,默认值为 9066

Mysql 连接相关属性

代码语言:javascript
复制
packetHeaderSize :
指定 Mysql 协议中的报文头长度。默认 4。
maxPacketSize :
指定 Mysql 协议可以携带的数据最大长度。默认16M。
idleTimeout :
指定连接的空闲超时时间。某连接在发起空闲检查下,
发现距离上次使用超过了空闲时间,那么这个连接会被回
收,就是被直接的关闭掉。默认 30 分钟,单位毫秒。
charset :
连接的初始化字符集。默认为 utf8。
txIsolation :
前端连接的初始化事务隔离级别,只在初始化的时候使
用,后续会根据客户端传递过来的属性对后端数据库连接进
行同步。默认为 REPEATED_READ,设置值为数字默认3。
READ_UNCOMMITTED = 1;
READ_COMMITTED = 2;
REPEATED_READ = 3;
SERIALIZABLE = 4;
sqlExecuteTimeout :
SQL 执行超时的时间,Mycat 会检查连接上最后一次
执行 SQL 的时间,若超过这个时间则会直接关闭这连接。
默认时间为 300 秒,单位秒

逻辑库配置

每次登录mycat都是tsdb

vim server.xml

代码语言:javascript
复制
1schema.xml
<schema name="oldguo"checkSQLschema="false" sqlMaxLimit="100"dataNode="sh1">
</schema>
2server.xml
server.xml
<user name="root" defaultAccount="true">
<propertyname="password">123456</property>
<propertyname="schemas">oldguo</property>
<propertyname="defaultSchema">oldguo</property>
<!--No MyCAT Databaseselected 错误前会尝试使用该schema作为schema,不
设置则为null,报错 -->
<!-- 表级 DML 权限设置 -->
<!--
<privileges check="false">
<schemaname="TESTDB" dml="0110" >
<tablename="tb01" dml="0000"></table>
<tablename="tb02" dml="1111"></table>
</schema>
</privileges>
-->
</user>
<user name="user">
<property
name="password">user</property>
<property
name="schemas">oldguo</property>
<property
name="readOnly">true</property>
<property
name="defaultSchema">oldguo</property>
</user>
reload @@config_all : 所有配置重新加载

新增逻辑库

代码语言:javascript
复制
添加一个逻辑库
schema.xml
<schema name="oldguo"checkSQLschema="false" sqlMaxLimit="100"dataNode="sh1">
</schema>

server.xml
<property
name="schemas">oldguo,oldguo</property>
reload @@config_all : 所有配置重新加载

sequence分布式全局

举报
领券