如果我有一个32核心的服务器,我就可以实现1个亿的数据分片,我有32核心的服务器么?没有,所以我至今无法实现1个亿的数据库分片。---Mycat's Plan
Mycat是什么?
对于DBA来说,可以这么理解Mycat:
对于软件工程师来说,可以这么理解Mycat:
对于架构师来说,可以这么理解Mycat:
Mycat原理
应用场景
Mycat长期路线图
数据库中间件
逻辑库(schema)
逻辑表(table)
既然有逻辑库,那么就会有逻辑表,分布式数据库中,对应用来说,读写数据的表就是逻辑表。逻辑表,可 以是数据切分后,分布在一个或多个分片库中,也可以不做数据切分,不分片,只有一个表构成。
分片表
<table name=nt_noden primaryKey=nvidn autoincrement=ntruen dataNode=ndn1,dn2n rule=nrule1n />
非分片表
<table name=nt_noden primaryKey=nvidn autoincrement=ntruen dataNode=ndn1" />
ER 表
全局表
分片节点(dataNode)
多租户
1.1 独立数据库
1.2共享数据库,隔离数据架构
共享数据库,共享数据架构
何为数据切分?
简单来说,就是指通过某种特定的条件,将我们存放在同一个数据库中的数据分散存放到多个数据库(主 机)上面,以达到分散单台设备负载的效果。
数据的切分(Sharding )根据其切分规则的类型,可以分为两种切分模式。一种是按照不同的表(或者 Schema )来切分到不同的数据库(主机)之上,这种切可以称之为数据的垂直(纵向)切分;另外一种则是根据表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面,这种切分称之为数据的水平(横向)切分。
垂直切分的最大特点就是规则简单,实施也更为方便,尤其适合各业务之间的耦合度非常低,相互影响很小,业务逻辑非常清晰的系统。在这种系统中,可以很容易做到将不同业务模块所使用的表分拆到不同的数据库中。根据不同的表来进行拆分,对应用程序的影响也更小,拆分规则也会比较简单清晰。
水平切分于垂直切分相比,相对来说稍微复杂一些。因为要将同一个表中的不同数据拆分到不同的据库中,对于应用程序来说,拆分规则本身就较根据表名来拆分更为复杂,后期的数据维护也会更为复杂一些。
垂直切分
|
|
下面来分析下垂直切分的优缺点:
- 拆分后业务清晰,拆分规则明确。
- 系统之间整合或扩展容易。
- 数据维护简单。
- 部分业务表无法join ,只能通过接口方式解决,提高了系统复杂度。
- 受每种业务不同的限制存在单库性能瓶颈,不易扩展跟性能提高。
- 事务处理复杂。由于垂直切分是按照业务的分类将表分散到不同的库,所以有些业务表会过于庞大,存在单库读写与存储瓶颈,所以就需要水平拆分来做解决。
水平切分
几种典型的分片规则包括:
前面讲了垂直切分跟水平切分的不同跟优缺点,会发现每种切分都有缺点,但共同的特点缺点有:
针对数据源管理,目前主要有两种思路:
可能 90%以上的人在面对上面这两种解决思路的时候都会倾向于选择第二种,尤其是系统不断变得庞大复杂的时候。确实,这是一个非常正确的选择,虽然短期内需要付出的成本可能会相对更大一些,但是对整个系统的扩展性来讲,是非常有帮助的数据切分的原则:
数据切分的原则:
安装Mycat
wget https://github.com/MyCATApache/Mycat-download/raw/master/1.5-RELEASE/Mycat-server-1.5.1-RELEASE-20160622153300-linux.tar.gztar zxf Mycat-server-1.5.1-RELEASE-20160622153300-linux.tar.gzmv mycat /application/echo "export PATH=/application/mycat/bin:$PATH">>/etc/profilesource /etc/profileecho $PATH
下载安装JDK
wget http://download.oracle.com/otn-pub/java/jdk/8u91-b14/jdk-8u91-linux-x64.rpmrpm -ivh jdk-8u91-linux-x64.rpm
配置环境变量
echo "export JAVA_HOME=/usr/java/jdk1.8.0_91/" >>/etc/profileecho "export PATH=$JAVA_HOME/bin:/application/mycat/bin/:$PATH">>/etc/profileecho "export CLASSPATH=$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar">>/etc/profilesource /etc/profile[root@Linuxdemo3 ~]# java -versionjava version "1.8.0_91"Java(TM) SE RuntimeEnvironment(build 1.8.0_91-b14)JavaHotSpot(TM)64-BitServer VM (build 25.91-b14, mixed mode)
创建管理用户
主库上对rep和rep_r用户授权如下:用户:rep 密码:oldboy 端口:3306权限:all命令:grant replication slave on test.* to 'rep'@'10.0.0.%' identified by 'oldboy';grant replication slave on test.* to 'rep_r'@'10.0.0.%' identified by 'oldboy';flush privileges;注:为了方便下面的主从切换,两个用户都授予了所有的权限,生产环境尽量不要这样子授权!
[root@Linuxdemo3 mycat]# pwd/application/mycat[root@Linuxdemo3 mycat]# lltotal 24drwxr-xr-x 2 root root 4096Jul 403:13 bindrwxrwxrwx 2 root root 4096Dec13 2015 catletdrwxrwxrwx 2 root root 4096Jul 403:13 confdrwxr-xr-x 2 root root 4096Jul 403:13 libdrwxrwxrwx 2 root root 4096Dec13 2015 logs-rwxrwxrwx 1 root root 219Jun2215:33 version.txt
修改server.xml文件
[root@Linuxdemo3 conf]# vim server.xml</system><user name="rep"><property name="password">oldboy</property><property name="schemas">test</property></user><user name="rep_r"><property name="password">oldboy</property><property name="schemas"> test</property><property name="readOnly">true</property></user>
修改schema.xml文件
[root@Linuxdemo3 conf]# vim schema.xml<?xml version="1.0"?><!DOCTYPE mycat:schema SYSTEM "schema.dtd"><mycat:schema xmlns:mycat="http://org.opencloudb/"><schema name="test" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema><dataNode name="dn1" dataHost="localhost1" database="test"/><dataNode name="dn2" dataHost="localhost1" database=" test "/><dataNode name="dn3" dataHost="localhost1" database=" test "/><dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"><heartbeat>select user()</heartbeat><writeHost host="hostM1" url="10.0.0.202:3306" user="rep"password="oldboy"></writeHost><readHost host="hostS1" url="10.0.0.202:3307" user="rep_r"password="oldboy"/></readHost></dataHost></mycat:schema>
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
需要配置的位置:
balance="1" writeType="0" switchType="1"
balance
writeType
switchType
<writeHost host="hostM1" url="10.0.0.202:3306" user="rep"password="oldboy"><!-- can have multi read hosts --><readHost host="hostS1" url="10.0.0.202:3306" user="rep_r"password="oldboy"/>
启动Mycat
[root@Linuxdemo3 conf]#/application/mycat/bin/mycat startStartingMycat-server...[root@Linuxdemo3 logs]#
mysql -urep -poldboy -h10.0.0.202 -P8066mysql> explain create table company(id int not null primary key,name varchar(100));+-----------+---------------------------------------------------------------------+| DATA_NODE | SQL |+-----------+---------------------------------------------------------------------+| dn1 | create table company(id int not null primary key,name varchar(100)) || dn2 | create table company(id int not null primary key,name varchar(100)) || dn3 | create table company(id int not null primary key,name varchar(100)) |+-----------+---------------------------------------------------------------------+3 rows in set (0.06 sec)mysql> create table company(id int not null primary key,name varchar(100));Query OK, 0 rows affected (1.82 sec)mysql> explain insert into company(id, name) values (100, 'abc');+-----------+---------------------------------------------------+| DATA_NODE | SQL |+-----------+---------------------------------------------------+| dn1 | insert into company(id, name) values (100, 'abc') || dn2 | insert into company(id, name) values (100, 'abc') || dn3 | insert into company(id, name) values (100, 'abc') |+-----------+---------------------------------------------------+3 rows in set (0.00 sec)mysql> insert into company(id, name) values (100, 'abc');Query OK, 1 row affected (0.24 sec)
查看日志

分别在主从库中执行以下命令:
mysql> select * from company where id =100;+-----+------+| id | name |+-----+------+|100| abc |+-----+------+1 row in set(0.00 sec)

mysql> insert into company(id, name) values (4,'abcwq');ERROR 1495(HY000):User readonly#从库只读
主从切换测试
将schema.xml文件做如下修改:
[root@Linuxdemo3 conf]# vim schema.xml<?xml version="1.0"?><!DOCTYPE mycat:schema SYSTEM "schema.dtd"><mycat:schema xmlns:mycat="http://org.opencloudb/"><schema name="test" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema><dataNode name="dn1" dataHost="localhost1" database="test"/><dataNode name="dn2" dataHost="localhost1" database=" test "/><dataNode name="dn3" dataHost="localhost1" database=" test "/><dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"writeType="0" dbType="mysql" dbDriver="native" switchType="2" slaveThreshold="100"><heartbeat>show slave status</heartbeat><writeHost host="hostM1" url="10.0.0.202:3306" user="rep"password="oldboy"></writeHost><readHost host="hostS1" url="10.0.0.202:3307" user="rep_r"password="oldboy"/></readHost><writeHost host="hostM2" url="10.0.0.202:3307" user="rep"password="oldboy"></writeHost></dataHost></mycat:schema>
重启mycat服务
[root@Linuxdemo2 conf]#/application/mycat/bin/mycat restartStoppingMycat-server...StoppedMycat-server.StartingMycat-server...
- [root@Linuxdemo2 conf]#/data/3306/mysql stop
Mycat-Web
安装zookpeer
wget http://mirrors.hust.edu.cn/apache/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar.gztar -xzvf zookeeper-3.4.6.tar.gzcd zookeeper-3.4.6/confcp zoo_sample.cfg zoo.cfgcd zookeeper-3.4.6/bin./zkServer.sh start出现一下信息说明启动成功JMX enabled by defaultUsing config:/usr1/zookeeper/bin/../conf/zoo.cfgStarting zookeeper ... STARTED
安装mycat-web
wget https://github.com/MyCATApache/Mycat-download/raw/master/mycat-web-1.0/Mycat-web-1.0-SNAPSHOT-20160617163048-linux.tar.gztar zxf Mycat-web-1.0-SNAPSHOT-20160617163048-linux.tar.gzcd mycat-web/mycat-web/WEB-INF/classesvim mycat.propertieszookeeper=127.0.0.1:2181sqlonline.server=10.0.0.202cd mycat-web#将start.sh文件中的JVM调整到合适的大小./start.sh ᾒ端口是web端口访问10.0.0.202:8082/mycat即可进入web页面
cd /application/mycat/bin
/application/mycat/bin/xml_to_yaml.sh 根据mycat配置生成 zookeeper yaml 配置工具/application/mycat/bin/init_zk_data.sh 将生成的yaml配置文件导入远程zookeeper/application/mycat/conf/myid.properties zookeeper 路径配置参数信息/application/mycat/conf/zk-create.yaml 自动生成的zk配置1)确认安装好zookeeper 环境2)启动mycat服务,确认本地服务一切正常。3)执行xml_to_yaml.sh脚本(确认本地配置过 JAVA_HOME 和 MYCAT_HOME环境变量,)[root@Linuxdemo3 bin]#./xml_to_yaml.sh4)执行 init_zk_data.sh 脚本,注意下默认情况下脚本会将zookeeper定位在同一台服务器上面,如有需要可以调整下 ZK 的 IP : PORT[root@Linuxdemo3 bin]#./init_zk_data.sh
管理命令与监控
mysql -urep -poldboy -h10.0.0.202-P9066 -Dtest
1、查看所有的命令,如下:
mysql> show @@help;+--------------------------------------+-----------------------------------+| STATEMENT | DESCRIPTION |+--------------------------------------+-----------------------------------+| clear @@slowwhere datanode =? |Clear slow sql by datanode || clear @@slowwhere schema =? |Clear slow sql by schema || kill @@connection id1,id2,... |Kill the specified connections || offline |ChangeMyCat status to OFF || online |ChangeMyCat status to ON || reload @@config |Reload basic config from file || reload @@config_all |Reload all config from file || reload @@route |Reload route config from file || reload @@user |Reload user config from file || rollback @@config |Rollback all config from memory || rollback @@route |Rollback route config from memory || rollback @@user |Rollback user config from memory || show @@backend |Report backend connection status || show @@cache |Report system cache usage || show @@command |Report commands status || show @@connection |Report connection status || show @@connection.sql |Report connection sql || show @@database |Report databases || show @@datanode |Report dataNodes || show @@datanodewhere schema =? |Report dataNodes || show @@datasource |Report dataSources || show @@datasourcewhere dataNode =?|Report dataSources || show @@heartbeat |Report heartbeat status || show @@parser |Report parser status || show @@processor |Report processor status || show @@router |Report router status || show @@server |Report server status || show @@session |Report front session details || show @@slowwhere datanode =? |Report datanode slow sql || show @@slowwhere schema =? |Report schema slow sql || show @@sqlwhere id =? |Report specify SQL || show @@sql.detail where id =? |Report execute detail status || show @@sql.execute |Report execute status || show @@sql.slow |Report slow SQL || show @@threadpool |Report threadPool status || show @@time.current |Report current timestamp || show @@time.startup |Report startup timestamp || show @@version |ReportMycatServer version || stop @@heartbeat name:time |Pause dataNode heartbeat ||switch@@datasource name:index |Switch dataSource
2、更新配置文件
mysql> reload @@config;Query OK,1 row affected (0.13 sec)Reload config success
3、显示mycat数据库的列表,对应的在scehma.xml配置的逻辑库
mysql> show @@database;+----------+| DATABASE |+----------+| oldboy |+----------+1 row in set(0.00 sec)
4、显示mycat数据节点的列表,对应的是scehma.xml配置文件的dataNode节点
mysql> show @@datanode;+------+-------------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+| NAME | DATHOST | INDEX | TYPE | ACTIVE | IDLE | SIZE | EXECUTE | TOTAL_TIME | MAX_TIME | MAX_SQL | RECOVERY_TIME |+------+-------------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+| dn1 | localhost1/oldboy | 0| mysql | 0| 10|1000| 457| 0| 0| 0| -1|| dn2 | localhost1/oldboy | 0| mysql | 0| 10|1000| 457| 0| 0| 0| -1|| dn3 | localhost1/oldboy | 0| mysql | 0| 10|1000| 457| 0| 0| 0| -1|+------+-------------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+3 rows in set(0.00 sec)
5、报告心跳状态
mysql> show @@heartbeat;+--------+-------+-------------+------+---------+-------+--------+---------+--------------+---------------------+-------+| NAME | TYPE | HOST | PORT | RS_CODE | RETRY | STATUS | TIMEOUT | EXECUTE_TIME | LAST_ACTIVE_TIME | STOP |+--------+-------+-------------+------+---------+-------+--------+---------+--------------+---------------------+-------+| hostM1 | mysql |10.0.0.202|3306| 1| 0| idle | 0|1,1,1 |2015-12-2921:39:40|false|| hostS1 | mysql |10.0.0.202|3307| 1| 0| idle | 0|3,3,3 |2015-12-2921:39:40|false|+--------+-------+-------------+------+---------+-------+--------+---------+--------------+---------------------+-------+2 rows in set(0.01 sec)
6、获取当前mycat的版本
mysql> show @@version;+--------------------------------------+| VERSION |+--------------------------------------+|5.5.8-mycat-1.4-alpha-20150520235658|+--------------------------------------+1 row in set(0.00 sec)
7、显示mycat前端连接状态
mysql> show @@connection;+------------+------+-----------+------+------------+--------+---------+--------+---------+---------------+-------------+------------+---------+------------+| PROCESSOR | ID | HOST | PORT | LOCAL_PORT | SCHEMA | CHARSET | NET_IN | NET_OUT | ALIVE_TIME(S)| RECV_BUFFER | SEND_QUEUE | txlevel | autocommit |+------------+------+-----------+------+------------+--------+---------+--------+---------+---------------+-------------+------------+---------+------------+|Processor0| 6|127.0.0.1|9066| 46490| oldboy | utf8:33| 281| 6164| 1008| 4096| 0| | |+------------+------+-----------+------+------------+--------+---------+--------+---------+---------------+-------------+------------+---------+------------+1 row in set(0.00 sec)
8、显示mycat后端连接状态
mysql> show @@backend;+------------+------+---------+-------------+------+--------+--------+---------+------+--------+----------+------------+--------+---------+---------+------------+| processor | id | mysqlId | host | port | l_port | net_in | net_out | life | closed | borrowed | SEND_QUEUE | schema | charset | txlevel | autocommit |+------------+------+---------+-------------+------+--------+--------+---------+------+--------+----------+------------+--------+---------+---------+------------+|Processor0| 1| 30|10.0.0.202|3306| 14881| 3554| 1068|5041|false |false | 0| oldboy | utf8:33|3 |true ||Processor0| 2| 32|10.0.0.202|3306| 14883| 3554| 1068|5041|false |false | 0| oldboy | utf8:33|3 |true ||Processor0| 3| 24|10.0.0.202|3306| 14875| 3515| 1068|5041|false |false | 0| oldboy | utf8:33|3 |true ||Processor0| 4| 28|10.0.0.202|3306| 14879| 3561| 986|5041|false |false | 0| oldboy | utf8:33|0 |true |
9、显示数据源
mysql> show @@datasource;+----------+--------+-------+-------------+------+------+--------+------+------+---------+| DATANODE | NAME | TYPE | HOST | PORT | W/R | ACTIVE | IDLE | SIZE | EXECUTE |+----------+--------+-------+-------------+------+------+--------+------+------+---------+| dn1 | hostM1 | mysql |10.0.0.202|3306| W | 0| 10|1000| 525|| dn1 | hostS1 | mysql |10.0.0.202|3306| R | 0| 8|1000| 522|| dn3 | hostM1 | mysql |10.0.0.202|3306| W | 0| 10|1000| 525|| dn3 | hostS1 | mysql |10.0.0.202|3306| R | 0| 8|1000| 522|| dn2 | hostM1 | mysql |10.0.0.202|3306| W | 0| 10|1000| 525|| dn2 | hostS1 | mysql |10.0.0.202|3306| R | 0| 8|1000| 522|+----------+--------+-------+-------------+------+------+--------+------+------+---------+6 rows in set(0.01 sec)

