mycat分库、分片、分表、读写分离、主从复制、性能监控-对mycat彻底掌握

前言

1:Mycat是这些年国内最活跃的、彻底开源的数据库中间件(介于数据库与应用之间),Mycat命名主要简单好记,另外希望能入驻Apache,膜拜开源产品Tomcat,也是一只猫。
2:行业内数据库中间件:Atlas+Kingshard-360公司,cobar-阿里巴巴B2B,TDDL-淘宝,heisenberg-百度,Oceanus-58同城,vitess-Youtube,OneProxy-支付宝,MySQL Route-Mysql官方。

本篇博客主要分下面几个章节
第一章:不使用任何数据库中间件如何进行分表操作
第二章:Mycat全局自增主键的几种方式
第三章:分库 + 分片即分实例 + 分表实战
第四章:RULE分表规则函数详解
第五章:基于主从复制的读写分离实战
第六章:SQL关联查询及ER分片设计
第七章:Mycat监控系统介绍及使用
第八章:实战过程中踩过的坑及问题汇总
第九章:以Mycat为代表的数据库中间件优点和缺陷

第一章:不使用任何数据库中间件如何进行分表操作

《1》:分表目的减小数据库的负担,提高查询效率,可分为水平分割 和 垂直分割。

1:水平分割:数据条数可以按ID范围,时间范围等横向存放到N个表中。
   优点:降低索引的层数,提高查询速度。
   缺点:分页或全量查询时,Union操作会增加索引层读取复杂度,降低查询速度。
2:垂直分割:表字段横向的切分,通过主键字段来建立关系。
   优点:数据量分表的同时,查询也减少了I/O次数。
   缺点:需管理冗余列字段,查询所有数据需Join操作。 
  
《2》:水平分割实战应用

1:创建表 COST00,COST01,COST02…COST18,COST19总20张表

CREATE TABLE COST00 (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id))  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
CREATE TABLE COST01 (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id))  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
CREATE TABLE COST02 (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id))  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
CREATE TABLE COST03 (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id))  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
CREATE TABLE COST04 (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id))  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
CREATE TABLE COST05 (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id))  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
CREATE TABLE COST06 (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id))  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
CREATE TABLE COST07 (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id))  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
CREATE TABLE COST08 (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id))  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
CREATE TABLE COST09 (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id))  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
CREATE TABLE COST10 (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id))  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
CREATE TABLE COST11 (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id))  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
CREATE TABLE COST12 (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id))  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
CREATE TABLE COST13 (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id))  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
CREATE TABLE COST14 (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id))  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
CREATE TABLE COST15 (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id))  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
CREATE TABLE COST16 (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id))  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
CREATE TABLE COST17 (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id))  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
CREATE TABLE COST18 (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id))  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
CREATE TABLE COST19 (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id))  ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

2:确定分表因子及方式,id或time等,hash或range等规则,获取表名进行CRUD操作。

/**
* 根据id取模获取表名,进行查询、删除、保存、修改操作。
* 
* @param table 表名
* @param id 分表因子
* @return
*/
public static String tableName(String table, String id){
   
  int mod = Integer.parseInt(id) % 20;
  String tableName = table;
  if (mod > -1) {
   
      if (mod < 10) {
   
          tableName = tableName.concat("0").concat(String.valueOf(mod));
      } else {
   
          tableName = tableName.concat(String.valueOf(mod));
      }
  }
  return tableName;
}

3:查询全部数据时有下面两种方式解决

方式一:利用Mysql的Merge存储引擎来实现,但对创建的主表和N个分表有要求。

CREATE TABLE COST_ALL (id bigint(18) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL, PRIMARY KEY (id)) ENGINE = MERGE UNION=(COST00,COST01,COST02,COST03,COST04,COST05,COST06,COST07,COST08,COST09,COST10,COST11,COST12,COST13,COST14,COST15,COST16,COST17,COST18,COST19) INSERT_METHOD = LAST AUTO_INCREMENT=1;
Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist

当遇到上面错误时候,通过下面建议去排查
a:MERGE引擎仅适用于MYISAM表
b:union了不存在的表
c:MERGE的时候引用了不在同一个数据库中的表,并且该表没有指定数据库名字
d:各个表的结构(索引、引擎、列、字符集等)不完全一致
#通过查询主表进行全数据操作。

select * from COST_ALL;

方式二:业务代码逻辑处理如下

// service层中实现如下逻辑

public List<String> listCost() {
   
   List<String> listAll = new ArrayList<>();
   for (int i = 0; i < 20; i++) {
   
       List<String> subList = dao.listAll(String.valueOf(i));
       if (!CollectionUtils.isEmpty(subList)) {
   
           listAll.addAll(subList);
       }
   }
   return listAll;
}
//dao层中实现如下逻辑

List<String> listAll(@Param(value = "tableNum") String tableNum);
<!-- 如果业务中你使用mybatis,则在mapping.xml中添加下面代码 -->

<select id="listCost" resultType="java.lang.String" parameterType="java.lang.String">
   SELECT * FROM
   <include refid="table_name"></include>
</select>

<sql id="table_name">
   <choose>
   	<when test="tableNum!= null and tableNum=='0'.toString()">
   		COST00
   	</when>
   	<when test="tableNum!= null and tableNum=='1'.toString()">
   		COST01
   	</when>
   	<when test="tableNum!= null and tableNum=='2'.toString()">
   		COST02
   	</when>
   	<when test="tableNum!= null and tableNum=='3'.toString()">
   		COST03
   	</when>
   	<when test="tableNum!= null and tableNum=='4'.toString()">
   		COST04
   	</when>
   	<when test="tableNum!= null and tableNum=='5'.toString()">
   		COST05
   	</when>
   	<when test="tableNum!= null and tableNum=='6'.toString()">
   		COST06
   	</when>
   	<when test="tableNum!= null and tableNum=='7'.toString()">
   		COST07
   	</when<
  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值