package com.bj58.opt.cpt.dbo.mdt;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class MDTIDHelper {
private static int upper = 9;
private static int lower = 5;
private static int count = (int) (Math.random()*(upper-lower+1)+lower); // 下限
private static final long idFlag = 1397059200000L; // DateHelper.strToDate("2014-04-10").getTime()
private static long oldID = 9999999999999999l;
private static long oldID_1 = 54500000000000000L;
private static long lastTimestamp = -1L;
private static long sequence = 0L;
public static void main(String[] args) throws Exception {
long gbid = getMDTUniqueID();
System.out.println(gbid);
System.out.println(getMDTUniqueID(gbid));
System.out.println(getMDTUniqueID(gbid));
gbid = System.currentTimeMillis();
System.out.println(gbid);
gbid = gbid - MDTConstantHelper.ID_FLAG;
System.out.println(gbid);
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Calendar c = Calendar.getInstance();
c.setTime(df.parse("2014-04-10"));
System.out.println(c.getTimeInMillis());
gbid = (gbid<<1)|1;
System.out.println(gbid);
gbid = 1 ;
gbid = (gbid<<5);
System.out.println(gbid);
System.out.println(getShortUniqueID());
System.out.println(getShortUniqueID(99));
}
/**
* 返回0-999自增数
* @return
* @throws InterruptedException
*/
private static int getRandom() throws InterruptedException{
// return new Random().nextInt(999);
// return (int) (Math.round(Math.random() * 1000) );
if(count==upper)// 上限
count = lower - 1;// 下限
return ++count;
}
private static long getMDTBaseID() throws Exception {
if(MDTConstantHelper.SERVER_ID <= 0) {
throw new Exception("server id is error,please check config file!");
}
long destID = System.currentTimeMillis() - MDTConstantHelper.ID_FLAG;
// long destID = DateHelper.strToDate("2581-08-16").getTime() - MDTConstantHelper.ID_FLAG;
destID = (destID<<9) | MDTConstantHelper.SERVER_ID;
Thread.sleep(1);
return destID;
}
/**
* 垂直分表源id生成
* 最大支持到2581-08-16
* @return
* @throws Exception
*/
public static synchronized long getMDTUniqueID() throws Exception {
return getMDTBaseID()*1000+getRandom();
}
/**
* 垂直分表目标id生成
* 最大支持到2581-08-16
* @param sourceId
* @return
* @throws Exception
*/
public static synchronized long getMDTUniqueID(long sourceId) throws Exception {
return getMDTBaseID()*1000+sourceId%1000;
}
/**
* 获取主键ID
* @return
* @throws Exception
*/
public static synchronized long getShortUniqueID() throws Exception {
if(MDTConstantHelper.SERVER_ID <= 0) {
throw new Exception("server id is error,please check config file!");
}
long timestamp = timeGen();
if (timestamp < lastTimestamp) {
try {
throw new Exception("Clock moved backwards. Refusing to generate id for "+ (lastTimestamp - timestamp) + " milliseconds");
} catch (Exception e) {
e.printStackTrace();
}
}
if (lastTimestamp == timestamp) {
// 当前毫秒内,则+1
sequence = (sequence + 1) & 7;//0111
if (sequence == 0) {
// 当前毫秒内计数满了,则等待下一秒
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0;
}
lastTimestamp = timestamp;
long destID = timestamp - MDTConstantHelper.ID_FLAG;
destID = (destID<<10) | (MDTConstantHelper.SERVER_ID<<3)|sequence;
return destID;
}
/**
* 获取主键ID
* @return
* @throws Exception
*/
public static synchronized long getShortUniqueID(long sourceID) throws Exception {
if(MDTConstantHelper.SERVER_ID <= 0) {
throw new Exception("server id is error,please check config file!");
}
sourceID = getShortDBIndex(sourceID);
long destID = System.currentTimeMillis() - MDTConstantHelper.ID_FLAG;
destID = (destID << 10) | sourceID;
destID = (destID<<7) | MDTConstantHelper.SERVER_ID;
Thread.sleep(1);
return destID;
}
/**
* 不分库,不分表
* 获取主键ID
* @return
* @throws Exception
*/
public static synchronized long getUniqueID() throws Exception {
long sourceID = 0;
return getUniqueID(sourceID);
}
/**
* 不分库,分表
* @param tableID
* @return
* @throws Exception
*/
public static synchronized long getUniqueID(int tableID) throws Exception {
int sourceID = 0;
return getUniqueID(sourceID, tableID);
}
/**
* 分库,不分表
* 生成唯一ID,该ID的dbIndex与sourceID一至
* 注:最大支持库 :1024个
* 最大支持时间:4240-01-01
* @param sourceID
* @return
* @throws Exception
*/
public static synchronized long getUniqueID(long sourceID) throws Exception {
int tableID = 0;
return getUniqueID(sourceID, tableID);
}
/**
* 分库,分表
* 生成唯一ID,该ID的表编号与tableID一致
* 注:分库同时分表ID生成
* @param tableID
* @return
* @throws Exception
*/
public static synchronized long getUniqueID(long sourceID, int tableID) throws Exception {
if(MDTConstantHelper.SERVER_ID <= 0) {
throw new Exception("server id is error,please check config file!");
}
int sourceIndex = getDBIndex(sourceID);
long destID = System.currentTimeMillis() - MDTConstantHelper.ID_FLAG;
destID = (destID << 10) | tableID;//分表
destID = (destID << 5) | sourceIndex;//分库
destID = (destID << 4) | MDTConstantHelper.SERVER_ID;
Thread.sleep(1);
return destID;
}
/**
* 获得表索引号
* @param id
* @param tableCount 分表总数
* @return
*/
public static int getTableIndex(long id, int tableCount){
if(id<9999999999999999L){
return 0;
}
return (int)((id >> 9 ) & (tableCount - 1));
}
/**
* 获得表索引号
* @param id
* @param clazz 实体
* @return
*/
public static int getTableIndex(long id, Class<?> clazz){
// if(Order.class.getName().equals(clazz.getName()) || Ticket.class.getName().equals(clazz.getName())){
// if(id<9999999999999999l){
// return 0;
// }
// if(id<54500000000000000L){
// return 1;
// }
// }
//取模定位表
return MDTTableHelper.getTableIndex(clazz, id);
}
/**
* 获取ID所对应该的数据库编号
* @param ID
* @return 数据库
*/
public static int getDBIndex(long id) {
return (int)((id>>4) & (MDTConstantHelper.DB_COUNT - 1));
}
/**
* 获取ID所对应该的数据库编号
* @param ID
* @return 数据库
*/
public static int getDBIndex(long id, Class<?> clazz) {
// if(Order.class.getName().equals(clazz.getName()) || Ticket.class.getName().equals(clazz.getName())){
// int dbIndex = 0;
// List<Node> nodes = MDTTableHelper.getNodes(clazz);
// if (null != nodes && nodes.size() > 0) {
// dbIndex = nodes.get(0).getDbIndex();
// }
//
// if(id<9999999999999999l){
// return dbIndex;
// }
// if(id<54500000000000000L){
// return dbIndex;
// }
// }
//取模定位库
return MDTTableHelper.getDBIndex(clazz, id);
}
/**
* 获取ID所对应该的数据库编号
* @param ID
* @return 数据库
*/
public static int getShortDBIndex(long id) {
return (int)((id>>7) & (MDTConstantHelper.DB_COUNT - 1));
}
private static long tilNextMillis(final long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
private static long timeGen() {
return System.currentTimeMillis();
}
}