Commit e745ae77 authored by zhiguo.liu's avatar zhiguo.liu

feat: 完善 parseUid 方法,支持解释 UID

parent 31cafb05
......@@ -11,6 +11,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.math.BigInteger;
import java.text.ParseException;
import java.util.Date;
import java.util.concurrent.TimeUnit;
......@@ -25,7 +26,6 @@ import java.util.concurrent.TimeUnit;
* <li>worker id: The next 22 bits, represents the worker's id which assigns based on database, max id is about 420W
* <li>sequence: The next 13 bits, represents a sequence within the same second, max for 8192/s<br><br>
* <p>
* The {@link DefaultUidGenerator#parseUID(long)} is a tool method to parse the bits
* <p>
* <pre>{@code
* +------+----------------------+----------------+-----------+
......@@ -58,7 +58,7 @@ public class DefaultUidGenerator implements UidGenerator, InitializingBean {
protected int dataCenterIdBits;
@Value("${uid.workerBits:13}")
protected int workerBits;
@Value("${uid.seqBits:23}")
@Value("${uid.seqBits:13}")
protected int seqBits;
/**
......@@ -90,12 +90,13 @@ public class DefaultUidGenerator implements UidGenerator, InitializingBean {
public void afterPropertiesSet() throws Exception {
// initialize bits allocator
bitsAllocator = new BitsAllocator(timeBits, dataCenterIdBits, workerBits, seqBits);
workerIdAssigner = new DisposableWorkerIdAssigner();
// initialize worker id
workerId = workerIdAssigner.assignWorkerId(dataCenterId, bitsAllocator);
Assert.isTrue(workerId < bitsAllocator.getMaxWorkerId(), "workerId is too big");
Assert.isTrue(workerId < bitsAllocator.getMaxDataCenterId(), "dataCenterId is too big");
Assert.isTrue(dataCenterId < bitsAllocator.getMaxDataCenterId(), "dataCenterId is too big");
LOGGER.info("Initialized bits dataCenterBits:{}, workerBits:{}, seqBits:{}", dataCenterIdBits, workerBits, seqBits);
LOGGER.info("Initialized nodes, workerId:{}, dataCenterId:{}", workerId, dataCenterId);
}
@Override
......@@ -110,28 +111,40 @@ public class DefaultUidGenerator implements UidGenerator, InitializingBean {
// TODO: 2018/3/5 反序列化 uid
@Override
public String parseUID(long uid) {
int totalBits = Long.toBinaryString(uid).length();
long timestampBits = bitsAllocator.getTimestampBits();
public String parseUID(String uidStr) {
BigInteger bigInteger = new BigInteger(uidStr);
int totalBits = bigInteger.bitLength();
long dataCenterIdBits = bitsAllocator.getDataCenterIdBits();
long workerIdBits = bitsAllocator.getWorkerIdBits();
long sequenceBits = bitsAllocator.getSequenceBits();
if (totalBits < 64) {
totalBits = 64;
long uid = bigInteger.longValue();
long sequence = (uid << (totalBits - sequenceBits)) >>> (totalBits - sequenceBits);
long workerId = (uid << (totalBits - workerIdBits - sequenceBits)) >>> (totalBits - workerIdBits);
long dataCenterId = (uid << (totalBits - dataCenterIdBits - workerIdBits - sequenceBits)) >>> (totalBits - dataCenterIdBits);
long deltaSeconds = uid >>> (dataCenterIdBits + workerIdBits + sequenceBits);
Date thatTime = new Date(TimeUnit.SECONDS.toMillis(epochSeconds + deltaSeconds));
String thatTimeStr = DateFormatUtils.format(thatTime, DATETIME_PATTERN);
return String.format("{\"UID\":\"%d\",\"timestamp\":\"%s\",\"dataCenterId\":\"%d\",\"workerId\":\"%d\",\"sequence\":\"%d\"}",
uid, thatTimeStr, dataCenterId, workerId, sequence);
} else {
BigInteger workerBig = getBigIntegerFromLength(workerIdBits).shiftLeft((int) sequenceBits).and(bigInteger);
System.out.println(workerBig);
long sequence = getBigIntegerFromLength(sequenceBits).and(bigInteger).longValue();
long workerId = getBigIntegerFromLength(workerIdBits).and(bigInteger.shiftRight((int)sequenceBits)).longValue();
long dataCenterId = getBigIntegerFromLength(dataCenterIdBits).and(bigInteger.shiftRight((int)sequenceBits+(int)workerIdBits)).longValue();
long deltaSeconds = bigInteger.shiftRight((int) dataCenterIdBits + (int) workerIdBits + (int) sequenceBits).longValue();
Date thatTime = new Date(TimeUnit.SECONDS.toMillis(epochSeconds + deltaSeconds));
String thatTimeStr = DateFormatUtils.format(thatTime, DATETIME_PATTERN);
return String.format("{\"UID\":\"%d\",\"timestamp\":\"%s\",\"dataCenterId\":\"%d\",\"workerId\":\"%d\",\"sequence\":\"%d\"}",
bigInteger, thatTimeStr, dataCenterId, workerId, sequence);
}
// parse UID
long sequence = (uid << (totalBits - sequenceBits)) >>> (totalBits - sequenceBits);
long workerId = (uid << (timestampBits + 1)) >>> (totalBits - workerIdBits);
long deltaSeconds = uid >>> (dataCenterIdBits + workerIdBits + sequenceBits);
Date thatTime = new Date(TimeUnit.SECONDS.toMillis(epochSeconds + deltaSeconds));
String thatTimeStr = DateFormatUtils.format(thatTime, DATETIME_PATTERN);
}
// format as string
return String.format("{\"UID\":\"%d\",\"timestamp\":\"%s\",\"workerId\":\"%d\",\"sequence\":\"%d\"}",
uid, thatTimeStr, workerId, sequence);
private BigInteger getBigIntegerFromLength(long n) {
return BigInteger.valueOf(-1).shiftLeft((int) n).not();
}
/**
......@@ -188,7 +201,6 @@ public class DefaultUidGenerator implements UidGenerator, InitializingBean {
return TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis());
}
public void setTimeBits(int timeBits) {
if (timeBits > 0) {
this.timeBits = timeBits;
......
......@@ -22,6 +22,6 @@ public interface UidGenerator {
* @param uid
* @return Parsed info
*/
String parseUID(long uid);
String parseUID(String uid);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment