暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Mycat数据分片

IT那活儿 2024-05-27
245
点击上方“IT那活儿”公众号--专注于企业全栈运维技术分享,不管IT什么活儿,干就完了!!!   



应用场景



Mycat发展到现在,适用的场景已经很丰富,而且不断有新用户给出新的创新性的方案。

以下是几个典型的应用场景:

  • 单纯的读写分离,此时配置最为简单,支持读写分离,主从切换;

  • 分表分库,对于超过1000万的表进行分片,最大支持1000亿的单表分片;

  • 多租户应用,每个应用一个库,但应用程序只连接Mycat,从而不改造程序本身,实现多租户化;

  • 报表系统,借助于Mycat的分表能力,处理大规模报表的统计;

  • 替代Hbase,分析大数据。

作为海量数据实时查询的一种简单有效方案,比如100亿条频繁查询的记录需要在3秒内查询出来结果,除了基于主键的查询,还可能存在范围查询或其他属性查询,此时Mycat可能是最简单有效的选择。

实验目的:

部署后端MMM集群,使用Mycat对写入MMM中的数据进行分片。

注:使用的是表中具有唯一性的字段如id. 身份证号....

例:

  • ID=1分到MMM_server1

  • ID=2分到MMM_server2

  • ID=3分到MMM_server1

  • ID=4分到MMM_server2

部署前端Haproxy,用来监测MMM集群是否正常,并部署Keepalived进行高可用*热备*负载均衡。

实验需求:

  MMM_server1:
    node01  10.15.200.101
    node02  10.15.200.102
    node03  10.15.200.103
  MMM_server2:
    node04  10.15.200.104
    node05  10.15.200.105
    node06  10.15.200.106
  Mycat_server1:
    tracker01  10.15.200.204
  Mycat_server2:
    tracker02  10.15.200.205
  Keepalived主+Haproxy主:
    ha01  10.15.200.115
  Keepalived]从+Haproxy从:
    ha02  10.15.200.118
  VIP:
    10.15.200.116




部署集群



六个节点都要安装相同的集群软件:

#每三个为一个集群。

yum clean all

yum install Percona-XtraDB-Cluster-57 -y

查看安装后是否有配置文件:

[root@node01 ~]# tree etc/percona-xtradb-cluster.conf.d

修改配置文件 #mysqld.cnf

vim /etc/percona-xtradb-cluster.conf.d/mysqld.cnf

[client]

socket=/var/lib/mysql/mysql.sock



[mysqld]

server-id=1

# 集群内所有节点的server-id不能相同

# 只需要修改server-id=x 这一项 node01/node02/node03的server-id依次修改为1 2 3

datadir=/var/lib/mysql

socket=/var/lib/mysql/mysql.sock

log-error=/var/log/mysqld.log

pid-file=/var/run/mysqld/mysqld.pid

log-bin

log_slave_updates

expire_logs_days=7



symbolic-links=0

修改配置文件 # wsrep.cnf

vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf

[mysqld]

wsrep_provider=/usr/lib64/galera3/libgalera_smm.so

# wsrep_cluster_address=gcomm://这一行的内容是三个集群节点的IP地址,用","逗号分隔

wsrep_cluster_address=gcomm://10.15.200.101,10.15.200.102,10.15.200.103

binlog_format=ROW

default_storage_engine=InnoDB

wsrep_slave_threads= 8

wsrep_log_conflicts

innodb_autoinc_lock_mode=2

wsrep_node_address=10.15.200.101 # 当前node节点的ip地址

wsrep_cluster_name=app-cluster

wsrep_node_name=node01 # 当前node节点的节点名称

pxc_strict_mode=ENFORCING

wsrep_sst_method=xtrabackup-v2

wsrep_sst_auth="sstuser:s3cretPass"

在主节点(node01 node04)上启动服务 (node02 03 05 05不是这么的启动服务)

[root@node01 ~]# systemctl start mysql@bootstrap.service

在主节点(node01 node04)上修改root密码并创建同步账号(同步账号需要跟/etc/percona-xtradb-cluster.conf.d/wsrep.cnf的键值wsrep_sst_auth对应)。

注:  # 启动服务时 服务自动生成了一个随机密码 记录在/var/log/mysqld.log之中。

# 用临时密码进行登录:

[root@node01 ~]# mysql -uroot -p`grep "temporary password" /var/log/mysqld.log  | awk '{print $11}'`

# 进行相关密码的修改或授权 (如果密码强度不够 设置复制的密码强度)

mysql> alter user 'root'@'localhost' identified by '123.com';

mysql>
 create user 'sstuser'@'localhost' identified by 's3cretPass';

mysql>
 grant reload, lock tables, replication client, process on *.* to 'sstuser'@'localhost';

mysql>
grant all privileges on *.* to 'root'@'%' identified by '123.com';

mysql>
 flush privileges;

在node02 . node03和node05 . node06上分别启动数据库服务 (用修改好的密码)

[root@node02 ~]# systemctl start mysql

[root@node02 ~]# mysql -uroot -p'123.com'

mysql> show databases;

在任意节点创建一张表, 注意这里创建的表必须有主键, 查看其它节点是否有数据, 有就表示同步完成, 没有的话去看日志/var/log/mysqld.log查找原因。

在node02和node05上创建数据库和表:

[root@node02 ~]#

mysql> create database app;

mysql> use app;

mysql> CREATE TABLE book(

bookid INT PRIMARY KEY COMMENT '图书id',

type VARCHAR(255) NOT NULL COMMENT '类型');

# 在node03和node06上进行校验:

[root@node03 ~]#

mysql>
 use app;

mysql>
 show tables;

mysql>
 select * from book;




部署Mycat



由于mycat是由Java编写,所以需要安装java,并且还需要mariadb数据库命令去连接数据库。

# mycat_server1和mycat_server2都需要安装:

yum -y install mariadb java

# 将mycat的安装包放入服务器或虚拟机中。

# 解压缩:

tar -zxf Mycat-server-1.6.6.1-release-20181031195535-linux.tar.gz

# 切换到mycat的bin路径下并启动:

[root@tracker02 ~]# cd mycat/bin/

[root@tracker02 ~]
# /mycat/bin ]# ./mycat start

#启动后测试是否启动:

[root@tracker02 ~/mycat/bin ]# ./mycat status

Mycat-server is running (4025).

[root@tracker02 ~/mycat/bin ]# ss -anptu |grep 8066

#修改配置文件:

vim /root/mycat/conf/schema.xml
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- mycat 实例逻辑库 -->
<schema name="app" checkSQLschema="true" sqlMaxLimit="100">
<table name="book" primaryKey="id" dataNode="dn1,dn2" rule="role1"/>
<!-- schema name="逻辑库名" checkSQLschema="布尔值,是否拦截SQL语句中mycat相关字段" sqlMaxLimit="SQL返回条数,太大可能会卡死">
  <table name="逻辑表名" primaryKey="主键" dataNode="数据节点" rule="分片规则" / -->

</schema>
<dataNode name="dn1" dataHost="mysql_host1" database="app"/>
<dataNode name="dn2" dataHost="mysql_host2" database="app"/>
<!-- dataNode name="数据节点名" dataHost="集群名" database="实例库"/ -->
<dataHost name="mysql_host1" maxCon="1000" minCon="10" balance="2" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<!-- dataHost name="集群名,供上层使用" maxCon="定义实例连接池的最大连接" minCon="定义实例连接池的最小连接" balance="负载均衡类型
         0 不开启读写分离机制
   1 全部的 readHost 与 writeHost 参与 select 语句的负载均衡
   2 所有读操作都随机的在 writeHost readhost上分发
   3 所有读请求随机的分发到 wiriterHost 对应的 readhost 执行 writerHost 不负担读压力"
              writeType="负载均衡类型
   0 所有写操作发送到配置的第一个 writeHost 第一个挂了切到还生存的第二个writeHost 重新启动后已切换后的为准
   1 所有写操作都随机的发送到配置的 writeHost"
   dbType="指定后端连接的数据库类型"
   dbDriver="指定连接后端数据库使用的Driver或JDBC"
   switchType="
   -1 不自动切换
   1 默认值 自动切换
   2 基于 MySQL 主从同步的状态决定是否切换
    3 基于mysql galary cluster 的切换机制 "
   slaveThreshold="100" -->

<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="10.15.200.101:3306" user="root" password="123.com">
<!-- writeHost host="集群的写入节点" url="IP+port" user="用户名 要和server.xml里的保持一致"
                   password="密码" -->

<!-- can have multi read hosts -->
<readHost host="hostS1" url="10.15.200.102:3306" user="root" password="123.com"/>
<readHost host="hostS2" url="10.15.200.103:3306" user="root" password="123.com"/>
<!-- readHost host="集群的读取节点" url="IP+port" user="用户名 和server.xml里的保持一致" password="密码" / -->
</writeHost>
</dataHost>
<dataHost name="mysql_host2" maxCon="1000" minCon="10" balance="2" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM2" url="10.15.200.104:3306" user="root" password="123.com">
<!-- can have multi read hosts -->
<readHost host="hostS1" url="10.15.200.105:3306" user="root" password="123.com"/>
<readHost host="hostS2" url="10.15.200.106:3306" user="root" password="123.com"/>
</writeHost>
</dataHost>
</mycat:schema>

vim /root/mycat/conf/server.xml
<!-- - - Licensed under the Apache License, Version 2.0 (the "License"); 
  - you may not use this file except in compliance with the License. - You
  may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0
  - - Unless required by applicable law or agreed to in writing, software -
  distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT
  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the
  License for the specific language governing permissions and - limitations
  under the License. -->

<mycat:server xmlns:mycat="http://io.mycat/">
<system>
<property name="nonePasswordLogin">0</property>
<!-- 0为需要密码登陆、1为不需要密码登陆 ,默认为0,设置为1则需要指定默认账户 -->
<property name="useHandshakeV10">1</property>
<property name="useSqlStat">0</property>
<!-- 1为开启实时统计、0为关闭 -->
<property name="useGlobleTableCheck">0</property>
<!-- 1为开启全加班一致性检测、0为关闭 -->
<property name="sequnceHandlerType">2</property>
<property name="subqueryRelationshipCheck">false</property>
<!-- 子查询中存在关联查询的情况下,检查关联字段中是否有分片字段 .默认 false -->
<!-- <property name="useCompression">1</property> -->
<!-- 1为开启mysql压缩协议 -->
<!-- <property name="fakeMySQLVersion">5.6.20</property> -->
<!-- 设置模拟的MySQL版本号 -->
<!-- <property name="processorBufferChunk">40960</property> -->
<!--
  <property name="processors">1</property>
  <property name="processorExecutor">32</property>
    -->

<!-- 默认为type 0: DirectByteBufferPool | type 1 ByteBufferArena | type 2 NettyBufferPool -->
<property name="processorBufferPoolType">0</property>
<!-- 默认是65535 64K 用于sql解析时最大文本长度 -->
<!-- <property name="maxStringLiteralLength">65535</property> -->
<!-- <property name="sequnceHandlerType">0</property> -->
<!-- <property name="backSocketNoDelay">1</property> -->
<!-- <property name="frontSocketNoDelay">1</property> -->
<!-- <property name="processorExecutor">16</property> -->
<!--
      <property name="serverPort">8066</property> <property name="managerPort">9066</property>
      <property name="idleTimeout">300000</property> <property name="bindIp">0.0.0.0</property>
      <property name="frontWriteQueueSize">4096</property> <property name="processors">32</property> -->

<!-- 分布式事务开关,0为不过滤分布式事务,1为过滤分布式事务(如果分布式事务内只涉及全局表,则不过滤),2为不过滤分布式事务,但是记录分布式事务日志 -->
<property name="handleDistributedTransactions">0</property>
<!--
      off heap for merge/order/group/limit 1开启 0关闭
     -->

<property name="useOffHeapForMerge">1</property>
<!--
      单位为m
     -->

<property name="memoryPageSize">64k</property>
<!--
      单位为k
     -->

<property name="spillsFileBufferSize">1k</property>
<property name="useStreamOutput">0</property>
<!--
      单位为m
     -->

<property name="systemReserveMemorySize">384m</property>
<!-- 是否采用zookeeper协调切换 -->
<property name="useZKSwitch">false</property>
<!-- XA Recovery Log日志路径 -->
<!-- <property name="XARecoveryLogBaseDir">./</property> -->
<!-- XA Recovery Log日志名称 -->
<!-- <property name="XARecoveryLogBaseName">tmlog</property> -->
<!-- 如果为 true的话 严格遵守隔离级别,不会在仅仅只有select语句的时候在事务中切换连接 -->
<property name="strictTxIsolation">false</property>
<property name="useZKSwitch">true</property>
</system>
<!-- 全局SQL防火墙设置 -->
<!-- 白名单可以使用通配符%或着* -->
<!-- 例如<host host="127.0.0.*" user="root"/> -->
<!-- 例如<host host="127.0.*" user="root"/> -->
<!-- 例如<host host="127.*" user="root"/> -->
<!-- 例如<host host="1*7.*" user="root"/> -->
<!-- 这些配置情况下对于127.0.0.1都能以root账户登录 -->
<!--
  <firewall>
     <whitehost>
        <host host="1*7.0.0.*" user="root"/>
     </whitehost>
       <blacklist check="false">
       </blacklist>
  </firewall>
   -->

<user name="root" defaultAccount="true">
<property name="password">123.com</property>
<property name="schemas">app</property>
<!-- user name="逻辑用户名,即登录mycat的用户名" defaultAccount="true" -->
<!-- property name="password">逻辑密码,即登录mycat的用户名对应的密码</property -->
<!-- property name="schemas">逻辑数据库,可配置多个,用英文逗号隔开,对应于schema.xml文件中配置的逻辑数据库,两者对应
         </property -->

<!-- 表级 DML 权限设置 -->
<!--
    <privileges check="false">
      <schema name="TESTDB" dml="0110" >
        <table name="tb01" dml="0000"></table>
        <table name="tb02" dml="1111"></table>
      </schema>
    </privileges>
      -->

</user>
</mycat:server>

vim /root/mycat/conf/rule.xml
<!-- - - Licensed under the Apache License, Version 2.0 (the "License"); 
       - you may not use this file except in compliance with the License. - You
  may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0
  - - Unless required by applicable law or agreed to in writing, software -
  distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT
  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the
  License for the specific language governing permissions and - limitations
  under the License. -->

<mycat:rule xmlns:mycat="http://io.mycat/">
<tableRule name="role1">
<rule>
<columns>bookid</columns>
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
<!-- tableRule name="用户标识不同的分表规则 规则名">
        <rule>
           <columns>指定按哪一列进行拆分 主键</columns>
          <algorithm>该属性值为下面function标签中name的属性值,定义了连接表规则的具体的路由算法,多个表规则可以连接到同一个路由算法上
    引用下面的规则</algorithm>
        </rule>
    </tableRule -->

<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<!-- how many data nodes -->
<property name="count">2</property>
</function>
<!-- function name="标识算法的名字" class="指定路由算法具体的类名字">
    <property name="count">具体算法用到的一些属性</property>
  </function -->

</mycat:rule>

# 重启服务并查看状态和端口:

[root@tracker01 ~/mycat/bin]# ./mycat restart

[root@tracker01 ~/mycat/bin]# ./mycat status

[root@tracker01 ~/mycat/bin]# ss -anptu |grep 8066

#进入本地数据库查看数据库并测试:

[root@tracker01 ~/mycat/bin]#mysql -uroot -p123.com -h127.0.0.1 -P8066
mysql> show databases;

#插入四条数据测试:

mysql> use app;

insert into book(bookid,type) value(1,'java');

insert into book(bookid,type) value(2,'java');

insert into book(bookid,type) value(3,'java');

insert into book(bookid,type) value(4,'java');

#到MMM集群中查看数据是否分片:

#node01-03和node04-06:
mysql> use app;
mysql> select * from book;

#清除数据等待下次使用:

mysql>truncate table book


部署Keepalived+Haproxy

#yum安装Keepalived和Haproxy:

yum -y install hapeoxy keepalived

#修改Keepalived主配置文件:

vim /etc/keepalived/keepalived.conf

global_defs {
    router_id ha01.example.cn #ha01为ha01 ha02为ha02
}

vrrp_instance node_http {
    state MASTER #两个都为BACKUP ha01配置为非抢占
    nopreempt #ha01加这一行 ha02不加
    interface ens33
    virtual_router_id 116
    priority 116 #主节点的优先级(1-255之间),备节点的优先级比主节点的低 ha02可以为1-115之间的任意数
    advert_int 1
    authentication 
{
        auth_type PASS
        auth_pass nodehttp
    }
    track_script {
        chk_haproxy ## 检查 HAProxy 服务是否存活
    }
    virtual_ipaddress {
        10.15.200.116
    }
}

#修改hapeoxy主配置文件:

vim /etc/haproxy/haproxy.cfg

global
    log         127.0.0.1 local2
    chroot /var/lib/haproxy
    pidfile /var/run/haproxy.pid
    maxconn 4000
    user haproxy
    group haproxy
    daemon no
defaults
    mode                    tcp
    log                     global
    option dontlognull # 不记录健康检查日志信息
    option http-server-close
    retries 3
    timeout http-request 10s
    timeout queue 1m
    timeout connect 10s
    timeout client 1m
    timeout server 1m
    timeout http-keep-alive 10s
    timeout check 10s
    maxconn 3000

listen admin_stats
        bind 0.0.0.0:80
        mode http
        stats uri /haproxy-status
        stats auth admin:admin

listen mycat_servers 0.0.0.0:8066
   mode tcp
   balance static-rr
  server mycat_01 10.15.200.204:8066 check port 8066 inter 1000 rise 3 fall 3 weight 10
  server mycat_01 10.15.200.205:8066 check port 8066 inter 1000 rise 3 fall 3 weight 10

# 分别启动Keepalived和Haproxy:

systemctl restart haproxy
systemctl restart keepalived

查看漂移IP是否存在:

ip a

#使用漂移IP登录网页查看是否监控两个集群:

http://11.11.11.11/haproxy-status

#在有数据库的主机上使用漂移IP连接数据库:

mysql -uroot -p'123456' -P8066 -h11.11.11.11

#连接上后插入四条数据,查看是否分片:

mysql> use app;

insert into book(bookid,type) value(1,'java');

insert into book(bookid,type) value(2,'java');

insert into book(bookid,type) value(3,'java');

insert into book(bookid,type) value(4,'java');

#到MMM集群中查看数据是否分片:

#node01-3:
mysql>
 use app;
mysql>
 select * from book;

#node04-6:
mysql>
 use app;
mysql>
 select * from book;

至此结束!!!!


END


本文作者:张 任(上海新炬中北团队)

本文来源:“IT那活儿”公众号

文章转载自IT那活儿,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论