mycat是一个开源的数据库中间件,其前身是阿里巴巴的cobar,主要可以实现的功能有读写分离,数据分片(垂直分库,垂直分表,水平分库,水平分表)及多数据源整合。其基本原理主要是拦截要执行的sql语句,该sql的表信息主要是逻辑表信息,依据规则进行分片分析,读写分析,缓存分析等等指定具体的物理表,而后将sql改写分别发送到不一样的数据库上执行,而后获取到结果进行归并,接着就是返回结果(sharding-jdbc原理与其大体相同,思考:mycat是否有绑定功能)。mysql
server.xml: mycat的系统信息等。sql
<user name="mycatUser"> //应用程序中配置的用户名、密码及数据库名称 <property name="password">mycatUserPassword</property> <property name="schema">testdb</property> //指定的schema </user>
schema.xml: 定义逻辑表,表分片节点信息等。数据库
<mycat:schema xmlns:mycat="http://io.mycat/"> <schema name="testdb" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema> //schema name 对应server中配置的schema name dataNode 对应下面dataNode的name <dataNode name="dn1" dataHost="host1" database="testdb"/> //database为物理数据库 dataHost和下面dataHost节点name保持一致 <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="192.168.101:3306" user="root" password="123456"> //写主机的地址 用户名 及密码 <readHost host="hostS1" url="192.168.101.102:3306" user="root" password="123456"/> //读主机的地址 用户名 及密码 </writeHost> </dataHost> //dataHost中 balance的值设置不一样的值,读写负载也不一样 //balance:0 读操做都在写库中 //balance:1 当有多主多从的时候,主之间互为主从,mater1->slave1 master2->slave2 master1和master2互为主备,select会在slave1 master2 slave2随机调用 //balance:2 全部读操做将会在全部数据库中随机执行 //balance:3 全部读操做将会在全部读数据库中执行 //通常使用1或者3,1单主单从 3 多主多从 </mycat:schema>
rule.xml: 定义数据分片信息等。segmentfault
启动在mycat bin目录下执行:缓存
./mycat console(控制台启动) ./mycat start (后台启动)
登陆函数
维护窗口: mysql -umycat -p123456 -P 9066 -h 192.168.101.101 使用窗口: mysql -umycat -p123456 -P 8066 -h 192.168.101.101
mysql主从数据库之间同步是基于mysql本身实现的,教程url
//dataHost中 balance的值设置不一样的值,读写负载也不一样 //balance:0 读操做都在写库中 //balance:1 当有多主多从的时候,主之间互为主从,mater1->slave1 master2->slave2 master1和master2互为主备,select会在slave1 master2 slave2随机调用 //balance:2 全部读操做将会在全部数据库中随机执行 //balance:3 全部读操做将会在全部读数据库中执行 //通常使用1或者3,1单主单从 3 多主多从
单主单从中,若是主挂了,对应业务影响就比较大了,能够采用多主要多从,一个主有多个主的从库,当一个主库挂掉,主的从库就升级为主库继续提供服务,当主库在挂掉后再从新服务就变成了运行中主的从库,当主库挂掉后就可能再次升级为主库。当balance设置为3时候,主的从库就能够做为读取数据的从库。.net
修改上述单主单从配置日志
解除主从关系:code
在从库上执行: stop slave; reset master;
修改单主单从中主的/etc/my.cnf
#在主数据库做为从数据库的时候,也要进行读取中继日志进行写操做 log-slave-updates #自增字段每次自增增加量 auto-increment-increment=2 范围:1---65535 #自增字段起始值 auto-increment-offset=1 范围:1---65535
设置第二台主的/etc/my.cnf
server-id=3 #serverid 不要重复 其余同第一台主的配置 auto-increment-increment=2 #设置同第一台主的配置 auto-increment-offset=2 #这个要设置为2了
第二台从的配置同第一台从的配置
须要修改sever-id=4
重启服务便可
在主数据库建立从库访问的用户,执行show master status;获取日志名及偏移值。
GRANT REPLICATION SLAVE ON *.* TO 'slaveDB'@'%' IDENTIFIED BY '123456'
执行主从同步命令
CHANGE MASTER to MASTER_HOST='主的ip地址', MASTER_USER='主给从访问的用户名', MASTER_PASSWORD='主给从访问的密码', MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=134; #经过在主数据库上show master status;查询到的值
启动slave:start slave;
执行完后,在从的数据库上执行:
show slave status; 查看io及sql状态,若是有错误能够看到错误信息。
上述是设置主与从之间的配置
主与主之间还要进行设置主备:
命令同主从之间的设置,执行命令
CHANGE MASTER to MASTER_HOST='另外一台主的ip地址', MASTER_USER='主给从访问的用户名', MASTER_PASSWORD='主给从访问的密码', MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=134;
执行后在主上执行:start slave;
经过在主数据库上show slave status;查看io及sql执行状态。
另一台主做为这台主的从设置同上述执行命令。
到此,数据库之间的双主双从设置完毕了。
下面配置mycat了:
修改schema.xml
<mycat:schema xmlns:mycat="http://io.mycat/"> <schema name="testdb" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema> //schema name 对应server中配置的schema name dataNode 对应下面dataNode的name <dataNode name="dn1" dataHost="host1" database="testdb"/> //database为物理数据库 dataHost和下面dataHost节点name保持一致 <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="192.168.101:3306" user="root" password="123456"> //第一个写主机的地址 用户名 及密码 <readHost host="hostS1" url="192.168.101.102:3306" user="root" password="123456"/> //第一个读主机的地址 用户名 及密码 </writeHost> <writeHost host="hostM2" url="192.168.103:3306" user="root" password="123456"> //第二个写主机的地址 用户名 及密码 <readHost host="hostS2" url="192.168.101.104:3306" user="root" password="123456"/> //第二个读主机的地址 用户名 及密码 </writeHost> </dataHost> //balance设置为1 //dataHost中 balance的值设置不一样的值,读写负载也不一样 //balance:0 读操做都在写库中 //balance:1 当有多主多从的时候,主之间互为主从,mater1->slave1 master2->slave2 master1和master2互为主备,select会在slave1 master2 slave2随机调用 //balance:2 全部读操做将会在全部数据库中随机执行 //balance:3 全部读操做将会在全部读数据库中执行 //通常使用1或者3,1单主单从 3 多主多从 //writeType 为0表示写操做将会在第一个writeHost中进行,若是第一个writeHost挂掉了,将会在第二个writeHost中进行 为1表示随机在两个writeHost中进行,不要使用要被弃用了 //switchType 1表示自动切换 推荐使用 -1表示不自动切换 2基于mysql主从同步状态切换 </mycat:schema>
在/usr/local/mycat/bin目录下:重启mycat服务 ./mycat console
修改schema.xml文件
<mycat:schema xmlns:mycat="http://io.mycat/"> <schema name="testdb" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">//testdb schema默认dataNode 为dn1 默认访问主库maindb <table name="customer" dataNode="dn2"></table> //设置customer dataNode 为dn2 dn2中指定的数据库为customerdb </schema> <dataNode name="dn1" dataHost="host2" database="maindb"/> //database为物理数据库 dataHost和下面dataHost节点name保持一致 <dataNode name="dn2" dataHost="host1" database="customerdb"/> //垂直分库 <dataHost name="host1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> //只有主库,balance设置为0 <writeHost host="hostM1" url="192.168.101:3306" user="root" password="123456"> </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>//只有主库,balance设置为0 <writeHost host="hostM1" url="192.168.102:3306" user="root" password="123456"> </writeHost> </dataHost> </mycat:schema>
A.字段取余分表: 对订单表依据id进行取余拆分
修改schema.xml文件
<mycat:schema xmlns:mycat="http://io.mycat/"> <schema name="testdb" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">//testdb schema默认dataNode 为dn1 默认访问主库maindb <table name="order" dataNode="dn1,dn2" rule="orderModRule"></table> //设置order表 dataNode 为dn1和dn2 </schema> </mycat:schema>
修改rule.xml文件
<tableRule name="orderModRule"> <rule> <columns>order_id</columns> <algorithm>orderIdModFunction</algrothim> </rule> </tableRule> <function name="orderIdModFunction" class="io.mycat.rount.function.PartatiionByMod"> <count>2</count> //该数目要和dataNode保持一致 </function>
B.关联表(相似sharding-jdbc绑定表):
修改schema.xml
<schema name="testdb" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">//testdb schema默认dataNode 为dn1 默认访问主库maindb <table name="order" dataNode="dn1,dn2" rule="orderModRule"> <childTable name="order_detail" primaryKey="id" joinKey="order_id" parentKey="id"/> //order_detail表中有order_id和order表中的id关联,primaryKey设置的是order_detail的主键,order_id为order_detail表中的字段,id为order表中的主键和order_id对应 </table> //设置order表 dataNode 为dn1和dn2 <table name="address" dataNode="dn1,dn2" type="global"></table> </schema>
C.枚举分片:依据region进行选择dataNode
修改schema.xml
<schema name="testdb" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">//testdb schema默认dataNode 为dn1 默认访问主库maindb <table name="ware_region_info" dataNode="dn1,dn2" rule="sharding_by_region"></table> </schema>
修改rule.xml
<tableRule name=“sharding_by_region”> <rule> <columns>region</columns> <algorithm>shardingByRegionFunction</algorithm> </rule> </tableRule> //指定枚举分片函数 <function name="shardingByRegionFunction" class="io.mycat.route.function.PartitionByFileMap"> <property name="mapFile">region-partition.txt</property> <property name="type">1</property> <property name="defaultNode">0</property> </function> //columns 分片的字段 algorithm 分片函数 //mapFile 映射文件 //type : 0表明为int型号 非0为String //defaultNode 小于0表示不设置默认节点 大于等于0表示设置 若是遇到不认识的枚举值就路由到默认节点
region-partition.txt文件保存在mycat conf目录下,内容以下:
henan=0 shanghai=1
D.全局表(相似sharding-jdbc广播表)
设置地址表在各个数据库中都有写入
在schema.xml文件中增长table type为global
<table name="address" primaryKey="id" type="global" dataNode="dn1,dn2" />
E.范围分片
schema.xml修改同枚举分片,rule.xml以下:
<function name="rangePartitionFunction" class="io.mycat.route.function.AutoPartitionByLong"> <property name="mapFile">rangePartitionFile.txt</property> <property name="defaultNode">0</property> </function> //mapFile:表示配置文件 //defaultNode: 默认节点,0设置默认节点,大于等于0不设置默认节点
rangePartitionFile.txt文件
0-100=0 101-200=1
F.日期分片
schema.xml的修改同上
主要是rule.xml对应函数的设置
<function name="shardingByDate" class="io.mycat.route.function.PartitionByDatat> <property name="dateFormat">yyyy-MM-dd</property> <property name="sBeginDate">2020-01-01</property> <property name="sEndDate">2020-01-04</property> <property name="sPartionDay">2</property> </function> //dateFormat:日期格式 //sBeginDate:开始日期 //sEndDate:结束日期 //sPartionDay:分区天数,即默认从开始日期算起,分隔2天一个分区 //上述demo含义:2020-01-01 2020-01-02 会写入dn1中 2020-01-03 2020-01-04 //会写入到dn2中,若是没有设置结束时间,按道理应该选择dn3,可是没有dn3因此就会报错 //若是设置告终束时间后,到了01-05后会重新循环dn1和dn2,设置告终束时间会保证循环 //插入数据值的格式为2020-01-01
插入sql:insert into(date) values("2020-02-10");
mycat全局序列设置有三种类型:本地文件0,数据库设置1,时间戳2
数据库设置:首先要在数据库中设置全局序列表及函数等,而后在mycat修改server.xml 全局序列表方式为数据库设置方式(值为1),修改sequence_db_conf.properties将设置的表指定到具体的dataNode。
其实现基本原理:将序列信息设置在数据库中,须要序列号的时候每次去数据库查询,每次能够获取必定量的,使用完成后从新请求获取,若是未使用完,服务宕机了,那么一部分序列号就丢弃了。
使用haproxy+keepalived实现高可用