provide fully support for snowflake

This commit is contained in:
tjq 2020-04-15 13:10:10 +08:00
parent 07d63df4d7
commit 19ffe6d052
10 changed files with 135 additions and 29 deletions

View File

@ -0,0 +1,38 @@
package com.github.kfcfans.oms.server.persistence.model;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.util.Date;
/**
* 服务器信息表用于分配服务器唯一ID
*
* @author tjq
* @since 2020/4/15
*/
@Data
@Entity
@NoArgsConstructor
@Table(name = "server_info", uniqueConstraints = {@UniqueConstraint(columnNames = "ip")})
public class ServerInfoDO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
/**
* 服务器IP地址
*/
private String ip;
private Date gmtCreate;
private Date gmtModified;
public ServerInfoDO(String ip) {
this.ip = ip;
this.gmtCreate = new Date();
this.gmtModified = this.gmtCreate;
}
}

View File

@ -0,0 +1,14 @@
package com.github.kfcfans.oms.server.persistence.repository;
import com.github.kfcfans.oms.server.persistence.model.ServerInfoDO;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* 服务器信息 数据操作层
*
* @author tjq
* @since 2020/4/15
*/
public interface ServerInfoRepository extends JpaRepository<ServerInfoDO, Long> {
ServerInfoDO findByIp(String ip);
}

View File

@ -1,16 +0,0 @@
package com.github.kfcfans.oms.server.service;
/**
* 唯一ID生成服务
*
* @author tjq
* @since 2020/4/6
*/
public class IdGenerateService {
public static Long allocate() {
// TODO换成合适的分布式ID生成算法
return System.currentTimeMillis();
}
}

View File

@ -0,0 +1,53 @@
package com.github.kfcfans.oms.server.service.id;
import com.github.kfcfans.common.utils.NetUtils;
import com.github.kfcfans.oms.server.persistence.model.ServerInfoDO;
import com.github.kfcfans.oms.server.persistence.repository.ServerInfoRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* 唯一ID生成服务使用 Twitter snowflake 算法
* 机房ID固定为0占用三位8个机房怎么样也够了吧
* 机器ID数据库自增占用7位最多支持128台机器
*
* @author tjq
* @since 2020/4/6
*/
@Slf4j
@Service
public class IdGenerateService {
private SnowFlakeIdGenerator snowFlakeIdGenerator;
private static final int DATA_CENTER_ID = 0;
@Autowired
public IdGenerateService(ServerInfoRepository serverInfoRepository) {
String ip = NetUtils.getLocalHost();
ServerInfoDO server = serverInfoRepository.findByIp(ip);
if (server == null) {
ServerInfoDO newServerInfo = new ServerInfoDO(ip);
server = serverInfoRepository.saveAndFlush(newServerInfo);
}
Long id = server.getId();
snowFlakeIdGenerator = new SnowFlakeIdGenerator(DATA_CENTER_ID, id);
log.info("[IdGenerateService] init snowflake for server(address={}) by machineId({}).", ip, id);
}
/**
* 分配分布式唯一ID
* @return 分布式唯一ID
*/
public long allocate() {
return snowFlakeIdGenerator.nextId();
}
}

View File

@ -1,4 +1,4 @@
package com.github.kfcfans.oms.server.common.utils.snowflake; package com.github.kfcfans.oms.server.service.id;
/** /**
* Twitter SnowFlakeScala -> Java * Twitter SnowFlakeScala -> Java
@ -6,19 +6,19 @@ package com.github.kfcfans.oms.server.common.utils.snowflake;
* @author tjq * @author tjq
* @since 2020/4/6 * @since 2020/4/6
*/ */
public class SnowFlakeIdGenerator { class SnowFlakeIdGenerator {
/** /**
* 起始的时间戳 * 起始的时间戳(a special day for me)
*/ */
private final static long START_STAMP = 1480166465631L; private final static long START_STAMP = 1555776000000L;
/** /**
* 每一部分占用的位数 * 每一部分占用的位数
*/ */
private final static long SEQUENCE_BIT = 12; //序列号占用的位数 private final static long SEQUENCE_BIT = 12; //序列号占用的位数
private final static long MACHINE_BIT = 5; //机器标识占用的位数 private final static long MACHINE_BIT = 7; //机器标识占用的位数
private final static long DATA_CENTER_BIT = 5;//数据中心占用的位数 private final static long DATA_CENTER_BIT = 3;//数据中心占用的位数
/** /**
* 每一部分的最大值 * 每一部分的最大值
@ -56,7 +56,7 @@ public class SnowFlakeIdGenerator {
public synchronized long nextId() { public synchronized long nextId() {
long currStamp = getNewStamp(); long currStamp = getNewStamp();
if (currStamp < lastTimestamp) { if (currStamp < lastTimestamp) {
throw new RuntimeException("Clock moved backwards. Refusing to generate id"); throw new RuntimeException("clock moved backwards, refusing to generate id");
} }
if (currStamp == lastTimestamp) { if (currStamp == lastTimestamp) {

View File

@ -13,7 +13,7 @@ import com.github.kfcfans.oms.server.persistence.repository.AppInfoRepository;
import com.github.kfcfans.oms.server.persistence.repository.JobInfoRepository; import com.github.kfcfans.oms.server.persistence.repository.JobInfoRepository;
import com.github.kfcfans.oms.server.persistence.repository.InstanceLogRepository; import com.github.kfcfans.oms.server.persistence.repository.InstanceLogRepository;
import com.github.kfcfans.oms.server.service.DispatchService; import com.github.kfcfans.oms.server.service.DispatchService;
import com.github.kfcfans.oms.server.service.IdGenerateService; import com.github.kfcfans.oms.server.service.id.IdGenerateService;
import com.github.kfcfans.oms.server.service.ha.WorkerManagerService; import com.github.kfcfans.oms.server.service.ha.WorkerManagerService;
import com.google.common.base.Stopwatch; import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
@ -46,7 +46,8 @@ public class JobScheduleService {
@Resource @Resource
private DispatchService dispatchService; private DispatchService dispatchService;
@Resource
private IdGenerateService idGenerateService;
@Resource @Resource
private AppInfoRepository appInfoRepository; private AppInfoRepository appInfoRepository;
@Resource @Resource
@ -109,7 +110,7 @@ public class JobScheduleService {
InstanceLogDO executeLog = new InstanceLogDO(); InstanceLogDO executeLog = new InstanceLogDO();
executeLog.setJobId(jobInfoDO.getId()); executeLog.setJobId(jobInfoDO.getId());
executeLog.setAppId(jobInfoDO.getAppId()); executeLog.setAppId(jobInfoDO.getAppId());
executeLog.setInstanceId(IdGenerateService.allocate()); executeLog.setInstanceId(idGenerateService.allocate());
executeLog.setStatus(InstanceStatus.WAITING_DISPATCH.getV()); executeLog.setStatus(InstanceStatus.WAITING_DISPATCH.getV());
executeLog.setExpectedTriggerTime(jobInfoDO.getNextTriggerTime()); executeLog.setExpectedTriggerTime(jobInfoDO.getNextTriggerTime());
executeLog.setGmtCreate(new Date()); executeLog.setGmtCreate(new Date());

View File

@ -13,7 +13,7 @@ import com.github.kfcfans.oms.server.persistence.repository.JobInfoRepository;
import com.github.kfcfans.common.response.ResultDTO; import com.github.kfcfans.common.response.ResultDTO;
import com.github.kfcfans.oms.server.persistence.model.JobInfoDO; import com.github.kfcfans.oms.server.persistence.model.JobInfoDO;
import com.github.kfcfans.oms.server.service.DispatchService; import com.github.kfcfans.oms.server.service.DispatchService;
import com.github.kfcfans.oms.server.service.IdGenerateService; import com.github.kfcfans.oms.server.service.id.IdGenerateService;
import com.github.kfcfans.oms.server.service.instance.InstanceService; import com.github.kfcfans.oms.server.service.instance.InstanceService;
import com.github.kfcfans.oms.server.web.request.ModifyJobInfoRequest; import com.github.kfcfans.oms.server.web.request.ModifyJobInfoRequest;
import com.github.kfcfans.oms.server.web.request.QueryJobInfoRequest; import com.github.kfcfans.oms.server.web.request.QueryJobInfoRequest;
@ -48,6 +48,8 @@ public class JobController {
@Resource @Resource
private DispatchService dispatchService; private DispatchService dispatchService;
@Resource @Resource
private IdGenerateService idGenerateService;
@Resource
private InstanceService instanceService; private InstanceService instanceService;
@Resource @Resource
@ -163,7 +165,7 @@ public class JobController {
InstanceLogDO executeLog = new InstanceLogDO(); InstanceLogDO executeLog = new InstanceLogDO();
executeLog.setJobId(jobInfoDO.getId()); executeLog.setJobId(jobInfoDO.getId());
executeLog.setAppId(jobInfoDO.getAppId()); executeLog.setAppId(jobInfoDO.getAppId());
executeLog.setInstanceId(IdGenerateService.allocate()); executeLog.setInstanceId(idGenerateService.allocate());
executeLog.setStatus(InstanceStatus.WAITING_DISPATCH.getV()); executeLog.setStatus(InstanceStatus.WAITING_DISPATCH.getV());
executeLog.setExpectedTriggerTime(System.currentTimeMillis()); executeLog.setExpectedTriggerTime(System.currentTimeMillis());
executeLog.setGmtCreate(new Date()); executeLog.setGmtCreate(new Date());

View File

@ -1,5 +1,6 @@
package com.github.kfcfans.oms.server.test; package com.github.kfcfans.oms.server.test;
import com.github.kfcfans.oms.server.service.id.IdGenerateService;
import com.github.kfcfans.oms.server.service.lock.LockService; import com.github.kfcfans.oms.server.service.lock.LockService;
import org.assertj.core.util.Lists; import org.assertj.core.util.Lists;
import org.junit.Test; import org.junit.Test;
@ -22,6 +23,8 @@ public class ServiceTest {
@Resource @Resource
private LockService lockService; private LockService lockService;
@Resource
private IdGenerateService idGenerateService;
@Test @Test
public void testLockService() { public void testLockService() {
@ -45,4 +48,9 @@ public class ServiceTest {
lockService.batchUnLock(lockNames); lockService.batchUnLock(lockNames);
} }
@Test
public void testIdGenerator() {
System.out.println(idGenerateService.allocate());
}
} }

View File

@ -71,4 +71,10 @@ public class UtilsTest {
System.out.println(nextValidTimeAfter); System.out.println(nextValidTimeAfter);
} }
@Test
public void normalTest() {
String s = "000000000111010000001100000000010110100110100000000001000000000000";
System.out.println(s.length());
}
} }

View File

@ -5,7 +5,7 @@
<!-- ConsoleAppender把日志输出到控制台 --> <!-- ConsoleAppender把日志输出到控制台 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder> <encoder>
<pattern>222222%d [%t] %-5level %logger{36}.%M\(%file:%line\) - %msg%n</pattern> <pattern>%d [%t] %-5level %logger{36}.%M\(%file:%line\) - %msg%n</pattern>
<!-- 控制台也要使用UTF-8不要使用GBK否则会中文乱码 --> <!-- 控制台也要使用UTF-8不要使用GBK否则会中文乱码 -->
<charset>UTF-8</charset> <charset>UTF-8</charset>
</encoder> </encoder>