Mycat 分片算法 AutoPartitionByLong

关于分片算法 AutoPartitionByLong,rule.xml 的配置为:

<function name="rang-long" class="io.mycat.route.function.AutoPartitionByLong">
    <property name="mapFile">autopartition-long.txt</property>
    <property name="defaultNode">2</property>
</function>

init的实现逻辑如下:

public void init() {
    BufferedReader in = null;
		try {
			// FileInputStream fin = new FileInputStream(new File(fileMapPath));
			InputStream fin = this.getClass().getClassLoader()
					.getResourceAsStream(mapFile);
			if (fin == null) {
				throw new RuntimeException("can't find class resource file "
						+ mapFile);
			}
			in = new BufferedReader(new InputStreamReader(fin));
			LinkedList<LongRange> longRangeList = new LinkedList<LongRange>();

			for (String line = null; (line = in.readLine()) != null;) {
				line = line.trim();
				if (line.startsWith("#") || line.startsWith("//")) {
					continue;
				}
				int ind = line.indexOf('=');
				if (ind < 0) {
					System.out.println(" warn: bad line int " + mapFile + " :" + line);
					continue;
				}
				String pairs[] = line.substring(0, ind).trim().split("-");
				long longStart = NumberParseUtil.parseLong(pairs[0].trim());
				long longEnd = NumberParseUtil.parseLong(pairs[1].trim());
				int nodeId = Integer.parseInt(line.substring(ind + 1)
						.trim());
				longRangeList.add(new LongRange(nodeId, longStart, longEnd));
			}
			longRongs = longRangeList.toArray(new LongRange[longRangeList
					.size()]);
		} catch (Exception e) {
			if (e instanceof RuntimeException) {
				throw (RuntimeException) e;
			} else {
				throw new RuntimeException(e);
			}

		} finally {
			try {
				in.close();
			} catch (Exception e2) {
			}
		}
}

可以看出,该段代码主要是完成 mapFile 配置文件的解析,读取节点索引与数值范围的映射关系,用于在 calculate 方法执行时计算dataNode节点。根据代码,可以看出该文件配置需要严格按照如下模板:

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

calculate方法实现为:

public Integer calculate(String columnValue)  {
    try {
        long value = Long.parseLong(columnValue);
        Integer rst = null;
        for (LongRange longRang : this.longRongs) {
            if (value <= longRang.valueEnd && value >= longRang.valueStart) {
                return longRang.nodeIndx;
            }
        }
        //数据超过范围,暂时使用配置的默认节点
        if (rst == null && defaultNode >= 0) {
            return defaultNode;
        }
        return rst;
    } catch (NumberFormatException e){
			throw new IllegalArgumentException(new                                        
               StringBuilder().append("columnValue:").append(columnValue).append(" 
           Please eliminate any quote and non number within it.").toString(),e);
    }
}

通过代码可以看出,计算节点根据autopartition-long.txt 的解析结果,遍历得出columnValue应该存储在哪个节点。如果遍历结束没有找到匹配的节点,即数据超过范围,此时将使用defaultNode存储,如果没有配置defaultNode,该值初始值为 -1 ,则会返回 rst,即返回null。那么根据会抛出异常信息“can't find any valid datanode”,如下:

Integer nodeIndex = algorithm.calculate(pair.colValue);
if(nodeIndex == null) {
    String msg = "can't find any valid datanode :" + tableConfig.getName() + " -> "         
                      + tableConfig.getPartitionColumn() + " -> " + pair.colValue;
    LOGGER.warn(msg);
    throw new SQLNonTransientException(msg);
}

总结:

1、如果数据在配置的范围内,存储在配置的节点中;
2、如果数据超出范围,且配置defaultNode,则存储在defaultNode中;
3、如果超出范围,且没有配置defaultNode,则抛出异常;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wyr2018

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值