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; ...@@ -11,6 +11,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import java.math.BigInteger;
import java.text.ParseException; import java.text.ParseException;
import java.util.Date; import java.util.Date;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
...@@ -25,7 +26,6 @@ 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>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> * <li>sequence: The next 13 bits, represents a sequence within the same second, max for 8192/s<br><br>
* <p> * <p>
* The {@link DefaultUidGenerator#parseUID(long)} is a tool method to parse the bits
* <p> * <p>
* <pre>{@code * <pre>{@code
* +------+----------------------+----------------+-----------+ * +------+----------------------+----------------+-----------+
...@@ -58,7 +58,7 @@ public class DefaultUidGenerator implements UidGenerator, InitializingBean { ...@@ -58,7 +58,7 @@ public class DefaultUidGenerator implements UidGenerator, InitializingBean {
protected int dataCenterIdBits; protected int dataCenterIdBits;
@Value("${uid.workerBits:13}") @Value("${uid.workerBits:13}")
protected int workerBits; protected int workerBits;
@Value("${uid.seqBits:23}") @Value("${uid.seqBits:13}")
protected int seqBits; protected int seqBits;
/** /**
...@@ -90,12 +90,13 @@ public class DefaultUidGenerator implements UidGenerator, InitializingBean { ...@@ -90,12 +90,13 @@ public class DefaultUidGenerator implements UidGenerator, InitializingBean {
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
// initialize bits allocator // initialize bits allocator
bitsAllocator = new BitsAllocator(timeBits, dataCenterIdBits, workerBits, seqBits); bitsAllocator = new BitsAllocator(timeBits, dataCenterIdBits, workerBits, seqBits);
workerIdAssigner = new DisposableWorkerIdAssigner();
// initialize worker id // initialize worker id
workerId = workerIdAssigner.assignWorkerId(dataCenterId, bitsAllocator); workerId = workerIdAssigner.assignWorkerId(dataCenterId, bitsAllocator);
Assert.isTrue(workerId < bitsAllocator.getMaxWorkerId(), "workerId is too big"); 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 bits dataCenterBits:{}, workerBits:{}, seqBits:{}", dataCenterIdBits, workerBits, seqBits);
LOGGER.info("Initialized nodes, workerId:{}, dataCenterId:{}", workerId, dataCenterId);
} }
@Override @Override
...@@ -110,28 +111,40 @@ public class DefaultUidGenerator implements UidGenerator, InitializingBean { ...@@ -110,28 +111,40 @@ public class DefaultUidGenerator implements UidGenerator, InitializingBean {
// TODO: 2018/3/5 反序列化 uid // TODO: 2018/3/5 反序列化 uid
@Override @Override
public String parseUID(long uid) { public String parseUID(String uidStr) {
int totalBits = Long.toBinaryString(uid).length(); BigInteger bigInteger = new BigInteger(uidStr);
long timestampBits = bitsAllocator.getTimestampBits();
int totalBits = bigInteger.bitLength();
long dataCenterIdBits = bitsAllocator.getDataCenterIdBits(); long dataCenterIdBits = bitsAllocator.getDataCenterIdBits();
long workerIdBits = bitsAllocator.getWorkerIdBits(); long workerIdBits = bitsAllocator.getWorkerIdBits();
long sequenceBits = bitsAllocator.getSequenceBits(); long sequenceBits = bitsAllocator.getSequenceBits();
if (totalBits < 64) { 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 private BigInteger getBigIntegerFromLength(long n) {
return String.format("{\"UID\":\"%d\",\"timestamp\":\"%s\",\"workerId\":\"%d\",\"sequence\":\"%d\"}", return BigInteger.valueOf(-1).shiftLeft((int) n).not();
uid, thatTimeStr, workerId, sequence);
} }
/** /**
...@@ -188,7 +201,6 @@ public class DefaultUidGenerator implements UidGenerator, InitializingBean { ...@@ -188,7 +201,6 @@ public class DefaultUidGenerator implements UidGenerator, InitializingBean {
return TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()); return TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis());
} }
public void setTimeBits(int timeBits) { public void setTimeBits(int timeBits) {
if (timeBits > 0) { if (timeBits > 0) {
this.timeBits = timeBits; this.timeBits = timeBits;
......
...@@ -22,6 +22,6 @@ public interface UidGenerator { ...@@ -22,6 +22,6 @@ public interface UidGenerator {
* @param uid * @param uid
* @return Parsed info * @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