一、Mycat常用分片规则
1. 时间类:按天分片、自然月分片、单月小时分片
2. 哈希类:Hash固定分片、日期范围Hash分片、截取数字Hash求模范围分片、截取数字Hash分片、一致性Hash分片
3. 取模类:取模分片、取模范围分片、范围求模分片
4. 其他类:枚举分片、范围约定分片、应用指定分片、冷热数据分片
下面基于源码来介绍Mycat的常用分片规则, 源码地址
二、Mycat常用分片规则介绍
说明: 分片规则都定义在rule.xml文件里面
id
func1
1,1,2,3,1
128,128,128,128,128
1. 自动范围分片
在rule.xml里面的配置:
id
rang-long
autopartition-long.txt
说明:
有3个分片,第1个分片存储的是1-500000的数据,第2个分片存储的是500001-1000000的数据,第3个分片存储的是1000001-1500000的数据
insert into employee(id, name) value(1,Tom);在第1个分片
insert into employee(id, name) value(500002,Jack);在第2个分片
insert into employee(id, name) value(1000002,Lucy);在第3个分片
对应代码:
package io.mycat.route.function;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import io.mycat.config.model.rule.RuleAlgorithm;
/**
* auto partition by Long ,can be used in auto increment primary key partition
*
* @author wuzhi
*/
public class AutoPartitionByLong extends AbstractPartitionAlgorithm implements RuleAlgorithm{
private String mapFile;
private LongRange[] longRongs;
private int defaultNode = -1;
@Override
public void init() {
initialize();
}
public void setMapFile(String mapFile) {
this.mapFile = mapFile;
}
@Override
public Integer calculate(String columnValue) {
// columnValue = NumberParseUtil.eliminateQoute(columnValue);
try {
long value = Long.parseLong(columnValue);
Integer rst = null;
for (LongRange longRang : this.longRongs) {
if (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);
}
}
@Override
public Integer[] calculateRange(String beginValue, String endValue) {
return AbstractPartitionAlgorithm.calculateSequenceRange(this, beginValue, endValue);
}
@Override
public int getPartitionNum() {
// int nPartition = longRongs.length;
/*
* fix #1284 这里的统计应该统计Range的nodeIndex的distinct总数
*/
Set distNodeIdxSet = new HashSet();
for(LongRange range : longRongs) {
distNodeIdxSet.add(range.nodeIndx);
}
int nPartition = distNodeIdxSet.size();
return nPartition;
}
private void initialize() {
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 longRangeList = new LinkedList();
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) {
}
}
}
public int getDefaultNode() {
return defaultNode;
}
public void setDefaultNode(int defaultNode) {
this.defaultNode = defaultNode;
}
static class LongRange {
public final int nodeIndx;
public final long valueStart;
public final long valueEnd;
public LongRange(int nodeIndx, long valueStart, long valueEnd) {
super();
this.nodeIndx = nodeIndx;
this.valueStart = valueStart;
this.valueEnd = valueEnd;
}
}
}
View Code
2. 枚举分片
把数据分类存储
在rule.xml里面的配置:
sharding_id
hash-int
partition-hash-int.txt
0
说明: 找不到分片时设置容错规则,把数据插入到默认分片 0 里面
对应代码:
package io.mycat.route.function;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import io.mycat.config.model.rule.RuleAlgorithm;
/**
*
* @author mycat
*/
public class PartitionByFileMap extends AbstractPartitionAlgorithm implements RuleAlgorithm {
private String mapFile;
private Map app2Partition;
/**
* Map app2Partition中key值的类型:默认值为0,0表示Integer,非零表示String
*/
private int type;
/**
* 默认节点在map中的key
*/
private static final String DEFAULT_NODE = "DEFAULT_NODE";
/**
* 默认节点:小于0表示不设置默认节点,大于等于0表示设置默认节点
*
* 默认节点的作用:枚举分片时,如果碰到不识别的枚举值,就让它路由到默认节点
* 如果不配置默认节点(defaultNode值小于0表示不配置默认节点),碰到
* 不识别的枚举值就会报错,
* like this:can't find datanode for sharding column:column_name val:ffffffff
*/
private int defaultNode = -1;
@Override
public void init() {
initialize();
}
public void setMapFile(String mapFile) {
this.mapFile = mapFile;
}
public void setType(int type) {
this.type = type;
}
public void setDefaultNode(int defaultNode) {
this.defaultNode = defaultNode;
}
@Override
public Integer calculate(String columnValue) {
try {
Object value = columnValue;
if (type == 0) {
value = Integer.valueOf(columnValue);
}
Integer rst = null;
Integer pid = app2Partition.get(value);
if (pid != null) {
rst = pid;
} else {
rst = app2Partition.get(DEFAULT_NODE);
}