MyCat

B 站视频

为什么叫 MyCat 呢 , 难道开发者当时正在 [ 撸猫 ]?

我也想要个 mycat [ 不可描述 ] [ 滑稽 ]

ps: 有点小问题就是 linux 数据库表格区分大小写, 用 mycat 创建的表是大写, 但是 show databases; 是小写, 注意这玩意, 到查表大写. 建议直接配置 mysql 忽略大小写, 我觉得报错你肯定会鬼叫 [ 滑稽 ]

概述

MyCat 概述

附: 配置文件详解

安装启动

安装

  1. 下载安装包

  2. 上传 解压

    tar -zxvf Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz
    
  3. 重要的三个配置文件

    cd mycat/conf
    
    schema.xml     # 定义逻辑库,表,分片节点等内容
    rule.xml        # 定义分片规则
    server.xml      # 定义用户以及系统相关变量,如端口
    

启动

  1. 修改配置文件

    这里首先你得有两台 mysql

    vim server.xml
    
    <!-- 配置 MyCat 用户名 密码 -->
    <user name="mycat" defaultAccount="true"><property name="password">sasa</property><property name="schemas">TESTDB</property><property name="defaultSchema">TESTDB</property>
    </user>
    
    vim schema.xml
    
    <?xml version="1.0"?>
    <!DOCTYPE mycat:schema SYSTEM "schema.dtd">
    <mycat:schema xmlns:mycat="http://io.mycat/"><!-- 相当与一个虚拟数据库,这个库中的表格映射了test库中的表 --><schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema><!-- 数据节点 hadoop01 机器内的 test 数据库 --><dataNode name="dn1" dataHost="hadoop01" database="test" /><dataHost name="hadoop01" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100"><!-- 心跳 --><heartbeat>select user()</heartbeat><!-- 读写分离 --><writeHost host="hostM1" url="hadoop01:3306" user="root" password="sasa"><readHost host="hostS1" url="hadoop02:3306" user="root" password="sasa"></readHost></writeHost></dataHost>
    </mycat:schema>
    
  2. 启动

    控制台启动

    [root@hadoop01 bin]# ./mycat console
    

    后台启动

    [root@hadoop01 bin]# ./mycat start
    

    为了看到日志 这里先 控制台启动
    [ 抱歉已经没有日志在控制台了, 在 log 目录 ]

  3. 登录 MyCat [ 有点意思, 像登录 MySql 一样登录 MyCat 搞得像那个叫非侵入式 ]

    维护窗口

    mysql -umycat -psasa -P 9066 -h hadoop01
    

    数据窗口 [ 登录这个 ]

    mysql -umycat -psasa -P 8066 -h hadoop01
    
  4. 测试

    mysql> show databases;
    +----------+
    | DATABASE |
    +----------+
    | TESTDB   |
    +----------+mysql> use TESTDB;mysql> show tables;
    +------------------+
    | Tables in TESTDB |
    +------------------+
    | user             |
    +------------------+
    

搭建读写分离

一主一从

  1. 主机配置

    # 主服务器唯一 ID
    server-id=1
    # 启用二进制日志
    log-bin=mysql-bin
    # 设置不要复制的数据库
    binlog-ignore-db=mysql
    binlog-ignore-db=infomation_schema
    # 设置需要复制的数据库
    binlog-do-db=test
    # 设置 logbin 格式
    binlog_format=STATEMENT
    

    binlog_format 三种格式

    # master写入执行的SQL语句到binlog中,从库读取这些SQL语句并执行,
    # 这种基于SQL语句的复制方式是MySQL最早支持的复制方式。
    # 缺点 执行某些函数时可能造成主从不一致的情况 如 update ... time=now()
    binlog_format=statement# 可以将master的binlog_format配置成同时使用基于statement和row两者的组合格式,
    # 它记录日志取决于修改的类型,选择合适的格式来记录该修改。
    # 默认情况下使用statement格式记录日志,特定情况下转换成基于row格式记录。
    # 缺点 识别不了特定的名称[系统变量] 如 @@host name
    binlog_format=mixed# MySQL5.7.7版本之后,把binlog_format的默认值修改为了row,
    # master将修改表的event写入binlog中,并且master将该binlog发送给slave,
    # slave重放binlog中的event。基于row格式复制时最安全的复制,slave需要的行锁更少。
    # 复制过程中建议使用row格式,其他格式可能会造成主从数据不一致的情况。
    # 缺点 执行 100 万次更新,会记录一百万次
    binlog_format=row
  2. 从机配置

    # 从机服务器唯一 ID
    server-id=2
    # 启用中继日志
    relay-log=mysql-relay
    
  3. 主从机都关闭防火墙 并 都 重启 mysql 服务

  4. 主机上创建账户 并 授权 slave [ 我这密码肯定是太短了哦会报错, 你可以弄123456 ]

     GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%' IDENTIFIED BY 'sasa';
    
  5. 主机查看状态

    mysql> show master status;
    +------------------+----------+--------------+-------------------------+
    | File             | Position [接入点]| Binlog_Do_DB | Binlog_Ignore_DB |
    +------------------+----------+--------------+-------------------------+
    | mysql-bin.000001 |      1199         | test | mysql,infomation_schema |
    +------------------+----------+--------------+-------------------------+
    
  6. 从机配置需要复制的主机 [ 我这配的密码太短会报错 建议123456 更安全 ]

    CHANGE MASTER TO MASTER_HOST='hadoop01',
    MASTER_USER='slave',
    MASTER_PASSWORD='sasa',                      # 接入点
    MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=1199;
    
  7. 从机执行复制功能

    mysql> start slave;
    
  8. 查看从机服务状态

    mysql> show slave status\G;Slave_IO_Running: YesSlave_SQL_Running: Yes
    
  9. 测试 [ 测试之前把之前建的 test 数据库删除 ]

    因为之前配置日志文件就是 test 数据库

    主机创建 test 数据库和表 从机 会 复制

  10. Questions

    之前搭过从机会报错, 执行 [ 停掉主从复制 ]

    mysql> stop slave;
    mysql> reset master;
    

一主一从配置 MyCat

  1. 启动 修改配置文件

  2. 之前配置的主从复制, MyCat 配置了读写分离 怎么验证?

    # 写主机上插入 [写入主从不一致的情况]
    insert into mytbl values(2,@@hostname);
    # mycat 中查询
    select * from mytbl;
    
  3. 发现 读请求查询出的结果为写主机的名字

    需要修改配置文件 schema.xml

    既然是读写分离 一般设置为 1 或者 3

    负载均衡类型,目前的取值有3种:
    1. balance="0", 不开启读写分离机制,所有读操作都发送到当前可用的 writehost 上。
    2. balance="1",全部的 readhost 与 standby wtirehost 参与select语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且M1与M2互为主备),正常情况下,M2,S1,S2 都参与 select 语句的负载均衡。
    3. balance="2",所以读操作都随机的在 writehost、readhost 上分发。
    4. balance="3",所有读请求随机的分发到 writehost 对应的 readhost 执行,writehost不负担读压力,注意 balance=3 只有1.4及其以后版本有,1.3没有。
    

    为看清效果该处设置为 2

                                                   #[这里!]
    <dataHost name="hadoop01" maxCon="1000" minCon="10" balance="2"writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
    mysql> select * from mytbl;
    +------+----------+
    | id   | name     |
    +------+----------+
    |    1 | zhang3   |
    |    2 | hadoop02 |
    +------+----------+
    2 rows in set (0.08 sec)mysql> select * from mytbl;
    +------+----------+
    | id   | name     |
    +------+----------+
    |    1 | zhang3   |
    |    2 | hadoop01 |
    +------+----------+
    2 rows in set (0.00 sec)
    

双主双从

挨 , 此处需要四台 mysql 有条件的大佬可以搞四台虚拟机

果然穷逼连学习都不配 !

我打算 在 hadoo01 和 hadoop02 上各开一个 mysql 容器 占用 3307 端口

在挂载目录之前还是建议启动个容器把配置文件拷贝到本地, 然后再挂载本地目录
又不会? 还是老老实实搞四个 mysql 吧 [ 滑稽 ]
[ 我这配的密码太短会报错 建议123456 更安全 ]

docker run --name mysql -p 3307:3306 -v /env/mysql/:/etc/mysql -e MYSQL_ROOT_PASSWORD=sasa -d mysql:5.7 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
  1. 从机 停掉之前的 主从 关系

    mysql> stop slave;
    mysql> reset master;
    
  2. hadoop01 master1配置

    # 主服务器唯一 ID
    server-id=1
    # 启用二进制日志
    log-bin=mysql-bin
    # 设置不要复制的数据库
    binlog-ignore-db=mysql
    binlog-ignore-db=infomation_schema
    # 设置需要复制的数据库
    binlog-do-db=test
    # 设置 logbin 格式
    binlog_format=STATEMENT# 在作为从数据库时,有些如操作也要更新二进制文件 [ 防止宕机 ]
    log-slave-updates
    # 表示自增长字段每次递增的量,指字段的其实质,其默认值为 1,取值范围1~65535
    auto-increment-increment=2
    # 表示自增长字段从那个数开始,值子弹一次递增多少,取值范围1~65535
    auto-increment-offset=1
    
  3. hadoop02 master2配置

    # 主服务器唯一 ID
    server-id=2
    # 启用二进制日志
    log-bin=mysql-bin
    # 设置不要复制的数据库
    binlog-ignore-db=mysql
    binlog-ignore-db=infomation_schema
    # 设置需要复制的数据库
    binlog-do-db=test
    # 设置 logbin 格式
    binlog_format=STATEMENT# 在作为从数据库时,有些如操作也要更新二进制文件 [ 防止宕机 ]
    log-slave-updates
    # 表示自增长字段每次递增的量,指字段的其实质,其默认值为 1,取值范围1~65535
    auto-increment-increment=2
    # 表示自增长字段从那个数开始,值子弹一次递增多少,取值范围1~65535
    auto-increment-offset=2
    
  4. 双从机配置 [ 和之前一样 容器下 就是 挂载目录中的 my.cnf ]

    直接添 docker 中有个小错误 开头加上 [mysqld]

    [mysqld]
    # 从机服务器唯一 ID
    server-id=3
    # 启用中继日志
    relay-log=mysql-relay# 从机服务器唯一 ID
    server-id=4
    # 启用中继日志
    relay-log=mysql-relay
    
  5. 重启所有的 mysql 服务

    systemctl restart mysqld
    # 容器中的 mysql 重启
    docker restart mysql
    
  6. 两台 主机 上创建账户 并 授权 slave [ 我这配的密码太短会报错 建议123456 更安全 ]

    GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%' IDENTIFIED BY 'sasa';
    
  7. 两台 slave 配置

    master 接入点查看

    mysql> show master status;
    

    [ MASTER_HOST 这个地方使用 hadoop01 ip 当然你要配置容器主机映射那就写你自己的 ]

    slave hadoop01-docker 从机配置复制

    CHANGE MASTER TO MASTER_HOST='192.168.100.101',
    MASTER_USER='slave',
    MASTER_PASSWORD='sasa',#日志文件看自己的 # 接入点写自己的
    MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=1199;
    

    [ host 这个地方使用 hadoop02 ip ]

    slave hadoop02-docker 从机配置复制

    CHANGE MASTER TO MASTER_HOST='192.168.100.102',
    MASTER_USER='slave',
    MASTER_PASSWORD='sasa',                      # 接入点
    MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=1199;
    

    启动从机

    mysql> start slave;
    

    查看从机服务状态

    mysql> show slave status\G;Slave_IO_Running: YesSlave_SQL_Running: Yes
    
  8. 到此 两套主从复制搭建完毕

    master hadoo01 ------> slave hadoop01-docker

    master hadoo02 ------> slave hadoop02-docker

    现在还差点意思:

    master hadoop01 <-------> master hadoop02

    即 hadoop01 和 hadoop01 互为主从

    # hadoop01 机器执行
    CHANGE MASTER TO MASTER_HOST='hadoop02',
    MASTER_USER='slave',
    MASTER_PASSWORD='sasa',
    MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=764;
    # hadoop02 机器执行
    CHANGE MASTER TO MASTER_HOST='hadoop01',
    MASTER_USER='slave',
    MASTER_PASSWORD='sasa',
    MASTER_LOG_FILE='mysql-bin.000002',MASTER_LOG_POS=764;start slave;
    show slave status\G;ps: 报错处理
    ERROR 1872 (HY000): Slave failed to initialize relay log info structure from the repository
    解决
    mysql> reset slave;
    # 机器再重新执行以上片段
    
  9. 测试 [ 测试之前先删掉 test 库 ]

    hadoop01 hadoop02 任意一个执行

    create database test;
    

双主双从配置 MyCat

schema.xml

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/"><schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema><dataNode name="dn1" dataHost="host1" database="test" /><dataHost name="host1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100"><heartbeat>select user()</heartbeat><writeHost host="hostM1" url="hadoop01:3306" user="root" password="sasa"><readHost host="hostS1" url="hadoop01:3307" user="root" password="sasa"></readHost></writeHost><writeHost host="hostM2" url="hadoop02:3306" user="root" password="sasa"><readHost host="hostS2" url="hadoop02:3307" user="root" password="sasa"></readHost></writeHost></dataHost>
</mycat:schema>

补充

writeType="0", 所有写操作发送到配置的第一个 writeHost,第一个挂了切到还生存的第二个riteHost,重新启动后已切换后的为准,切换记录在配置文件中:dnindex.properties.writeType="1",所有写操作都随机的发送到配置的 writeHost,1.5 以后废弃不推荐。
switchType 属性switchType="-1" 表示不自动切换 mysql 实例switchType="1" 默认值,自动切换

分库 ---- 垂直拆分

ps: 相关的表放在一起

​ 只用 hadoop01 hadoop02 做演示

  1. schema.xml

    <?xml version="1.0"?>
    <!DOCTYPE mycat:schema SYSTEM "schema.dtd">
    <mycat:schema xmlns:mycat="http://io.mycat/"><!-- dataNode 是默认的 数据节点 不配置的表格 默认就是 dn1 的节点--><schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"><!-- customer 这个表格在 节点 2 上 映射到 tesetdb 中--><table name="customer" dataNode="dn2"/></schema><!-- 两个数据库嘛 hadoop01,2 上都要创建 orders 数据库 --><dataNode name="dn1" dataHost="host1" database="orders" /><dataNode name="dn2" dataHost="host2" database="orders"/><!-- 两个数据库 肯定两个 dataHost --><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="hadoop01:3306" user="root" password="sasa"><!-- 就用一个写库测试 balance="0" 就是读写都是这个库 --></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="hostM2" url="hadoop02:3306" user="root" password="sasa"></writeHost></dataHost>
    
  2. 启动 mycat

    bin/mycat start
    
  3. 测试

    mysql -uroot -psasa -P8066 -h hadoop01mysql> use TESTDB;
    # 使用 mycat 创建四个表
    create table customer(
    id int auto_increment,
    name varchar(200),
    primary key(id)
    );create table orders(
    id int auto_increment,
    order_type int,
    customer_id int,
    amount decimal(10,2),
    primary key(id)
    );create table orders_detail(
    id int auto_increment,
    order_id int,
    detail varchar(200),
    primary key(id)
    );create table dict_order_type(
    id int auto_increment,
    order_type varchar(200),
    primary key(id)
    );mysql> show tables;
    +------------------+
    | Tables_in_orders |
    +------------------+
    | customer         |
    | dict_order_type  |
    | orders           |
    | orders_detail    |
    +------------------+# 而 实际上 表 customer 在 hadoop02 机器上
    # 其他表在默认的 hadoop01 机器上
    

分表 ---- 水平拆分

分表实现

ps: 测试表 orders 假设 700w 数据

根据哪个字段拆分? 为什么?

根据 id 问题很大 排在前面的订单相当于历史, 看的人太少, 后面的太多, 会导致有的服务器繁忙,有的无事可做

应该根据 customer_id 划分, 因为同一用户的订单信息在一台机器上, 可以提高查询效率

用 customer_id 取机器数量的模 分配订单

schema.xml

<!-- schema 标签下的 table 标签新增一行 rule 为分片规则 在 rule.xml 中配置 -->
<table name="orders" dataNode="dn1,dn2" rule="mod_rule"/>

role.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">2</property>
</function>

hadoop02 上还没有 orders 表 创建一下

create table orders(
id int auto_increment,
order_type int,
customer_id int,
amount decimal(10,2),
primary key(id)
);

mycat 测试

insert into orders(id,order_type,customer_id,amount) values(1,101,100,81901);
insert into orders(id,order_type,customer_id,amount) values(2,101,100,19201);
insert into orders(id,order_type,customer_id,amount) values(3,101,101,51901);
insert into orders(id,order_type,customer_id,amount) values(4,101,101,19501);
insert into orders(id,order_type,customer_id,amount) values(5,102,101,19061);
insert into orders(id,order_type,customer_id,amount) values(6,102,100,31901);

效果

mysql> select * from orders;
+----+------------+-------------+----------+
| id | order_type | customer_id | amount   |
+----+------------+-------------+----------+
|  1 |        101 |         100 | 81901.00 |
|  2 |        101 |         100 | 19201.00 |
|  6 |        102 |         100 | 31901.00 |
|  3 |        101 |         101 | 51901.00 |
|  4 |        101 |         101 | 19501.00 |
|  5 |        102 |         101 | 19061.00 |
+----+------------+-------------+----------+
6 rows in set (0.03 sec)
mysql> select * from orders order by id; # id 排序

ps: 如果不写 id 的话, 大概 id 也不会重复, 试了七八次 都没重复

分片 join

ps: 上面表分片有点小问题

​ orders 表 分片了,那和他相关的 orders_detail 表未分片, join联查的时候, hadoop01 正常查询出结果, hadoop02 上由于没有 orders_detail 表,则报错, 最后聚合结果肯定也是错误的

ER 表

将子表的存储位置依赖于主表,并且物理上紧邻存放,因此彻底 解决了 JOIN 的效率和性能问题,根据这一思路提出基于 E-R 关系的数据分片策略, 子表的记录与所关联的浮标记录存放在同一个数据分片上,这样关联查询就不需要跨库进行查询。

schema.xml

<table name="orders" dataNode="dn1,dn2" rule="mod_rule"><childTable name="orders_detail" primaryKey="id" joinKey="orde_id" parentKe
y="id" />
</table>

hadoop02 上没有 订单详情表 创建一下

测试 加入数据

insert into orders_detail(detail, order_id) values('detail1',1);
insert into orders_detail(detail, order_id) values('detail1',2);
insert into orders_detail(detail, order_id) values('detail1',3);
insert into orders_detail(detail, order_id) values('detail1',4);
insert into orders_detail(detail, order_id) values('detail1',5);
mysql> select a.*,b.detail from orders a join orders_detail b on a.id=b.order_id;
+----+------------+-------------+----------+---------+
| id | order_type | customer_id | amount   | detail  |
+----+------------+-------------+----------+---------+
|  1 |        101 |         100 | 81901.00 | detail1 |
|  2 |        101 |         100 | 19201.00 | detail1 |
|  7 |        101 |         100 | 81901.00 | detail1 |
|  9 |        101 |         100 | 19201.00 | detail1 |
| 11 |        102 |         100 | 31901.00 | detail1 |
|  3 |        101 |         101 | 51901.00 | detail1 |
|  4 |        101 |         101 | 19501.00 | detail1 |
|  5 |        102 |         101 | 19061.00 | detail1 |
|  8 |        101 |         101 | 19501.00 | detail1 |
| 10 |        102 |         101 | 19061.00 | detail1 |
+----+------------+-------------+----------+---------+
10 rows in set (0.00 sec)

全局表

有个表被遗忘了, 字典表~

这玩意 hadoop01 hadoop02 表都要用

考虑到 字典表 特点

  1. 变动不平凡
  2. 数据量总体不大
  3. 数据规模不大

鉴于此 mycat 定义了一种特别的表, 称为全局表,具有以下特征:

  1. 全局表的插入更新操作会实时在所有节点上执行, 保持哥哥分片的数据一致
  2. 全局表的查询操作,只从一个节点获取
  3. 全局表可以和任何一个表进行 JOIN 操作

schema.xml

schema 标签中增加子标签

<table name="dict_order_type" dataNode="dn1,dn2" type="global"></table>

hadoop02 上无全局表 加上

测试

insert into dict_order_type(id,order_type)values(101,'type1');
insert into dict_order_type(id,order_type)values(102,'type2');mysql> select * from dict_order_type;
+-----+------------+
| id  | order_type |
+-----+------------+
| 101 | type1      |
| 102 | type2      |
+-----+------------+

常用分片规则

取模

对分片字段取模运算.是水平分表常用的规则

分片枚举

通过在配置文件中配置可枚举的 id,自己配置分片, 本规则适用于特定的场景, 比如某些业务需要按照省份区县来做保存,二全国的省份区县是固定的,这类业务使用本条规则

案例

schema.xml

<table name="orders_ware_info" dataNode="dn1,dn2" rule="sharding_by_intfile"></table>

rule.xml

 # 修改<tableRule name="sharding-by-intfile"><rule><columns>areacode</columns><algorithm>hash-int</algorithm></rule></tableRule># 修改<function name="hash-int" class="io.mycat.route.function.PartitionByFileMap"><property name="mapFile">partition-hash-int.txt</property><property name="type">1</property><property name="defaultNode">0</property></function>
# columns 分片字段 , algorithm分片函数
# mapFile 标识配置文件名称
# type 0 int型 1 非 int 型
# defaultNode 默认节点,小于 0 表示不设置默认节点, 大于 0 表示设置默认节点
# 设置默认节点如果碰到不识别的枚举值, 就让它路由到默认节点, 若不设置, 不识别报错

partition-hash-int.txt

110=0
120=1

通过 mycat 创建表

[ linux ] 这里有个大坑 通过 mycat 创建的表, 表名都是大写, 但是在 show tables; 都是小写, sql 语句也必须大写才行 , 不然就报错表格不存在

[ win 没有问题 ]

解决的办法

  1. 都用大写
  2. 配置数据库 忽略 大小写 my.cnf 添加 lower_case_table_names=1 mysql 重启后问题就是已经大写的表就没了, 先重命名再配 [ 滑稽 ]
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)
);

重启 mycat 测试

插入数据

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');

范围约定

该分片适用于,提前规划好某个范围属于哪个分片

shcema.xml

<table name="payment_info" dataNode="dn1,dn2" rule="auto_sharding_long"></table>

rule.xml

修改

<tableRule name="auto_sharding_long"><rule><columns>order_id</columns><algorithm>rang-long</algorithm></rule></tableRule><function name="rang-long" class="io.mycat.route.function.AutoPartitionByLong"><property name="mapFile">autopartition-long.txt</property><property name="defaultNode">0</property></function>

autopartition-long.txt

# range start-end ,data node index
# K=1000,M=10000.
0-102=0
103-200=1

重启 mycat 测试

create table payment_info(
id int auto_increment,
order_id int,
payment_status int,
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,0);
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,0);

按日期 ( 天 ) 分片

schema.xml 添加新表

<table name="login_info" dataNode="dn1,dn2" rule="sharding_by_date"></table>

rule.xml 新增

<tableRule><tableRule name="sharding_by_date"><columns>login_date</columns><algorithm>shardingByDate</algorithm></rule></tableRule><function name="shardingByDate" class="io.mycat.route.function.PartitionByDate"><property name="dateFormat">yyyy-MM-dd</property><property name="sBeginDate">2021-01-18</property><property name="sEndDate">2021-01-20</property><property name="sPartionDay">2</property></function><!--
dateFormat      日期格式
sBeginDate      开始日期
sEndDate        结束日期, 数据达到这个日期的分片后, 循环从开始分片插入
sPartionDay     分区天数, 默认从开始日期算起,分隔两天一个分区
-->

重启 mycat 测试

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,'2021-01-18');
insert into LOGIN_INFO(id,user_id,login_date) values(2,102,'2021-01-19');
insert into LOGIN_INFO(id,user_id,login_date) values(3,103,'2021-01-20');
insert into LOGIN_INFO(id,user_id,login_date) values(4,104,'2021-01-21');
insert into LOGIN_INFO(id,user_id,login_date) values(5,105,'2021-01-22');
insert into LOGIN_INFO(id,user_id,login_date) values(6,106,'2021-01-23');

全局序列

在实现分库分表的情况下, 数据库自增主键已经无法保证自增主键的全局唯一,为此 MyCat 提供了全局 sequence,并且提供了包产本地配置和数据库配置等多种实现方式。

本地文件配置【一般不用】

此方式 MyCat 将 sequence 配置到文件中,当使用到 sequence 中的配置文件后,MyCat 会读取 classpath 中的 sequence_conf.properties 文件中 sequence 当前的值。

优点:本地加载,读取速度快

缺点:抗风险能力差,Mycat 所在主机宕机后,无法读取本地文件。

数据库方式 【常用】

利用数据库中的一个表来进行计数累加,但不是每次生成序列都读取数据库,这样效率太低,MyCat 会预加载一部份号段到 MyCat 内存中,这样大部分读写都是在内存中完成的。

如果内存中的段号用完了 MyCat 会从数据库中再次索要。

如果 MyCat 宕机,内存中的段号丢失,MyCat 重新启动后会向数据库申请新的段号,原有段号会弃用。这样 MyCat 宕机后只是损失当前未用完的号码,而不会出现重复的主键。

  1. 创建序列脚本

    # 在 dn1 上创建全局序列脚本
    DROP TABLE IF EXISTS MYCAT_SEQUENCE;
    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;# 创建全局序列所需函数
    DROP FUNCTION IF EXISTS mycat_seq_currval;
    DELIMITER ;;
    CREATE FUNCTION mycat_seq_currval(seq_name VARCHAR(50)) RETURNS varchar(64) CHARSET utf8
    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 ;
    #-------------
    DROP FUNCTION IF EXISTS mycat_seq_setval;
    DELIMITER ;;
    CREATE FUNCTION mycat_seq_setval(seq_name VARCHAR(50),value INTEGER) RETURNS varchar(64) CHARSET utf8
    DETERMINISTIC
    BEGIN
    UPDATE MYCAT_SEQUENCE
    SET current_value = value
    WHERE name = seq_name;
    RETURN mycat_seq_currval(seq_name);
    END ;;
    DELIMITER ;
    #-------------
    DROP FUNCTION IF EXISTS mycat_seq_nextval;
    DELIMITER ;;
    CREATE FUNCTION mycat_seq_nextval(seq_name VARCHAR(50)) RETURNS varchar(64) CHARSET utf8
    DETERMINISTIC
    BEGIN
    UPDATE MYCAT_SEQUENCE
    SET current_value = current_value + increment WHERE name = seq_name;
    RETURN mycat_seq_currval(seq_name);
    END ;;
    DELIMITER ;
    #-------------
    INSERT INTO MYCAT_SEQUENCE(name,current_value,increment) VALUES ('ORDERS', 100000, 100);
    
  2. 修改 mycat 配置

    # 修改 sequence_db_conf.properties
    # sequence stored in datanode
    GLOBAL=dn1
    COMPANY=dn1
    CUSTOMER=dn1
    ORDERS=dn1
    # 修改 server.xml 改为 1 表示使用数据库方式生成sequence。
    <property name="sequnceHandlerType">1</property>
    

    验证全序列

    # mycat 插入
    insert into orders(id,amount,customer_id,order_type)values(next value for MYCATSEQ_ORDERS,1000,101,102);
    
时间戳方式

优点: 配置简单

缺点: 18 位 有点长

自主生成

在 java 项目中自己生产全局序列:

  • 根据业务逻辑组合
  • 利用 redis 单线程原子性 incr 来生成序列

基于 HA 机制的 MyCat 高可用 方案

使用 HAProxy + Keepalived 配合两台 MyCat 搭建MyCat 集群,实现高可用性。HAProxy实现了 MyCat 多节点的集群到可用和负载均衡,而 HAProxy 自身的高可用则可用 Keepalived 来实现。

安装 HAProxy

  1. 安装

    yum install -y haproxy
    
  2. 创建目录、配置文件

    mkdir -p /env/haproxy/data
    mkdir -p /env/haproxy/confcd /env/haproxy/conf
    vim haproxy.conf
    
    globallog         127.0.0.1 local0chroot      /var/lib/haproxypidfile     /env/haproxy/data/haproxy.pidmaxconn     4000uid         99gid         99daemonstats socket /var/lib/haproxy/statsdefaultsmode                    tcplog                     globaloption                  redispatchretries                 3timeout queue           1mtimeout connect         10stimeout client          1mtimeout server          1mmaxconn                 3000listen proxy_statusbind :48066mode        tcpbalance     roundrobinserver      mycat_1 hadoop01:8066 check inter 10sserver      mycat_2 hadoop02:8066 check inter 10sfrontend  admin_statsbind :7777mode        httpstats       enableoption      httplogmaxconn     10stats       refresh 30sstats       uri /adminstats       auth admin:123123stats       hide-versionstats       admin if TRUE
    
  3. 启动 haproxy

    /usr/sbin/haproxy -f /env/haproxy/conf/haproxy.conf
    
  4. 测试

    http://hadoop01:7777/admin # admin 123123mysql -umycat -psasa -hhadoop01 -P48066
    

  1. hadoop02 一样步骤安装 HAProxy

安装 Keepalived

  1. 安装

    下载 Keepalived

  2. 配置

    # 解压 [ 版本 ][root@hadoop01 env]# tar -zxvf keepalived-2.1.5.tar.gz
    # 进入解压目录 设置安装目录
    [root@hadoop01 keepalived-2.1.5]# ./configure --prefix=/env/keepalived/
    # 编译 安装
    [root@hadoop01 keepalived-2.1.5]# make && make install[root@hadoop01 keepalived]# cp /env/keepalived/etc/keepalived/keepalived.conf  /etc/keepalived/
    [root@hadoop01 keepalived]# cp /env/keepalived/keepalived-2.1.5/keepalived/etc/init.d/keepalived /etc/init.d
    [root@hadoop01 keepalived]# cp /env/keepalived/keepalived-2.1.5/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
    [root@hadoop01 keepalived]# cp /env/keepalived/sbin/keepalived /usr/sbin/[root@hadoop01 conf]# vim /etc/keepalived/keepalived.conf
    
    ! Configuration File for keepalivedglobal_defs {notification_email {something@qq.com}notification_email_from Alexandre.Cassen@firewall.locsmtp_server localhsotsmtp_connect_timeout 30router_id LVS_DEVELvrrp_skip_check_adv_addrvrrp_strictvrrp_garp_interval 0vrrp_gna_interval 0
    }vrrp_instance VI_1 {# 主机配置 masterstate MASTERinterface ens33virtual_router_id 51# 数值越大 优先级越高priority 100advert_int 1authentication {auth_type PASSauth_pass 1111}# 虚拟 ip [ 同网段 ip ]virtual_ipaddress {192.168.100.100}
    }virtual_server 192.168.100.100 48066 {delay_loop 6lb_algo rrlb_kind NATpersistence_timeout 50protocol TCPreal_server 192.168.100.101 48066 {weight 1TCP_CHECK {connect_timeout 3retry 3delay_before_retry 3}}real_server 192.168.100.102 48066 {weight 1TCP_CHECK {connect_timeout 3retry 3delay_before_retry 3}}
    }
    
  3. 测试

    # 启动keepalived
    systemctl start keepalived
    # 测试
    mysql -umycat -psasa -P48066 -h192.168.100.100
    # 任意关闭一个 mycat 不影响系统整体可用性
    
  4. 相同步骤安装 Keepalived 在 hadoop02 上 配置文件中 MASTER 改为 BACKUP

  5. 总结: 其实就是套娃奥, mycat 保证 mysql 集群高可用, haproxy 保证 mycat 高可用, keepalived 保证 haproxy高效可用,当然其实这些都应该分配在不同的节点上奥, 我就两台机器, 那肯定都放两台上了奥

安全设置

配置 server.xml

权限控制

对数据库的权限控制

<!-- 对于数据库的权限设置 -->
<user name="mycat"><property name="password">sasa</property><property name="schemas">TESTDB</property>
</user><user name="user"><property name="password">user</property><property name="schemas">TESTDB</property><!-- 只读权限 --><property name="readOnly">true</property>
</user>

对数据库表的权限控制 privilege 标签

<user name="mycat"><property name="password">user</property><property name="schemas">TESTDB</property><!-- check 检查权限 默认 false --><privilege check="true"><schema name="TESTDB" dml="1111"><table name="orders" dml1="0000"></table></schema></privilege>
</user>

配置说明

DML 权限 增加 更新 查询 删除
四位对应 如 0001 禁止 禁止 禁止 可以

SQL 拦截

firewall 标签用来定义防火墙; Firewall 下 whitehost 标签用来定义 IP 白名单, blacklist 用来定义黑名单 .

白名单

<firewall><whitehost><host host="hadoop01" user="mycat"></host></whitehost>
</firewall>

黑名单

<firewall><whitehost><host host="hadoop01" user="mycat"></host></whitehost><blacklist check="false"><!-- 拦截所有删除操作 --><property name="deleteAll"></property></blacklist>
</firewall>

blacklist 配置详解

监控工具

mycat-web 配置使用

安装 zookeeper

  1. 下载zookeeper

  2. 解压 zookeeper

    tar -zxvf apache-zookeeper-3.6.2-bin.tar.gz -C /env
    # 名字太长 重命名 我一般建立软连接
    cd /env
    link -ls apache-zookeeper-3.6.2-bin/ zookeeper
    
  3. 配置 zookeeper

    # conf 目录下 zoo_samle.cfg 拷贝为 zoo.cfg
    cp zoo_sample.cfg zoo.cfg
    
  4. 启动

    # bin 目录启动
    ./zkServer.sh start
    

安装 mycat-web

  1. 下载 mycat-web [ 尼玛 没找到 官网炸了 炸的干干净净 ]

    笔记还是要做的 [ 滑稽 ]

  2. 解压安装

  3. 启动

    bin/start.sh &
    
  4. 测试

    http://hadoop01:8082/mycat/
    
  5. 配置 zookeeper

    网页面中 配置

    ip hadoop01

    端口 2181

    … 自己看看 ba

MyCat 从入门到放弃相关推荐

  1. mysql 分库分表中间件 mycat_阿里开源的分布式分库分表中间件之MyCat从入门到放弃...

    原标题:阿里开源的分布式分库分表中间件之MyCat从入门到放弃 1.非分片字段查询 Mycat中的路由结果是通过分片字段和分片方法来确定的.例如下图中的一个Mycat分库方案: 根据 tt_waybi ...

  2. mycat 从入门到放弃 (转)

    http://blog.csdn.net/u013235478/article/details/53178657 1.非分片字段查询 Mycat中的路由结果是通过分片字段和分片方法来确定的.例如下图中 ...

  3. MyCat 的入门和放弃

    1.非分片字段查询 Mycat中的路由结果是通过分片字段和分片方法来确定的.例如下图中的一个Mycat分库方案: 根据 tt_waybill 表的 id 字段来进行分片 分片方法为 id 值取 3 的 ...

  4. Mycat从入门到放弃

    当初写这篇文章的初衷只是想提醒自己在用一个开源产品前不仅要了解其提供的功能,更要了解其功能和场景边界. 1.非分片字段查询 Mycat中的路由结果是通过分片字段和分片方法来确定的.例如下图中的一个My ...

  5. AI从入门到放弃2:CNN的导火索,用MLP做图像分类识别?

    来源 | 腾讯知乎专栏 作者 | AIoys(腾讯员工,后台工程师) 项目文档和代码在此:github项目地址: https://github.com/zsysuper/AI_Notes ▌一.前言 ...

  6. AOP埋点从入门到放弃(二)

    其实人最大悲哀莫过于知道自己想要什么,却不知道怎么坚持!最近迷恋上了死侍 其实和我平时的状态差不多,以一个混子的心态去做任何事情,往往成功的概率会更大!!! 一张图片镇楼!!! 上文说到了Aspect ...

  7. 入门到放弃node系列之网络模块(二)

    为什么80%的码农都做不了架构师?>>>    前言 本文首发[一名打字员] 上一节我们刚刚介绍完node的HTTP和HTTPS模块,相信我们也对nodejs有了更深层次的理解,接下 ...

  8. webpack - vue Component 从入门到放弃(三)

    离上一篇已经一个星期了,人的拖延症是没法救的,今晚趁着蒙蒙春雨,来抒发抒发情感. 上一篇简单介绍了webpack的配置,这里稍微再做一一下延伸 插件 插件可以完成更多 loader 不能完成的功能.插 ...

  9. CYQ.Data 从入门到放弃ORM系列:开篇:自动化框架编程思维

    前言: 随着CYQ.Data 开始回归免费使用之后,发现用户的情绪越来越激动,为了保持这持续的激动性,让我有了开源的念头. 同时,由于框架经过这5-6年来的不断演进,以前发的早期教程已经太落后了,包括 ...

最新文章

  1. 测序数据学习笔记:bcl2fastq 安装
  2. 下一个汽车万亿市场打开!氢能源时代正到来
  3. Poj 2503 Babelfish(Map操作)
  4. 关于a标签的href属性的注意事项
  5. 蛮力法 —— 求解迷宫问题 —— DFS和BFS
  6. javascript:typeof与instanceof区别
  7. 高一下学期计算机考试知识点,高中数学知识点总结
  8. java 病毒查杀_Java清除exe文件中的病毒
  9. ubuntu 查看cpu运行频率_ubuntu cpu频率控制
  10. 编程工具│Fiddler 抓包 mumu 模拟器详细配置步骤
  11. Dima and Lisa
  12. 如何用人工的方式将Excel里的一堆数字变成一个数组
  13. button渐变色 ios_UIButton 背景色渐变动画
  14. WGCNA那么多图,都啥意思? 官网
  15. C++实现DLL注入的完整过程
  16. 多语种互译批量中英文翻译插件
  17. 贝壳找房校招java笔试题_2020年最新贝壳找房java面试题分享
  18. python词云图代码示例 无jieba_Python爬虫入门-jieba库制作词云图
  19. opencv调用basler简单示例
  20. 你造吗,Oracle SQLplus 也有History命令了

热门文章

  1. 检索 COM 类工厂中 CLSID 为{00024500-0000-0000-C000-000000000046} 的组件失败,原因是出现以下错误:80070005 拒绝访问
  2. Scrapy笔记(2)——使用正则表达式提取jQuery文档内容
  3. 福克斯保养注意事项及驾驶技巧
  4. 2016012025 童宇欣 散列函数的应用及其安全性
  5. 基于Keras搭建LSTM网络实现文本情感分类
  6. php面试题10(复习)
  7. 全国计算机等级考试四级软件测试工程师,计算机等级考试四级软件测试工程师过关总结...
  8. 淘宝天猫评价采集软件淘宝-
  9. java笔试-小红书秋招笔试-9.6(子矩阵索引、未出现的最小自然数、航海危险区)
  10. 杭州银行与阿里云达成战略合作 将阿里云定义为首选云服务商