Commit 61f477b7 authored by liuxingyu's avatar liuxingyu

雪花算法修改

parent 6ed9535a
...@@ -69,6 +69,12 @@ ...@@ -69,6 +69,12 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId> <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
</dependencies> </dependencies>
......
...@@ -43,7 +43,7 @@ public class TestController { ...@@ -43,7 +43,7 @@ public class TestController {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String threadId = Thread.currentThread().getName() + Thread.currentThread().getId(); String threadId = Thread.currentThread().getName() + Thread.currentThread().getId();
log.info("enter"+threadId+dateFormat.format(new Date())); log.info("enter"+threadId+dateFormat.format(new Date()));
System.out.println(threadId+dateFormat.format(new Date())); //redissonLockUtil.getLockByKey("265213225444411", LockType.FAIR_LOCK.value());
Tuple2<RLock, Boolean> rlocks = redissonLockUtil.tryLock(30000L, -1L, "265213225444411", LockType.REENTRANT_LOCK.value()); Tuple2<RLock, Boolean> rlocks = redissonLockUtil.tryLock(30000L, -1L, "265213225444411", LockType.REENTRANT_LOCK.value());
if (rlocks.getT2()) { if (rlocks.getT2()) {
log.info(threadId + "拿锁成功"+ dateFormat.format(new Date())); log.info(threadId + "拿锁成功"+ dateFormat.format(new Date()));
...@@ -83,7 +83,7 @@ public class TestController { ...@@ -83,7 +83,7 @@ public class TestController {
e.printStackTrace(); e.printStackTrace();
return new ResultForLock().error(); return new ResultForLock().error();
}finally { }finally {
redissonLockUtil.releaseLock("265213225444411", LockType.REENTRANT_LOCK.value()); redissonLockUtil.releaseLock(rlocks.getT1());
} }
} else { } else {
System.out.println("拿锁失败"); System.out.println("拿锁失败");
...@@ -126,7 +126,7 @@ public class TestController { ...@@ -126,7 +126,7 @@ public class TestController {
@PostMapping ("api/fair") @PostMapping ("api/fair")
public ResultForLock<String> fair() { public ResultForLock<String> fair() {
String threadId = Thread.currentThread().getName() + Thread.currentThread().getId(); String threadId = Thread.currentThread().getName() + Thread.currentThread().getId();
redissonLockUtil.getLockByKey("265213225444411", LockType.FAIR_LOCK.value()); // redissonLockUtil.getLockByKey("265213225444411", LockType.FAIR_LOCK.value());
Tuple2<RLock, Boolean> rlocks = redissonLockUtil.tryLock(20000L, -1L, "265213225444411", LockType.REENTRANT_LOCK.value()); Tuple2<RLock, Boolean> rlocks = redissonLockUtil.tryLock(20000L, -1L, "265213225444411", LockType.REENTRANT_LOCK.value());
if (rlocks.getT2()) { if (rlocks.getT2()) {
System.out.println(threadId + "拿锁成功"); System.out.println(threadId + "拿锁成功");
...@@ -139,7 +139,8 @@ public class TestController { ...@@ -139,7 +139,8 @@ public class TestController {
e.printStackTrace(); e.printStackTrace();
return new ResultForLock().error(); return new ResultForLock().error();
}finally { }finally {
redissonLockUtil.releaseLock("265213225444411", LockType.REENTRANT_LOCK.value()); rlocks.getT1().unlock();
// redissonLockUtil.releaseLock("265213225444411", LockType.REENTRANT_LOCK.value());
} }
} else { } else {
System.out.println("拿锁失败"); System.out.println("拿锁失败");
......
...@@ -24,7 +24,7 @@ import java.util.concurrent.TimeUnit; ...@@ -24,7 +24,7 @@ import java.util.concurrent.TimeUnit;
public class RedissonLockUtil { public class RedissonLockUtil {
public static final Long WAITTIME = 12000L; public static final Long WAITTIME = 10000L;
public static final Long RELEASETIME = -1L; public static final Long RELEASETIME = -1L;
@Autowired @Autowired
...@@ -58,6 +58,7 @@ public class RedissonLockUtil { ...@@ -58,6 +58,7 @@ public class RedissonLockUtil {
/** /**
* 手动加锁,锁的有效期默认30秒 * 手动加锁,锁的有效期默认30秒
*
* @param rLock * @param rLock
*/ */
public void lock(RLock rLock) { public void lock(RLock rLock) {
...@@ -66,6 +67,7 @@ public class RedissonLockUtil { ...@@ -66,6 +67,7 @@ public class RedissonLockUtil {
/** /**
* 手动解锁 * 手动解锁
*
* @param rLock * @param rLock
*/ */
public void unlock(RLock rLock) { public void unlock(RLock rLock) {
...@@ -76,15 +78,16 @@ public class RedissonLockUtil { ...@@ -76,15 +78,16 @@ public class RedissonLockUtil {
/** /**
* 当releaseTime传的是-1或者是空时,开启watch dog模式,会开启自动续锁 * 当releaseTime传的是-1或者是空时,开启watch dog模式,会开启自动续锁
* 非阻塞式 * 非阻塞式
*
* @param waitTime 等待时间 * @param waitTime 等待时间
* @param releaseTime 锁有效时间 * @param releaseTime 锁有效时间
* @param key * @param key
* @param type * @param type
* @return * @return
*/ */
public Tuple2<RLock,Boolean> tryLock(Long waitTime, Long releaseTime, String key, int type) { public Tuple2<RLock, Boolean> tryLock(Long waitTime, Long releaseTime, String key, int type) {
boolean lock = false; boolean lock = false;
RLock rLock =null; RLock rLock = null;
if (ObjectUtils.isEmpty(waitTime)) { if (ObjectUtils.isEmpty(waitTime)) {
waitTime = WAITTIME; waitTime = WAITTIME;
} }
...@@ -97,33 +100,32 @@ public class RedissonLockUtil { ...@@ -97,33 +100,32 @@ public class RedissonLockUtil {
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
return Tuples.of(rLock,lock); return Tuples.of(rLock, lock);
} }
/** /**
* 手动释放 redissonLock 锁 * 手动释放 redissonLock 锁
* *
* @param key * @param rLock
* @return * @return
*/ */
public boolean releaseLock(String key, int type) { public boolean releaseLock(RLock rLock) {
String threadName = Thread.currentThread().getName() + ":" + Thread.currentThread().getId(); String threadName = Thread.currentThread().getName() + ":" + Thread.currentThread().getId();
try { try {
RLock rLock = getLockByKey(key, type);
rLock.unlock(); rLock.unlock();
if (!rLock.isLocked()) { if (!rLock.isLocked()) {
log.debug("已删除锁{}成功,当前线程:{}", key, threadName); log.debug("已删除锁{}成功,当前线程:{}", rLock.getName(), threadName);
return true; return true;
} else if (rLock.isHeldByCurrentThread()) { } else if (rLock.isHeldByCurrentThread()) {
log.debug("未删除锁{},还需当前线程解锁{}次,当前线程:{}", key, rLock.getHoldCount(), threadName); log.debug("未删除锁{},还需当前线程解锁{}次,当前线程:{}", rLock.getName(), rLock.getHoldCount(), threadName);
return true; return true;
} else { } else {
log.warn("未删除锁{},还需其他线程解锁{}次,当前线程:{}", key, rLock.getHoldCount(), threadName); log.warn("未删除锁{},还需其他线程解锁{}次,当前线程:{}", rLock.getName(), rLock.getHoldCount(), threadName);
return false; return false;
} }
} catch (Throwable e) { } catch (Throwable e) {
log.error("解锁{}异常,返回false,当前线程:{}", key, threadName, e); log.error("解锁{}异常,返回false,当前线程:{}", threadName, e);
return false; return false;
} }
} }
......
package com.mushiny.redisson.utils; package com.mushiny.redisson.utils;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.RandomUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.UUID; import java.util.Random;
/** /**
* 描述信息 * 雪花算法的原理就是生成一个的 64 位比特位的 long 类型的唯一 id。开头一位固定0,41位时间戳,5位机器id,5位服务id,12位序号
* *
* @auther lxy * @auther lxy
* @since 2023/8/9 13:57 * @since 2023/8/9 13:57
*/ */
@Component
public class SnowFlakeUtil { public class SnowFlakeUtil {
/** /**
* 起始时间戳,从2023-08-01开始生成 * 起始时间戳,从2023-08-01开始生成
*/ */
@Value("${snowflake.config.stamp:1690819200000L}")
private final static long START_STAMP = 1690819200000L; private final static long START_STAMP = 1690819200000L;
/** /**
* 序列号占用的位数 12 * 序列号占用的位数 12
*/ */
private final static long SEQUENCE_BIT = 22; private final static long SEQUENCE_BIT = 12;
/** /**
* 机器标识占用的位数 * 机器标识占用的位数
...@@ -47,6 +51,7 @@ public class SnowFlakeUtil { ...@@ -47,6 +51,7 @@ public class SnowFlakeUtil {
/** /**
* 机器标识 * 机器标识
*/ */
@Value("${snowflake.config.machineId:160}")
private long machineId; private long machineId;
/** /**
* 序列号 * 序列号
...@@ -57,16 +62,18 @@ public class SnowFlakeUtil { ...@@ -57,16 +62,18 @@ public class SnowFlakeUtil {
*/ */
private long lastStamp = -1L; private long lastStamp = -1L;
/**
* 构造方法 @Value("${snowflake.config.id.length:16")
* private int length = 16;
* @param machineId 机器ID
*/ @Value("${snowflake.config.id.strLength:16}")
public SnowFlakeUtil(long machineId) { private int strLength = 25;
public SnowFlakeUtil() {
if (machineId > MAX_MACHINE_NUM || machineId < 0) { if (machineId > MAX_MACHINE_NUM || machineId < 0) {
throw new RuntimeException("机器超过最大数量"); throw new RuntimeException("机器超过最大数量");
} }
this.machineId = machineId;
} }
/** /**
...@@ -89,22 +96,32 @@ public class SnowFlakeUtil { ...@@ -89,22 +96,32 @@ public class SnowFlakeUtil {
// 不同毫秒内,序列号置为0 // 不同毫秒内,序列号置为0
sequence = 0L; sequence = 0L;
} }
lastStamp = currStamp; lastStamp = currStamp;
return transferLength((currStamp - START_STAMP) << TIMESTAMP_LEFT | machineId << MACHINE_LEFT | sequence);
return (currStamp - START_STAMP) << TIMESTAMP_LEFT // 时间戳部分
| machineId << MACHINE_LEFT // 机器标识部分
| sequence; // 序列号部分
} }
/** /**
* 产生下一个String类型的ID * 产生下一个String类型的ID(随机5位字符串加上雪花算法id)
*/ */
public synchronized String nextStrId() { public synchronized String nextStrId() {
String prefix = RandomUtil.randomString(5); long currStamp = getNewStamp();
String netId = String.valueOf(nextId()); if (currStamp < lastStamp) {
return prefix + netId; throw new RuntimeException("时钟后移,拒绝生成ID!");
}
if (currStamp == lastStamp) {
// 相同毫秒内,序列号自增
sequence = (sequence + 1) & MAX_SEQUENCE;
// 同一毫秒的序列数已经达到最大
if (sequence == 0L) {
currStamp = getNextMill();
}
} else {
// 不同毫秒内,序列号置为0
sequence = 0L;
}
lastStamp = currStamp;
return transferLength(String.valueOf((currStamp - START_STAMP) << TIMESTAMP_LEFT | machineId << MACHINE_LEFT | sequence));
} }
private long getNextMill() { private long getNextMill() {
...@@ -120,4 +137,43 @@ public class SnowFlakeUtil { ...@@ -120,4 +137,43 @@ public class SnowFlakeUtil {
} }
/**
* Long类型id转换长度
*
* @param id
* @return
*/
private long transferLength(Long id) {
if (length < 20 && length > 15) {
id = Long.parseLong(StringUtils.rightPad(id.toString(), length, "0"));
}
if (length > 19) {
id = Long.parseLong(StringUtils.rightPad(id.toString(), 19, "0"));
}
return id;
}
/**
* String类型id转换长度
*
* @param id
* @return
*/
private String transferLength(String id) {
if (strLength > 16) {
id = RandomUtil.randomString(strLength - id.length()) + id;
}
return id;
}
public static void main(String[] args) {
SnowFlakeUtil snowFlakeUtil = new SnowFlakeUtil();
Long nextId = snowFlakeUtil.nextId();
String nextStrId = snowFlakeUtil.nextStrId();
System.out.println("Long类型的为" + nextId + "长度为" + nextId.toString().length());
System.out.println("String类型的为" + nextStrId + "长度为" + nextStrId.length());
}
} }
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