目录

夜雨飘零

记录精彩的程序人生

X

CentOS下安装和使用Mycat实现分布式数据库

前言

在笔者的《在CentOS上使用Nginx和Tomcat搭建高可用高并发网站》这篇文章中,笔者介绍了如何在CentOS上搭建一个可支持高可用高并发的Java web后端服务器。善于思考的读者可能会想到,在上一篇文章中,我们只是实现Java web服务器的分布式来应对高并发,但是高并发对数据库的的负担也是很重的。在上一篇文章中,我们只是使用到一个MySQL服务器,但是但数据量非常大的时候,比如有一千万的用户,如果只有单个数据库存储,那一张用户表就有一千万条数据。庞大的数据量使得我们对数据进行查询的时候非常慢,但出现高并发的时候,大量的查询请求发送到数据库服务器,而数据库来不及响应,随时可能出现数据库崩溃的情况。

面对这个问题,我们使用Mycat来实现分布式数据库,假设我们有两个数据库服务器,那么一千万条的数据分开来存储,这样每个数据库只有五百万条数据,可以大大提高查询速度。如果有更多的数据库服务器,那么每个数据库所需要存储的数据就更少了,查询速度就会更快。基于这一个问题,我们就来学习如何在CentOS下安装和使用Mycat实现分布式数据库。

分布式数据库的整体架构:
这里写图片描述

总体架构

我们使用3个装有CentOS系统机器,这三机器都是在虚拟机上创建的,如果不知道如何安装虚拟机上创建CentOS,可以参考笔者的上一篇文章《在CentOS上使用Nginx和Tomcat搭建高可用高并发网站》来安装这三个虚拟机。下面的这张表就是三个机器的信息和负责的任务。

主机名IP地址数据库名称任务角色
node1192.168.204.121Mycat
node2192.168.204.122db2MySQL
node3192.168.204.123db3MySQL

前提工作

在开始安装之前,我们还要设置一下CentOS的hosts文件,添加我们的IP地址和主机名。三个机器都要设置,主要是node1,如果node1没有设置,Mycat会报错,会报node1: 域名解析暂时失败的错误。如果读者在安装的时候没有修改过主机名,或者没有在/etc/sysconfig/network下修改过主机名,那可以不用做以下的操作。

设置的文件是/etc/hosts,可以使用以下的命令编写:

vim /etc/hosts

node1机器上添加以下信息:

192.168.204.121    node1

同理,node2和node3添加以下信息:

192.168.204.122    node2
192.168.204.123    node3

最后提醒一下,是添加,不是覆盖。

安装MySQL数据库

这一部分我们将介绍在node2和node3机器上安装MySQL数据库。

首先关闭防火墙,方便之后的操作。

service iptables stop

我们可以使用以下命令查看MySQL是否安装了:

rpm -qa | grep mysql

应该会输出一下日志:

[root@localhost ~]# rpm -qa | grep mysql
mysql-libs-5.1.71-1.el6.x86_64

然后我们可以先移除这个MySQL,重新安装一个:

yum -y remove mysql-libs-5.1.71-1.el6.x86_64

移除之前的MySQL之后,可以重新安装MySQL:

yum -y install mysql-server mysql mysql-devel

最后再查看安装情况:

rpm -qa | grep mysql

正常的应该会输出以下信息:

mysql-5.1.73-8.el6_8.x86_64
mysql-libs-5.1.73-8.el6_8.x86_64
mysql-server-5.1.73-8.el6_8.x86_64
mysql-devel-5.1.73-8.el6_8.x86_64

安装完成之后,我们可以对MySQL数据库进行一些配置:

vim /etc/my.cnf

主要也是在[mysqld]下加上下面两个代码,主要是设置编码方式和不区分字母大小写。

default-character-set=utf8
lower_case_table_names=1

修改之后的配置文件如下:

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
default-character-set=utf8
lower_case_table_names=1

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

配置完成之后,我们直接启动MySQL:

service mysqld start

然后我们可以把MySQL服务添加到开机自动启,这样就不用每次都启动了。

chkconfig mysqld on

我们可以使用以下的命令查看是否成功添加到开机服务中了。

chkconfig --list | grep mysqld

设置MySQL数据库的密码:

mysqladmin -u root password 'root'

登录数据库,输入该命令之后还有输入数据库的密码,这个密码就是上面设置的root:

mysql -u root -p

为了让Mycat可以连接MySQL数据库,我们还要设置数据库支持远程连接,在登录数据库之后输入以下两条命令:

mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;
mysql> FLUSH PRIVILEGES;

可以使用以下的命令查看所有的数据库:

mysql> show databases;

这里写图片描述

使用以下的命令可以进入mysql数据库中。

mysql> use mysql;

使用以下命令可以查看该数据库有多少张表。

mysql> show tables;

这里写图片描述

使用以下的查询SQL语句可以查看用户名和对应支持访问的IP地址,因为我们在上面已经设置root用户可以支持远程登录了,所以可以看到有一个root用的host%

mysql> select user,host from user;

这里写图片描述

我们看到有一些host是空用户的,我们可以使用以下的SQL语句删除这个数据。

mysql> delete from user where user="";

再来查询一下,可以看到已经没有了空用户的信息了。

mysql> select user,host from user;

这里写图片描述

然后我们创建一个数据库,node2创建数据库db2,node3创建数据库db3。

mysql> create database db2;
mysql> create database db3;

最后还是使用这个命令可以查看到刚才创建的数据库,node2是db2,node3是db3。

mysql> show databases;

这里写图片描述

然后我们使用这两个数据中都创建一张表,首先是要进行到这个数据库。node2的是db2,node3的是db3。

mysql> use db2;
mysql> use db3;

最后在这两个数据库中都创建一张employee表,结构需要一致,否则会出错的。这个两张是真实表,为什么叫真实表,因为在Mycat中还有一个逻辑表,Mycat中的逻辑表就是指向这两张真实表的。

create table employee(id int not null primary key,name varchar(100),sharding_id int not null);

其中字段sharding_id是为了作分片存储使用的,下面会介绍到。

到这里MySQL数据库的安装和配置就完成了,接下来就是Mycat的安装和配置了。

安装和配置Mycat

在这一部分中,将会介绍Mycat的安装和配置。Mycat主要是接收网站后端操作请求,再去操作各个数据库服务器中的MySQL数据库。接下来的操作在node1下完成。

在操作之前,首先关闭防火墙,方便之后的操作。

service iptables stop

Mycat是一个是免安装的的,首先我们下载Mycat的压缩包,我们的安装路径是/opt/sxt/soft/

cd /opt/sxt/soft/
wget http://dl.mycat.io/Mycat-server-1.4-beta-20150604171601-linux.tar.gz

然后解压Mycat压缩包,会得到一个mycat的文件夹。

tar -zxvf Mycat-server-1.4-beta-20150604171601-linux.tar.gz

Mycat解压就可以使用了,但是我为了方便我们操作Mycat,我们在配置文件上添加环境变量。

vim /etc/profile

添加以下的信息,前两条是添加Mycat的环境变量,第三条是设置开机启动。

export MYCAT_HOME=/opt/sxt/soft/mycat
PATH=$PATH:$MYCAT_HOME/bin

sh $MYCAT_HOME/bin/mycat start

然后为了能够让Mycat正常工作,还要对Mycat进行一些配置,主要配置的文件有schema.xmlserver.xmlrule.xml这个三个文件,其中rule.xml主要是配置规则的,我们直接使用默认的配置文件就行了。所以只配置另外两个配置文件,为了方便以后的使用,我们备份原来的配置文件。

cp $MYCAT_HOME/conf/schema.xml $MYCAT_HOME/conf/schema.xml.tmp
cp $MYCAT_HOME/conf/server.xml $MYCAT_HOME/conf/server.xml.tmp
cp $MYCAT_HOME/conf/rule.xml $MYCAT_HOME/conf/rule.xml.tmp

首先配置schema.xml,这个配置文件主要是设置各个服务器的数据库和对应的表。

vim $MYCAT_HOME/conf/schema.xml

我们清空之前的配置信息,加入下面的的配置信息。清空的快捷键是:把光标移到第一行,在命令状态下输入:.,$d即可,或者是在命令状态下输入dd快速删除一行。这个配置文件是创建逻辑数据库,逻辑数据库中包含逻辑数据表,可以指定这张逻辑数据表在那个真实数据库。通过url访问的真实数据库并找到对应的数据库,如db2和db3。同时还指定插入数据的分片规则是sharding-by-intfile

<?xml version="1.0" encoding="UTF8"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://org.opencloudb/">

    <!-- 设置表的存储方式.schema name="JamesMycatSchema" 与 server.xml中的 JamesMycatSchema 设置一致  -->
    <schema name="JamesMycatSchema" checkSQLschema="false" sqlMaxLimit="100">
        <table name="employee" primaryKey="ID" dataNode="dn2,dn3" rule="sharding-by-intfile" />
    </schema>

    <!--数据节点dn1,对应的主机c1,对应是数据库db1 -->
    <dataNode name="dn2" dataHost="node2" database="db2" />
    <dataNode name="dn3" dataHost="node3" database="db3" />

    <!-- 主机C2-->
    <dataHost name="node2" maxCon="1000" minCon="10" balance="0"
        writeType="0" dbType="mysql" dbDriver="native">
        <heartbeat>select user()</heartbeat>

        <!--mysql数据库的连接串 -->
        <writeHost host="hostM2" url="192.168.204.122:3306" user="root" password="root"></writeHost>
    </dataHost>

    <!-- 主机C3-->
    <dataHost name="node3" maxCon="1000" minCon="10" balance="0"
        writeType="0" dbType="mysql" dbDriver="native">
        <heartbeat>select user()</heartbeat>

        <!--mysql数据库的连接串 -->
        <writeHost host="hostM3" url="192.168.204.123:3306" user="root" password="root"></writeHost>
    </dataHost>

</mycat:schema>

然后是配置server.xml,这个配置文件主要是设置连接Mycat的账号和密码,同时还指定刚才配置的逻辑数据库。

vim $MYCAT_HOME/conf/server.xml

同样我们清空之前的配置信息,加入下面的的配置信息。其中schemas的值是上面配置的逻辑数据库的名称。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://org.opencloudb/">
        <system>
                <property name="defaultSqlParser">druidparser</property>
        </system>

        <user name="mycat">
                <property name="password">123456</property>
                <property name="schemas">JamesMycatSchema</property>
        </user>

</mycat:server>

如果有多个数据库服务器,还要配置插入数据的分片ID,在插入数据的时候,会根据这个ID进行分布存储。我们之所以使用这个分片规则,这个是因为我们在配置schema.xml的时候指定的分片规则是sharding-by-intfile,这个规则我们可以在rule.xml中找到。如下图:
这里写图片描述

这个规则就是根据表中的sharding_id字段分片存储到不同的真实数据表中。这个ID在下面的文件中配置。

vim $MYCAT_HOME/conf/partition-hash-int.txt

比如我们有三个数据库,如果数据中的字段sharding_id的值是10000就存在第一个数据表中,如果是10010就存储在第二个数据表中。多个数据库的话,就以此类推。

10000=0
10010=1

除了sharding-by-intfile规则之外,还有很多种分片存储的规则,比如还有一种比较常用的auto-sharding-long。我们可以看看这个规则:
这里写图片描述

auto-sharding-long这个规则同样有一个配置文件指定分片方式,我们可以以下命令查看:

vim $MYCAT_HOME/conf/autopartition-long.txt

该配置文件的内容如下,根据rule.xml的配置文件指定是数据表的字段idid0到500万的时候,数据存储在第一个数据库中,id500万到1000万的时候,数据存储在第二个数据库中,依次类推。

# range start-end ,data node index 
# K=1000,M=10000.
0-500M=0
500M-1000M=1
1000M-1500M=2

配置完成之后就可以启动Mycat了。

mycat start

启动之后可以使用以下命令查看启动输出的日志。

tail -f $MYCAT_HOME/logs/wrapper.log

正常情况下是输出以下的日志信息,如果输出错误信息,可以根据错误信息定位错误的位置再进行修改。

[root@node1 mycat]# tail -f $MYCAT_HOME/logs/wrapper.log
INFO   | jvm 1    | 2018/06/30 00:15:12 | 	... 7 more
STATUS | wrapper  | 2018/06/30 00:15:14 | <-- Wrapper Stopped
STATUS | wrapper  | 2018/06/30 00:17:42 | --> Wrapper Started as Daemon
STATUS | wrapper  | 2018/06/30 00:17:42 | Launching a JVM...
INFO   | jvm 1    | 2018/06/30 00:17:42 | Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=64M; support was removed in 8.0
INFO   | jvm 1    | 2018/06/30 00:17:44 | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org
INFO   | jvm 1    | 2018/06/30 00:17:44 |   Copyright 1999-2006 Tanuki Software, Inc.  All Rights Reserved.
INFO   | jvm 1    | 2018/06/30 00:17:44 | 
INFO   | jvm 1    | 2018/06/30 00:17:45 | log4j 2018-06-30 00:17:45 [./conf/log4j.xml] load completed.
INFO   | jvm 1    | 2018/06/30 00:17:46 | MyCAT Server startup successfully. see logs in logs/mycat.log

使用以下命令可以查看mycat输出的日志信息。

tail -f $MYCAT_HOME/logs/mycat.log

正常情况下是输出以下信息,如果出现连接数据库不成功的日志,就要查看连接数据库的URL、账号、密码是否正常,又或者是否关闭了防火墙。

[root@node1 mycat]# tail -f $MYCAT_HOME/logs/mycat.log 
06/30 00:17:46.029   INFO [$_NIOREACTOR-0-RW] (GetConnectionHandler.java:66) -connected successfuly MySQLConnection [id=13, lastTime=1530289066029, schema=db3, old shema=db3, borrowed=true, fromSlaveDB=false, threadId=989, charset=utf8, txIsolation=0, autocommit=true, attachment=null, respHandler=null, host=192.168.204.123, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]
06/30 00:17:46.042   INFO [$_NIOREACTOR-0-RW] (GetConnectionHandler.java:66) -connected successfuly MySQLConnection [id=14, lastTime=1530289066042, schema=db3, old shema=db3, borrowed=true, fromSlaveDB=false, threadId=990, charset=utf8, txIsolation=0, autocommit=true, attachment=null, respHandler=null, host=192.168.204.123, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]
06/30 00:17:46.055   INFO [$_NIOREACTOR-0-RW] (GetConnectionHandler.java:66) -connected successfuly MySQLConnection [id=15, lastTime=1530289066055, schema=db3, old shema=db3, borrowed=true, fromSlaveDB=false, threadId=991, charset=utf8, txIsolation=0, autocommit=true, attachment=null, respHandler=null, host=192.168.204.123, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]
06/30 00:17:46.093   INFO [$_NIOREACTOR-0-RW] (GetConnectionHandler.java:66) -connected successfuly MySQLConnection [id=16, lastTime=1530289066093, schema=db3, old shema=db3, borrowed=true, fromSlaveDB=false, threadId=992, charset=utf8, txIsolation=0, autocommit=true, attachment=null, respHandler=null, host=192.168.204.123, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]
06/30 00:17:46.142   INFO [$_NIOREACTOR-0-RW] (GetConnectionHandler.java:66) -connected successfuly MySQLConnection [id=17, lastTime=1530289066131, schema=db3, old shema=db3, borrowed=true, fromSlaveDB=false, threadId=993, charset=utf8, txIsolation=0, autocommit=true, attachment=null, respHandler=null, host=192.168.204.123, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]
06/30 00:17:46.144   INFO [$_NIOREACTOR-0-RW] (GetConnectionHandler.java:66) -connected successfuly MySQLConnection [id=18, lastTime=1530289066144, schema=db3, old shema=db3, borrowed=true, fromSlaveDB=false, threadId=994, charset=utf8, txIsolation=0, autocommit=true, attachment=null, respHandler=null, host=192.168.204.123, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]
06/30 00:17:46.149   INFO [$_NIOREACTOR-0-RW] (GetConnectionHandler.java:66) -connected successfuly MySQLConnection [id=19, lastTime=1530289066149, schema=db3, old shema=db3, borrowed=true, fromSlaveDB=false, threadId=995, charset=utf8, txIsolation=0, autocommit=true, attachment=null, respHandler=null, host=192.168.204.123, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]
06/30 00:17:46.160   INFO [$_NIOREACTOR-0-RW] (GetConnectionHandler.java:66) -connected successfuly MySQLConnection [id=20, lastTime=1530289066160, schema=db3, old shema=db3, borrowed=true, fromSlaveDB=false, threadId=996, charset=utf8, txIsolation=0, autocommit=true, attachment=null, respHandler=null, host=192.168.204.123, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]
06/30 00:17:46.215   INFO [WrapperSimpleAppMain] (PhysicalDBPool.java:301) -init result :finished 10 success 10 target count:10
06/30 00:17:46.215   INFO [WrapperSimpleAppMain] (PhysicalDBPool.java:243) -node3 index:0 init success

Mycat启动完成之后,我们就开始使用连接工具来操作Mycat,笔者使用的是NavicatForMySQL,读者可以根据自己习惯的连接工具来连接各个数据库和Mycat。

我们可以使用NavicatForMySQL来连接Mycat,Mycat的默认端口是8066。
这里写图片描述

我们也可以使用NavicatForMySQL连接MySQL数据库,以下就是我们连接node2和node3的MySQL数据库。
这里写图片描述

连接Mycat之后,可以直接在Mycat上操作数据表。比如我们要插入以下的数据,其中sharding_id就是我们分片存储的ID。

insert into employee(id,name,sharding_id) values(1, 'I am db1',10000);
insert into employee(id,name,sharding_id) values(2, 'I am db2',10010);
insert into employee(id,name,sharding_id) values(3, 'I am db3',10010);
insert into employee(id,name,sharding_id) values(4, 'I am db1',10000);
insert into employee(id,name,sharding_id) values(5, 'I am db2',10010);
insert into employee(id,name,sharding_id) values(6, 'I am db3',10010);

插入数据完成之后,可以在Mycat的逻辑表中看到添加的数据。
这里写图片描述

然后数据被分片存储到node2和node3数据库中,下图是node2数据库表中的数据:
这里写图片描述

下图是node3数据库表中的数据:
这里写图片描述

之后的数据操作,只要对Mycat的逻辑表操作就可以了,操作方式跟操作MySQL数据库一样。但是要注意一点的是,创建数据库和创建数据表都只能在schema.xml上配置,而且Mycat的数据表是逻辑数据表,必须要真实数据库中有对应的数据表。

好了,关于CentOS下安装和使用Mycat实现分布式数据库就介绍到这里。路漫漫其修远兮,吾将上下而求索。

注意

这里要说一下的是,我们为了方便外界可以访问到服务器的端口,我们把防火墙关闭了,但是这种是非常不安全的。所以我们可以单独开放某一端口,比如我们要开放MySQL数据库的3306端口号,操作如下:

编辑防火墙配置文件:

vim /etc/sysconfig/iptables

添加以下信息:

-A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT

如下图所示:
这里写图片描述

保存退出,最后重启防火墙:

service iptables restart

开放其他端口也是同样的操作。

参考资料

  1. https://blog.csdn.net/y534560449/article/details/54095574
  2. https://blog.csdn.net/peppapiggit/article/details/54173486
  3. https://www.cnblogs.com/wanghuaijun/p/6859593.html
  4. https://blog.csdn.net/yinwenjie/article/details/53317948
  5. http://dl.mycat.io/

标题:CentOS下安装和使用Mycat实现分布式数据库
作者:yeyupiaoling
地址:https://yeyupiaoling.cn/articles/1584972765438.html