-分表方案
-数据迁移
1.分表计算。
根据数据量现有量和递增量评估。表中字段不太多,字段长度适中的表,默认页大小为16kb情况下,数据量维持在2000万以下就可以(保持B+树的高度不超过3)。
比如:t_client_records 用户订单表,现有数据量为4000万,业务增速为20%,每年增长4000万*1.2,5年以后,总量为3个亿左右的数据。3亿/2000万,为15张表。按照2的 倍数来,就是16张表。
表名:t_client_course;
分表:t_client_course_0,t_client_course_1....t_client_course_15;
分表字段: client_id 客户号,算法: 1.计算公式: client_id&(16-1)。2.启用表对列: aliveList:{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}。
伪代码:
public int queryIdx(){
int len=16;
int idx=-1;
while(len>0){
int idxTemp = client_id & (len-1)
if( aliveList.contains(idxTemp) ){
idx = idxTemp;
break;
}
len = (len>>1);
}
if(idx<0){
throw new Exception("查找异常");
}
}
如果后期扩容:
将 t_client_course 扩容两张表:t_client_course_0 --->t_client_course_0 和t_client_course_16;
修改配置 -> aliveList:{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}。
原表t_client_course_0中的数据,一部分会迁移到 t_client_course_16中。
不停机迁移
1.设置系统级参数标量: is_in_migrate,是否在做数据迁移。
2.设置在对表t_client_course的写入操作,都需要对client_id 加分布式锁。
3.在迁移过程中,对客户ID 维度来迁移。
伪代码:
// 原来的对t_client_course表的写入操作,添加 client_id 维度的分布式锁。
lock = redisson.getLock(lockKeyPrefix + client_id);
lock.lock(timeout, TimeUnit.SECONDS);
// 是否迁移完成
boolean isSuccess = query();
if(isSuccess){
//写入分表中的数据
}else{
//写入原表逻辑
}
//分割线-------------------------------------------------------
// 数据迁移
lock = redisson.getLock(lockKeyPrefix + client_id);
lock.lock(timeout, TimeUnit.SECONDS);
list records = queryByClientId(client_id);
int idx = queryIdx(client_id);
// 写入分表 t_client_course_idx