Mycat——项目中整合Mycat遇到的问题总结

1、开发中遇到的问题

历史数据表随着业务的增长已经有4-5个亿的数据,之前是按照定时任务每月创建一个表,插入的时候根据当前的时间来将数据插入到当前表,联查的时候跨月查是个问题,刚好有个新项目尝试使用了Mycat来解决该问题,采用两个库对历史表进行分片。

2、Mycat整合步骤

2.1在两台服务器上安装Mysql(这里用mysql-5.7.26)(https://note.youdao.com/s/KlTcX694

2.2安装Mycat(这里使用1.6版本)

        解压之后进入Mycat的conf目录进行配置:

2.2.1 schema.xml 

<schema name="xinchai" checkSQLschema="false" sqlMaxLimit="100">
		<!-- auto sharding by id (long) -->
		<!-- <table name="user_profile" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" /> -->

		<!-- global table is auto cloned to all defined data nodes ,so can join 
			with any table whose sharding node is in the same data node -->
		
		<table name="history" primaryKey="id"  autoIncrement="true" dataNode="distribute(dn1$0-6,dn2$0-6)" rule="sharding-by-date-customer" />
		<table name="mycat_sequence" dataNode="dn10" autoIncrement="true" primaryKey="id"></table>
		
	</schema>

注意: 

1、关键的有两个表,一个是业务表history和序列表mycat_sequence

 2、dataNode为数据节点,在<dataNode />中配置,我用了两个服务器,配置了14个分片节点,如下:

    <dataNode name="dn10" dataHost="datahost1" database="test" />
	<dataNode name="dn11" dataHost="datahost1" database="test-db1" />
	<dataNode name="dn12" dataHost="datahost1" database="test-db2" />
	<dataNode name="dn13" dataHost="datahost1" database="test-db3" />
	<dataNode name="dn14" dataHost="datahost1" database="test-db4" />
	<dataNode name="dn15" dataHost="datahost1" database="test-db5" />
	<dataNode name="dn16" dataHost="datahost1" database="test-db6" />
	<dataNode name="dn20" dataHost="datahost2" database="test" />
	<dataNode name="dn21" dataHost="datahost2" database="test-db1" />
	<dataNode name="dn22" dataHost="datahost2" database="test-db2" />
	<dataNode name="dn23" dataHost="datahost2" database="test-db3" />
	<dataNode name="dn24" dataHost="datahost2" database="test-db4" />
	<dataNode name="dn25" dataHost="datahost2" database="test-db5" />
	<dataNode name="dn26" dataHost="datahost2" database="test-db6" />

3、如果使用全局自增Id并且在insert添加时不用写id需要进行以下配置(采用数据库序列方式而非本地文件形式)

(1)需要配置表属性autoIncrement="true",

(2)在序列中表中添加供history表使用的序列(序列表及执行添加语句需要在该节点库中执行而非mycat

INSERT INTO MYCAT_SEQUENCE(name,current_value,increment,remark) VALUES ('HISTORY', 1, 100,'历史数据使用');

(3)在sequence_db_conf.properties中添加序列存储节点

#sequence stored in datanode
GLOBAL=dn10
COMPANY=dn10
CUSTOMER=dn10
ORDERS=dn10
HISTORY=dn10

(4)在server.xml中配置:

<property name="sequnceHandlerType">1</property>

踩坑一: 在使用本地文件方式使用ID自增时,批量插入数据经常会出现异常,而且不容易维护。所以推荐使用数据库形式配置全局自增序列:

fetch Param Values error.

注:配置自增序列语句:

-- 1、在第一个数据库节点上创建 MYCAT_SEQUENCE 表

DROP TABLE IF EXISTS MYCAT_SEQUENCE;
CREATE TABLE MYCAT_SEQUENCE (
name VARCHAR(50) NOT NULL,
current_value INT NOT NULL,
increment INT NOT NULL DEFAULT 1,
remark varchar(100),
PRIMARY KEY(name)) ENGINE=InnoDB;

-- 2、创建存储过程——获取当前 sequence 的值
DROP FUNCTION IF EXISTS `mycat_seq_currval`;
DELIMITER ;;
CREATE DEFINER=`root`@`%` FUNCTION `mycat_seq_currval`(seq_name VARCHAR(50)) RETURNS varchar(64)
CHARSET latin1
DETERMINISTIC
BEGIN
DECLARE retval VARCHAR(64);
SET retval="-999999999,null";
SELECT concat(CAST(current_value AS CHAR),",",CAST(increment AS CHAR) ) INTO retval FROM
MYCAT_SEQUENCE WHERE name = seq_name;
RETURN retval ;
END
;;
DELIMITER ;

-- 3、创建存储过程,获取下一个 sequence

DROP FUNCTION IF EXISTS `mycat_seq_nextval`;
DELIMITER ;;
CREATE DEFINER=`root`@`%` FUNCTION `mycat_seq_nextval`(seq_name VARCHAR(50)) RETURNS varchar(64)
CHARSET latin1
DETERMINISTIC
BEGIN
UPDATE MYCAT_SEQUENCE
SET current_value = current_value + increment WHERE name = seq_name;
RETURN mycat_seq_currval(seq_name);
END
;;
DELIMITER ;

-- 4、创建存储过程,设置 sequence

DROP FUNCTION IF EXISTS `mycat_seq_setval`;
DELIMITER ;;
CREATE DEFINER=`root`@`%` FUNCTION `mycat_seq_setval`(seq_name VARCHAR(50), value INTEGER)
RETURNS varchar(64) CHARSET latin1
DETERMINISTIC
BEGIN
UPDATE MYCAT_SEQUENCE
SET current_value = value
WHERE name = seq_name;
RETURN mycat_seq_currval(seq_name);
END
;;
DELIMITER ;

-- 5、插入记录
INSERT INTO MYCAT_SEQUENCE(name,current_value,increment,remark) VALUES ('HISTORY', 1, 100,'历史数据使用');

2.2.2 server.xml

<mycat:server xmlns:mycat="http://org.opencloudb/">
	<system>
	<property name="defaultSqlParser">druidparser</property>
	<property name="sequnceHandlerType">1</property>
      <!--  <property name="useCompression">1</property>--> <!--1为开启mysql压缩协议-->
	<!-- <property name="processorBufferChunk">40960</property> -->
	<!-- 
	<property name="processors">1</property> 
	<property name="processorExecutor">32</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="mutiNodeLimitType">1</property> 0:开启小数量级(默认) ;1:开启亿级数据排序
	    	<property name="mutiNodePatchSize">100</property> 亿级数量排序批量
			<property name="processors">32</property> <property name="processorExecutor">32</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> -->
	</system>
	<user name="root">
		<property name="password">test123</property>
		<property name="schemas">test</property>
	</user>

	<!-- <cluster> <node name="cobar1"> <property name="host">127.0.0.1</property> 
		<property name="weight">1</property> </node> </cluster> -->
	<!-- <quarantine> <host name="1.2.3.4"> <property name="user">test</property> 
		</host> </quarantine> -->

</mycat:server>

     配置逻辑库账号及密码

2.2.3在rule.xml中配置分片规则(本次采用按月分片)

<mycat:rule xmlns:mycat="http://org.opencloudb/">
	<tableRule name="sharding-by-date-customer">
		<rule>
			<columns>created_time</columns>
			<algorithm>sharding-by-date</algorithm>
		</rule>
	</tableRule>

	
	<function name="sharding-by-date"
		class="org.opencloudb.route.function.PartitionByMonth">
		<property name="dateFormat">yyyy-MM-dd HH:mm:ss</property> <!--日期格式-->
		<property name="sBeginDate">2021-01-01 00:00:00</property> <!--开始日期-->
		<!-- <property name="sPartionDay">30</property>  -->
		<property name="sEndDate">2021-12-31 23:59:59</property>
		
	</function>
</mycat:rule>

 通过查看mycat源码可以看到其按照月份分片的规则:分片数=相差的年份*12 + (相差的月份+1)

比如我设置的为sBeginDate:2021-01-01 ,sEndDate:2021-12-31 则分片数为:0*12 + (12 - 1 + 1) = 12个分片。

并且注意实际数据库分片数不能小于计算出来的分片数

@Override
    public void init() {
        try {
            if (StringUtil.isEmpty(sBeginDate) && StringUtil.isEmpty(sEndDate)) {
                nPartition = 12;
                scene = 1;
                initFormatter();
                beginDate = Calendar.getInstance();
                beginDate.set(Calendar.MONTH, 0);
                endDate = Calendar.getInstance();
                endDate.set(Calendar.MONTH, 11);
                return;
            }
            beginDate = Calendar.getInstance();
            beginDate.setTime(new SimpleDateFormat(dateFormat)
                .parse(sBeginDate));
            initFormatter();
            // 如果在rule.xml中配置了,按照以下方式进行
            if (sEndDate != null && !sEndDate.equals("")) {
                endDate = Calendar.getInstance();
                endDate.setTime(new SimpleDateFormat(dateFormat).parse(sEndDate));
                nPartition = ((endDate.get(Calendar.YEAR) - beginDate.get(Calendar.YEAR)) * 12
                    + endDate.get(Calendar.MONTH) - beginDate.get(Calendar.MONTH)) + 1;

                if (nPartition <= 0) {
                    throw new java.lang.IllegalArgumentException("Incorrect time range for month partitioning!");
                }
            } else {
                nPartition = -1;
            }
        } catch (ParseException e) {
            throw new java.lang.IllegalArgumentException(e);
        }
    }

3、关于Springboot项目连接Mycat

3.1在yml中添加使用jdbc连接:

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: xinchai123
    url: jdbc:mysql://192.168.3.221:8066/test?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull
    druid:
      initial-size: 5
      min-idle: 5
      max-active: 5
      max-wait: 5000
      time-between-eviction-runs-millis: 6000
      min-evictable-idle-time-millis: 30000
      web-stat-filter:
        enabled: true
        url-pattern: /*
        exclusions: '*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*'
      stat-view-servlet:
        enabled: true
        url-pattern: /druid/*
        login-username: root
        login-password: root
        reset-enable: false

 3.2添加mysql连接jar包

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.30</version>
        </dependency>

踩坑二:建议使用5.1.30的包,之前使用5.1.38的包会出现异常:

com.mysql.jdbc.PacketTooBigException: Packet for query is too large (4 > -1). You can change this value on the server by setting the max_allowed_packet' variable

 另外如果插入数据时出现:Mycat 的分片数据插入报异常 IndexOutofBoundException,应该是分片规则配置不正确所致。

4、关于Mycat提供的测试工具 testtool.tar(自行下载)

对于官方给出的文档真的需要改进的地方很多,给出的例子应该再规范点,虽然是开源的软件,造福大家,但是希望也让开发人员少走弯路。

官方给出的插入测试语句不能用,测试了良久才解决:

4.1在解压的bin目录下创建mydate-create.sql模板文件:

total=10

sql=INSERT INTO `history` (`timepoint`, `state`, `code`, `serial_number`, `location_state`, `lat`, `lng`, `speed`, `pressure_value`, `engine_torque`, `engine_speed`, `friction_torque`, `engine_fuel_flow`, `scr_up_nox`, `scr_down_nox`, `residual_reactant`, `intake_value`, `scr_in_temperature`, `scr_export_temperature`, `dpf_differential_pressure`, `engine_coolant_temperature`, `power`, `actual_egr`, `setting_egr`, `created_time`, `idt_version`, `fault_status`) VALUES ('2021-07-25 23:59:59', '0', '${char([a-f,0-9]8:10)}', '34', 0, '41.88891', '123.5265', '0.0', '0.0', '0', '0', '0', '0.00', '0.00', '0.00', '0', '0.00', '0.0', '0.0', '0.0', '0', '0', '0', '0', '${date(yyyyMMdd-[2021-2021]y)}', 1, '0');

4.2执行语句:

test_stand_insert_perf.bat jdbc:mysql://192.168.3.221:8066/xinchai root xinchai123 10 "file=mydata-create.sql"

踩坑三:sql模板文件中的sql=xxx一句不能换行

踩坑四:执行语句test_stand_insert_perf.bat时最后的file=mydata-create.sql需要加引号(官方文档是没有加的...)

启动 ./mycat start
停止 ./mycat stop
重启 ./mycat restart
查看状态 ./mycat status
前台运行 ./mycat console

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值