分布式数据库中间件Mycat分片规则

概念

数据切分,一个大表被分成若干个分片表,就需要一定的规则,这样按照某种业务规则把数据分到某个分片的规则就是分片规则,数据切分选择合适的分片规则非常重要,将极大的避免后续数据处理的难度。

分片规则是最终解析 sql 到那个分片执行的规则,Mycat 分片的确定是根据分片字段来确定数据的分布,即根据预先配置好的分片字段(只有一个)到分片规则中解析该字段对应的值应该路由到哪个分片,然后确认 sql 到哪个分片执行

 

规则

Mycat提供的分片规则

分片枚举  (自定义一个字段,根据这个字段的值来决定数据插入到哪个分片)
固定分片 hash 算法  (分片字段二进制后十位,&11111111,与运算。0-1023结果。根据partitionLength设置区间放到不同分片
范围约定  (分片字段某个范围属于哪个分片)
取模  (对分片字段求摸运算)
按日期(天)分片 
取模范围约束  (取模运算与范围约束的结合,主要为了后续数据迁移做准备,即可以自主决定取模后数据的节点分布)
截取数字做 hash 求模范围约束  (类似于取模范围约束,此规则支持数据符号字母取模)
应用指定  (是在运行阶段有应用自主决定路由到那个分片)
截取数字 hash 解析 (是截取字符串中的 int 数值 hash 分片)
一致性 hash (一致性 hash 预算有效解决了分布式数据的扩容问题
按单月小时拆分  (此规则是单月内按照小时拆分,最小粒度是小时,可以一天最多 24 个分片,每个月月尾,需要手工清理数据
范围求模分片  (先进行范围分片计算出分片组,组内再求模,优点可以避免扩容时的数据迁移,又可以一定程度上避免范围分片的热点问题)
日期范围 hash 分片  (先根据日期分组,再根据时间 hash 使得短期内数据分布的更均匀)
冷热数据分片  (日期查询日志数据 冷热数据分布 ,最近 n 个月的到实时交易库查询,超过 n 个月的按照 m 天分片)
自然月分片  (按月份列分区 ,每个自然月一个分片)
有状态分片算法,支持的分片策略  (crc32slot 分片)

 

那几个常用的测试

 

分片枚举

首先改schema.xml

<table name="travelrecord" dataNode="dn1,dn2,dn3" rule="sharding-by-intfile" />

第二在rule.xml中查看规则相关默认配置

algorithm 对应算法名称,也在rule.xml中。

很明显,根据这个配置文件来,在conf目录下

vi修改文件

10000=0
10010=1
10020=2

第三建表

create table travelrecord (id integer primary key,record varchar(255),sharding_id integer);

mycat中执行插入语句
//...
INSERT into travelrecord(id,record,sharding_id) VALUES(3,'深圳',10020)

结果

备注

可设置默认节点,也可以设置sharding_id类型为String

 

 

范围约定

 

<table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />

 

 

取模 

 

<table name="travelrecord" dataNode="dn1,dn2,dn3" rule="mod-long" />

 

按日期(天)分片

<table name="travelrecord" dataNode="dn1,dn2,dn3" rule="sharding-by-day" />

只有3个DN,从1-31号开始的话,需要配置4个DN,否则报错

 

当插入时间不在区间范围内,超出后还是10一区间分配

 

 

新属性看源码,sNaturalDay改为1

//自然日差额最少是28天
	//自然日差额最少
	private static final int naturalLimitDay =28;
	//开启自然日模式
	private static final String  naturalDayOpen ="1";
	private String oldsPartionDay;
	@Override
	public void init() {
		try {
			//Support  Natural Day
			if(naturalDayOpen.equals(sNaturalDay)){
				bNaturalDay =true;
				oldsPartionDay=sPartionDay;
				sPartionDay="1";
			}
			if(sBeginDate!=null&&!sBeginDate.equals("")) {
				partionTime = Integer.parseInt(sPartionDay) * oneDay;
				beginDate = new SimpleDateFormat(dateFormat).parse(sBeginDate).getTime();
			}
			if(sEndDate!=null&&!sEndDate.equals("")&&beginDate>0){
			    endDate = new SimpleDateFormat(dateFormat).parse(sEndDate).getTime();
				nCount = (int) ((endDate - beginDate) / partionTime) + 1;
				if(bNaturalDay&&nCount<naturalLimitDay){
					bNaturalDay =false;
					partionTime = Integer.parseInt(oldsPartionDay) * oneDay;
					nCount = (int) ((endDate - beginDate) / partionTime) + 1;
				}
			}
			formatter = new ThreadLocal<SimpleDateFormat>() {
				@Override
				protected SimpleDateFormat initialValue() {
					return new SimpleDateFormat(dateFormat);
				}
			};
		} catch (ParseException e) {
			throw new java.lang.IllegalArgumentException(e);
		}
	}
    @Override
	public Integer calculate(String columnValue)  {
		try {
			int targetPartition ;
			if(bNaturalDay){
				Calendar curTime = Calendar.getInstance();
				curTime.setTime(formatter.get().parse(columnValue));
				targetPartition = curTime.get(Calendar.DAY_OF_MONTH);
				return  targetPartition-1;
			}
			long targetTime = formatter.get().parse(columnValue).getTime();
			targetPartition = (int) ((targetTime - beginDate) / partionTime);
			if(targetTime>endDate && nCount!=0) {
				targetPartition = targetPartition % nCount;
			}
			return targetPartition;
		} catch (ParseException e) {
			throw new IllegalArgumentException(new StringBuilder().append("columnValue:").append(columnValue).append(" Please check if the format satisfied.").toString(),e);
		}
	}

当开始和结束时间间隔超过28天,可直接返回当前是第几天,不用除,取余预算了。

 

一致性 hash

如果数据库要扩容,如果采用前面几种分片规则,之前配置会失效,可能会出现数据库查询紊乱。

一致性 hash 预算有效解决了分布式数据的扩容问题。

重要,单独开一章

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值