From e311e7c50062115c390c16966c5a8d294eb964b6 Mon Sep 17 00:00:00 2001 From: tanwenhai Date: Tue, 15 Dec 2020 16:11:02 +0800 Subject: [PATCH] id generate --- .../core/repository/ServerInfoRepository.java | 9 ++++ .../server/service/id/IdGenerateService.java | 52 ++++++++++++++----- .../resources/application-daily.properties | 17 ++---- 3 files changed, 51 insertions(+), 27 deletions(-) diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/repository/ServerInfoRepository.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/repository/ServerInfoRepository.java index 615933f2..7f0b70ba 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/repository/ServerInfoRepository.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/repository/ServerInfoRepository.java @@ -2,6 +2,11 @@ package com.github.kfcfans.powerjob.server.persistence.core.repository; import com.github.kfcfans.powerjob.server.persistence.core.model.ServerInfoDO; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Lock; +import org.springframework.data.jpa.repository.Query; + +import javax.persistence.LockModeType; +import java.util.List; /** * 服务器信息 数据操作层 @@ -11,4 +16,8 @@ import org.springframework.data.jpa.repository.JpaRepository; */ public interface ServerInfoRepository extends JpaRepository { ServerInfoDO findByIp(String ip); + + @Query("select t from ServerInfoDO as t order by t.id asc") + @Lock(LockModeType.PESSIMISTIC_WRITE) + List findAllAndLockTable(); } diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/IdGenerateService.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/IdGenerateService.java index e56462fa..bf3f0ee7 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/IdGenerateService.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/IdGenerateService.java @@ -3,9 +3,23 @@ package com.github.kfcfans.powerjob.server.service.id; import com.github.kfcfans.powerjob.common.utils.NetUtils; import com.github.kfcfans.powerjob.server.persistence.core.model.ServerInfoDO; import com.github.kfcfans.powerjob.server.persistence.core.repository.ServerInfoRepository; +import com.google.common.base.Throwables; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.jdbc.support.JdbcUtils; import org.springframework.stereotype.Service; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.support.TransactionTemplate; +import org.springframework.util.Assert; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; /** * 唯一ID生成服务,使用 Twitter snowflake 算法 @@ -24,20 +38,32 @@ public class IdGenerateService { private static final int DATA_CENTER_ID = 0; @Autowired - public IdGenerateService(ServerInfoRepository serverInfoRepository) { + public IdGenerateService(ServerInfoRepository serverInfoRepository, + @Qualifier("coreTransactionManager") PlatformTransactionManager platformTransactionManager) { + TransactionTemplate transactionTemplate = new TransactionTemplate(platformTransactionManager); + // 服务频繁重启,数据库id自增值过大,使用表锁获取机器id + snowFlakeIdGenerator = transactionTemplate.execute(action -> { + List serverInfos = serverInfoRepository.findAllAndLockTable(); + String ip = NetUtils.getLocalHost(); + ServerInfoDO server = serverInfoRepository.findByIp(ip); + Long id = null; + if (server == null) { + ServerInfoDO newServerInfo = new ServerInfoDO(ip); + serverInfoRepository.saveAndFlush(newServerInfo); + id = serverInfos.size() + 1L; + } else { + for (int i = 0, len = serverInfos.size(); i < len; i++) { + if (Objects.equals(serverInfos.get(i).getId(), server.getId())) { + id = i + 1L; + break; + } + } + } + Assert.notNull(id, "[IdGenerateService] init snowflake error, id is null"); + log.info("[IdGenerateService] init snowflake for server(address={}) by machineId({}).", ip, id); - 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); + return new SnowFlakeIdGenerator(DATA_CENTER_ID, id); + }); } /** diff --git a/powerjob-server/src/main/resources/application-daily.properties b/powerjob-server/src/main/resources/application-daily.properties index 18bb67ef..32d7da66 100644 --- a/powerjob-server/src/main/resources/application-daily.properties +++ b/powerjob-server/src/main/resources/application-daily.properties @@ -3,28 +3,17 @@ logging.config=classpath:logback-dev.xml ####### 外部数据库配置(需要用户更改为自己的数据库配置) ####### spring.datasource.core.driver-class-name=com.mysql.cj.jdbc.Driver -spring.datasource.core.jdbc-url=jdbc:mysql://localhost:3306/powerjob-daily?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai +spring.datasource.core.jdbc-url=jdbc:mysql://localhost:3306/powerjob?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai spring.datasource.core.username=root -spring.datasource.core.password=No1Bug2Please3! +spring.datasource.core.password=123456 spring.datasource.core.hikari.maximum-pool-size=20 spring.datasource.core.hikari.minimum-idle=5 ####### mongoDB配置,非核心依赖,通过配置 oms.mongodb.enable=false 来关闭 ####### -oms.mongodb.enable=true +oms.mongodb.enable=false spring.data.mongodb.uri=mongodb+srv://zqq:No1Bug2Please3!@cluster0.wie54.gcp.mongodb.net/powerjob_daily?retryWrites=true&w=majority -####### 邮件配置(不需要邮件报警可以删除以下配置来避免报错) ####### -spring.mail.host=smtp.163.com -spring.mail.username=zqq@163.com -spring.mail.password=GOFZPNARMVKCGONV -spring.mail.properties.mail.smtp.auth=true -spring.mail.properties.mail.smtp.starttls.enable=true -spring.mail.properties.mail.smtp.starttls.required=true -####### 钉钉报警配置(不需要钉钉报警可以删除以下配置来避免报错) ####### -oms.alarm.ding.app-key=dingauqwkvxxnqskknfv -oms.alarm.ding.app-secret=XWrEPdAZMPgJeFtHuL0LH73LRj-74umF2_0BFcoXMfvnX0pCQvt0rpb1JOJU_HLl -oms.alarm.ding.agent-id=847044348 ####### 资源清理配置 ####### oms.instanceinfo.retention=1