mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
Snowflake增加方法:根据传入时间戳,计算ID起终点
This commit is contained in:
parent
fe37c1aa84
commit
bea36c2b5f
@ -9,6 +9,7 @@
|
|||||||
* 【core 】 新增ProxySocketFactory
|
* 【core 】 新增ProxySocketFactory
|
||||||
* 【http 】 UserAgent增加百度浏览器识别(issue#I847JY@Gitee)
|
* 【http 】 UserAgent增加百度浏览器识别(issue#I847JY@Gitee)
|
||||||
* 【core 】 ReflectUtil.getFieldsValue增加Filter重载(pr#1090@Gitee)
|
* 【core 】 ReflectUtil.getFieldsValue增加Filter重载(pr#1090@Gitee)
|
||||||
|
* 【core 】 Snowflake增加方法:根据传入时间戳,计算ID起终点(pr#1096@Gitee)
|
||||||
|
|
||||||
### 🐞Bug修复
|
### 🐞Bug修复
|
||||||
* 【cron 】 修复Cron表达式range解析错误问题(issue#I82CSH@Gitee)
|
* 【cron 】 修复Cron表达式range解析错误问题(issue#I82CSH@Gitee)
|
||||||
|
@ -204,7 +204,7 @@ public class Snowflake implements Serializable {
|
|||||||
* @param timestampStart 开始时间戳
|
* @param timestampStart 开始时间戳
|
||||||
* @param timestampEnd 结束时间戳
|
* @param timestampEnd 结束时间戳
|
||||||
* @return key-ID起点,Value-ID终点
|
* @return key-ID起点,Value-ID终点
|
||||||
* @since 5.8.24
|
* @since 5.8.23
|
||||||
*/
|
*/
|
||||||
public Pair<Long, Long> getIdScopeByTimestamp(long timestampStart, long timestampEnd) {
|
public Pair<Long, Long> getIdScopeByTimestamp(long timestampStart, long timestampEnd) {
|
||||||
return getIdScopeByTimestamp(timestampStart, timestampEnd, true);
|
return getIdScopeByTimestamp(timestampStart, timestampEnd, true);
|
||||||
@ -217,7 +217,7 @@ public class Snowflake implements Serializable {
|
|||||||
* @param timestampEnd 结束时间戳
|
* @param timestampEnd 结束时间戳
|
||||||
* @param ignoreCenterAndWorker 是否忽略数据中心和机器节点的占位,忽略后可获得分布式环境全局可信赖的起终点。
|
* @param ignoreCenterAndWorker 是否忽略数据中心和机器节点的占位,忽略后可获得分布式环境全局可信赖的起终点。
|
||||||
* @return key-ID起点,Value-ID终点
|
* @return key-ID起点,Value-ID终点
|
||||||
* @since 5.8.24
|
* @since 5.8.23
|
||||||
*/
|
*/
|
||||||
public Pair<Long, Long> getIdScopeByTimestamp(long timestampStart, long timestampEnd, boolean ignoreCenterAndWorker) {
|
public Pair<Long, Long> getIdScopeByTimestamp(long timestampStart, long timestampEnd, boolean ignoreCenterAndWorker) {
|
||||||
long startTimeMinId = (timestampStart - twepoch) << TIMESTAMP_LEFT_SHIFT;
|
long startTimeMinId = (timestampStart - twepoch) << TIMESTAMP_LEFT_SHIFT;
|
||||||
|
@ -25,65 +25,40 @@ public class SnowflakeTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void snowflakeTestGetIdScope() {
|
public void snowflakeTestGetIdScope() {
|
||||||
long workerId = RandomUtil.randomLong(31);
|
final long workerId = RandomUtil.randomLong(31);
|
||||||
long dataCenterId = RandomUtil.randomLong(31);
|
final long dataCenterId = RandomUtil.randomLong(31);
|
||||||
Snowflake idWorker = new Snowflake(workerId, dataCenterId);
|
final Snowflake idWorker = new Snowflake(workerId, dataCenterId);
|
||||||
long generatedId = idWorker.nextId();
|
final long generatedId = idWorker.nextId();
|
||||||
// 随机忽略数据中心和工作机器的占位
|
// 随机忽略数据中心和工作机器的占位
|
||||||
boolean ignore = RandomUtil.randomBoolean();
|
final boolean ignore = RandomUtil.randomBoolean();
|
||||||
long createTimestamp = idWorker.getGenerateDateTime(generatedId);
|
final long createTimestamp = idWorker.getGenerateDateTime(generatedId);
|
||||||
Pair<Long, Long> idScope = idWorker.getIdScopeByTimestamp(createTimestamp, createTimestamp, ignore);
|
final Pair<Long, Long> idScope = idWorker.getIdScopeByTimestamp(createTimestamp, createTimestamp, ignore);
|
||||||
long startId = idScope.getKey();
|
final long startId = idScope.getKey();
|
||||||
long endId = idScope.getValue();
|
final long endId = idScope.getValue();
|
||||||
|
|
||||||
System.out.println(longToBinaryReadable(generatedId) + " = generatedId longToBinaryReadable");
|
|
||||||
System.out.println(longToBinaryReadable(startId) + " = startId longToBinaryReadable");
|
|
||||||
System.out.println(longToBinaryReadable(endId) + " = endId longToBinaryReadable");
|
|
||||||
// 起点终点相差比较
|
// 起点终点相差比较
|
||||||
long trueOffSet = endId - startId;
|
final long trueOffSet = endId - startId;
|
||||||
// 忽略数据中心和工作机器时差值为22个1,否则为12个1
|
// 忽略数据中心和工作机器时差值为22个1,否则为12个1
|
||||||
long expectedOffSet = ignore ? ~(-1 << 22) : ~(-1 << 12);
|
final long expectedOffSet = ignore ? ~(-1 << 22) : ~(-1 << 12);
|
||||||
System.out.println("计算差值 = " + trueOffSet + ", 预期差值 = " + expectedOffSet);
|
|
||||||
Assert.assertEquals(trueOffSet, expectedOffSet);
|
Assert.assertEquals(trueOffSet, expectedOffSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* long转雪花格式的2进制字符串
|
|
||||||
*
|
|
||||||
* @param number long值
|
|
||||||
* @return 符号位(1bit)- 时间戳相对值(41bit)- 数据中心标志(5bit)- 机器标志(5bit)- 递增序号(12bit)
|
|
||||||
*/
|
|
||||||
private String longToBinaryReadable(long number) {
|
|
||||||
String binaryString = Long.toBinaryString(number);
|
|
||||||
StringBuilder sb = new StringBuilder(binaryString);
|
|
||||||
while (sb.length() < 64) {
|
|
||||||
sb.insert(0, '0'); // 在二进制字符串前面补零
|
|
||||||
}
|
|
||||||
sb
|
|
||||||
.insert(52, "-")
|
|
||||||
.insert(47, "-")
|
|
||||||
.insert(42, "-")
|
|
||||||
.insert(1, "-")
|
|
||||||
;
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void snowflakeTest1(){
|
public void snowflakeTest1(){
|
||||||
//构建Snowflake,提供终端ID和数据中心ID
|
//构建Snowflake,提供终端ID和数据中心ID
|
||||||
Snowflake idWorker = new Snowflake(0, 0);
|
final Snowflake idWorker = new Snowflake(0, 0);
|
||||||
long nextId = idWorker.nextId();
|
final long nextId = idWorker.nextId();
|
||||||
Assert.assertTrue(nextId > 0);
|
Assert.assertTrue(nextId > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void snowflakeTest(){
|
public void snowflakeTest(){
|
||||||
HashSet<Long> hashSet = new HashSet<>();
|
final HashSet<Long> hashSet = new HashSet<>();
|
||||||
|
|
||||||
//构建Snowflake,提供终端ID和数据中心ID
|
//构建Snowflake,提供终端ID和数据中心ID
|
||||||
Snowflake idWorker = new Snowflake(0, 0);
|
final Snowflake idWorker = new Snowflake(0, 0);
|
||||||
for (int i = 0; i < 1000; i++) {
|
for (int i = 0; i < 1000; i++) {
|
||||||
long id = idWorker.nextId();
|
final long id = idWorker.nextId();
|
||||||
hashSet.add(id);
|
hashSet.add(id);
|
||||||
}
|
}
|
||||||
Assert.assertEquals(1000L, hashSet.size());
|
Assert.assertEquals(1000L, hashSet.size());
|
||||||
@ -92,8 +67,8 @@ public class SnowflakeTest {
|
|||||||
@Test
|
@Test
|
||||||
public void snowflakeGetTest(){
|
public void snowflakeGetTest(){
|
||||||
//构建Snowflake,提供终端ID和数据中心ID
|
//构建Snowflake,提供终端ID和数据中心ID
|
||||||
Snowflake idWorker = new Snowflake(1, 2);
|
final Snowflake idWorker = new Snowflake(1, 2);
|
||||||
long nextId = idWorker.nextId();
|
final long nextId = idWorker.nextId();
|
||||||
|
|
||||||
Assert.assertEquals(1, idWorker.getWorkerId(nextId));
|
Assert.assertEquals(1, idWorker.getWorkerId(nextId));
|
||||||
Assert.assertEquals(2, idWorker.getDataCenterId(nextId));
|
Assert.assertEquals(2, idWorker.getDataCenterId(nextId));
|
||||||
@ -104,9 +79,9 @@ public class SnowflakeTest {
|
|||||||
@Ignore
|
@Ignore
|
||||||
public void uniqueTest(){
|
public void uniqueTest(){
|
||||||
// 测试并发环境下生成ID是否重复
|
// 测试并发环境下生成ID是否重复
|
||||||
Snowflake snowflake = IdUtil.getSnowflake(0, 0);
|
final Snowflake snowflake = IdUtil.getSnowflake(0, 0);
|
||||||
|
|
||||||
Set<Long> ids = new ConcurrentHashSet<>();
|
final Set<Long> ids = new ConcurrentHashSet<>();
|
||||||
ThreadUtil.concurrencyTest(100, () -> {
|
ThreadUtil.concurrencyTest(100, () -> {
|
||||||
for (int i = 0; i < 50000; i++) {
|
for (int i = 0; i < 50000; i++) {
|
||||||
if(false == ids.add(snowflake.nextId())){
|
if(false == ids.add(snowflake.nextId())){
|
||||||
@ -143,7 +118,7 @@ public class SnowflakeTest {
|
|||||||
final Snowflake snowflake = new Snowflake(null, 0, 0,
|
final Snowflake snowflake = new Snowflake(null, 0, 0,
|
||||||
false, Snowflake.DEFAULT_TIME_OFFSET, 100);
|
false, Snowflake.DEFAULT_TIME_OFFSET, 100);
|
||||||
|
|
||||||
Set<Long> ids = new ConcurrentHashSet<>();
|
final Set<Long> ids = new ConcurrentHashSet<>();
|
||||||
ThreadUtil.concurrencyTest(100, () -> {
|
ThreadUtil.concurrencyTest(100, () -> {
|
||||||
for (int i = 0; i < 50000; i++) {
|
for (int i = 0; i < 50000; i++) {
|
||||||
if(false == ids.add(snowflake.nextId())){
|
if(false == ids.add(snowflake.nextId())){
|
||||||
|
Loading…
x
Reference in New Issue
Block a user