视频056~(完成雪花算法)

master
Administrator 4 years ago
parent 432d5464cb
commit 3d5d86584b

@ -4,6 +4,7 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;
/**
* @author zjw
@ -12,6 +13,10 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@ComponentScan(basePackages = {
"com.mashibing.api",
"com.mashibing.common"
})
public class ApiStarterApp {
public static void main(String[] args) {

@ -6,6 +6,7 @@ import com.mashibing.api.util.R;
import com.mashibing.api.vo.ResultVO;
import com.mashibing.common.enums.ExceptionEnums;
import com.mashibing.common.model.StandardSubmit;
import com.mashibing.common.util.SnowFlakeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
@ -30,6 +31,10 @@ import javax.servlet.http.HttpServletRequest;
@RefreshScope
public class SmsController {
@Autowired
private SnowFlakeUtil snowFlakeUtil;
/**
* 客户端IP地址的请求头信息,多个用','隔开。
*/
@ -80,6 +85,9 @@ public class SmsController {
//=========================调用策略模式的校验链=========================================
checkFilterContext.check(submit);
//========================基于雪花算法生成唯一id,并添加到StandardSubmit对象中=========================================
submit.setSequenceId(snowFlakeUtil.nextId());
//=========================发送到MQ,交给策略模块处理=========================================
return R.ok();
}

@ -16,7 +16,8 @@ public enum ExceptionEnums {
ERROR_MOBILE(-5,"手机号格式不正确"),
BALANCE_NOT_ENOUGH(-6,"客户余额不足"),
PARAMETER_ERROR(-10,"参数不合法!"),
SNOWFLAKE_OUT_OF_RANGE(-11,"雪花算法的机器id或服务id超出最大范围!")
SNOWFLAKE_OUT_OF_RANGE(-11,"雪花算法的机器id或服务id超出最大范围!"),
SNOWFLAKE_TIME_BACK(-12,"雪花算法的服务器出现时间回拨问题!"),
;
private Integer code;

@ -2,15 +2,10 @@ package com.mashibing.common.util;
import com.mashibing.common.enums.ExceptionEnums;
import com.mashibing.common.exception.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
/**
* 雪花算法生成全局唯一ID
@ -24,7 +19,6 @@ import java.util.Date;
* @description
*/
@Component
@Slf4j
public class SnowFlakeUtil {
/**
@ -98,16 +92,64 @@ public class SnowFlakeUtil {
/**
* 时间戳需要位移的位数
*/
private long timestampShift = sequenceBits + serviceIdBits + maxMachineId;
private long timestampShift = sequenceBits + serviceIdBits + machineIdBits;
/**
* 序列的最大值
*/
private long maxSequenceId = -1 ^ (-1 << sequenceBits);
/**
* 记录最近一次获取id的时间
*/
private long lastTimestamp = -1;
/**
* 获取系统时间毫秒值
* @return
*/
private long timeGen(){
return System.currentTimeMillis();
}
public synchronized long nextId(){
//1、 拿到当前系统时间的毫秒值
long timestamp = timeGen();
// 避免时间回拨造成出现重复的id
if(timestamp < lastTimestamp){
// 说明出现了时间回拨
System.out.println("当前服务出现时间回拨!!!");
throw new ApiException(ExceptionEnums.SNOWFLAKE_TIME_BACK);
}
//2、 判断当前生成id的时间和上一次生成的时间
if(timestamp == lastTimestamp){
// 同一毫秒值生成id
sequence = (sequence + 1) & maxSequenceId;
// 0000 10100000 :sequence
// 1111 11111111 :maxSequenceId
if(sequence == 0){
// 进到这个if,说明已经超出了sequence序列的最大取值范围
// 需要等到下一个毫秒再做回来生成具体的值
timestamp = timeGen();
while(timestamp <= lastTimestamp){
// 时间还没动。
timestamp = timeGen();
}
}
}else{
// 另一个时间点生成id
sequence = 0;
}
//3、重新给lastTimestamp复制
lastTimestamp = timestamp;
//4、计算id,将几位值拼接起来。 41bit位的时间,5位的机器,5位的服务 ,12位的序列
return ((timestamp - timeStart) << timestampShift) |
(machineId << machineIdShift) |
(serviceId << serviceIdShift) |
sequence &
Long.MAX_VALUE;
}
}

Loading…
Cancel
Save