mirror of
http://git.pig4cloud.com/pig/pigx.git
synced 2026-11-11 05:19:00 +08:00
refactor(sequence): 重构sequence 使用anyline 实现数据库创表抽象
This commit is contained in:
1 parent
f914c2385a
commit
83935f26ce
23 files changed
+388
-962
No files matched your search
@@ -1,37 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.pig4cloud</groupId>
|
||||
<artifactId>pigx-common</artifactId>
|
||||
<version>5.5.0</version>
|
||||
</parent>
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.pig4cloud</groupId>
|
||||
<artifactId>pigx-common</artifactId>
|
||||
<version>5.5.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>pigx-common-sequence</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<artifactId>pigx-common-sequence</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<description>pigx 分布式发号器</description>
|
||||
<description>pigx 分布式发号器</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.pig4cloud</groupId>
|
||||
<artifactId>pigx-common-core</artifactId>
|
||||
</dependency>
|
||||
<!--mybatis plus-->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-extension</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.pig4cloud</groupId>
|
||||
<artifactId>pigx-common-core</artifactId>
|
||||
</dependency>
|
||||
<!-- redis 实现-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<!--anyline-->
|
||||
<dependency>
|
||||
<groupId>org.anyline</groupId>
|
||||
<artifactId>anyline-environment-spring-data-jdbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.anyline</groupId>
|
||||
<artifactId>anyline-data-jdbc-mysql</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.anyline</groupId>
|
||||
<artifactId>anyline-data-jdbc-postgresql</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.anyline</groupId>
|
||||
<artifactId>anyline-data-jdbc-oracle</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.anyline</groupId>
|
||||
<artifactId>anyline-data-jdbc-dm</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
+45
-21
@@ -17,34 +17,58 @@
|
||||
|
||||
package com.pig4cloud.pigx.common.sequence;
|
||||
|
||||
import com.pig4cloud.pigx.common.sequence.builder.SnowflakeSeqBuilder;
|
||||
import com.pig4cloud.pigx.common.sequence.properties.SequenceSnowflakeProperties;
|
||||
import com.pig4cloud.pigx.common.sequence.sequence.Sequence;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import com.pig4cloud.pigx.common.sequence.properties.BaseSequenceProperties;
|
||||
import com.pig4cloud.pigx.common.sequence.range.impl.db.SequenceTable;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.anyline.metadata.Column;
|
||||
import org.anyline.metadata.Index;
|
||||
import org.anyline.metadata.Table;
|
||||
import org.anyline.proxy.ServiceProxy;
|
||||
import org.anyline.service.AnylineService;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.context.WebServerInitializedEvent;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.event.EventListener;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2019-05-26
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@ComponentScan("com.pig4cloud.pigx.common.sequence")
|
||||
@ConditionalOnMissingBean(Sequence.class)
|
||||
@RequiredArgsConstructor
|
||||
@EnableConfigurationProperties(BaseSequenceProperties.class)
|
||||
public class SequenceAutoConfiguration {
|
||||
|
||||
/**
|
||||
* snowflak 算法作为发号器实现
|
||||
* @param properties
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnBean(SequenceSnowflakeProperties.class)
|
||||
public Sequence snowflakeSequence(SequenceSnowflakeProperties properties) {
|
||||
return SnowflakeSeqBuilder.create().datacenterId(properties.getDatacenterId())
|
||||
.workerId(properties.getWorkerId()).build();
|
||||
}
|
||||
private final BaseSequenceProperties sequenceDbProperties;
|
||||
|
||||
}
|
||||
/**
|
||||
* 启动后自动创建表
|
||||
*/
|
||||
@EventListener({WebServerInitializedEvent.class})
|
||||
public void onApplicationReady() throws Exception {
|
||||
// 判断是否需要创建表
|
||||
AnylineService service = ServiceProxy.service();
|
||||
Table tableMetadata = service.metadata().table(sequenceDbProperties.getDb().getTableName(), false);
|
||||
if (Objects.isNull(tableMetadata)) {
|
||||
Table table = Table.from(SequenceTable.class);
|
||||
table.setName(sequenceDbProperties.getDb().getTableName());
|
||||
table.setComment("序列号区间管理表");
|
||||
table.setPrimaryKey(SequenceTable.Fields.id);
|
||||
LinkedHashMap<String, Index> indexLinkedHashMap = new LinkedHashMap<>();
|
||||
Index nameUnique = new Index(SequenceTable.Fields.name);
|
||||
nameUnique.setUnique(true);
|
||||
nameUnique.addColumn(new Column(SequenceTable.Fields.name));
|
||||
indexLinkedHashMap.put(SequenceTable.Fields.name, nameUnique);
|
||||
table.setIndexes(indexLinkedHashMap);
|
||||
|
||||
service.ddl().create(table);
|
||||
log.debug("发号器自动创建表成功:{} ", table);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-1
@@ -53,7 +53,6 @@ public class DbSeqBuilder implements SeqBuilder {
|
||||
public Sequence build() {
|
||||
// 利用DB获取区间管理器
|
||||
DbSeqRangeMgr dbSeqRangeMgr = new DbSeqRangeMgr();
|
||||
dbSeqRangeMgr.setDataSource(this.dataSource);
|
||||
dbSeqRangeMgr.setTableName(this.tableName);
|
||||
dbSeqRangeMgr.setRetryTimes(this.retryTimes);
|
||||
dbSeqRangeMgr.setStep(this.step);
|
||||
|
||||
+5
-32
@@ -1,9 +1,11 @@
|
||||
package com.pig4cloud.pigx.common.sequence.builder;
|
||||
|
||||
import com.pig4cloud.pigx.common.core.util.SpringContextHolder;
|
||||
import com.pig4cloud.pigx.common.sequence.range.BizName;
|
||||
import com.pig4cloud.pigx.common.sequence.range.impl.redis.RedisSeqRangeMgr;
|
||||
import com.pig4cloud.pigx.common.sequence.sequence.Sequence;
|
||||
import com.pig4cloud.pigx.common.sequence.sequence.impl.DefaultRangeSequence;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
|
||||
/**
|
||||
* 基于redis取步长,序列号生成器构建者
|
||||
@@ -12,25 +14,11 @@ import com.pig4cloud.pigx.common.sequence.sequence.impl.DefaultRangeSequence;
|
||||
*/
|
||||
public class RedisSeqBuilder implements SeqBuilder {
|
||||
|
||||
/**
|
||||
* 连接redis的IP[必选]
|
||||
*/
|
||||
private String ip;
|
||||
|
||||
/**
|
||||
* 连接redis的port[必选]
|
||||
*/
|
||||
private int port;
|
||||
|
||||
/**
|
||||
* 业务名称[必选]
|
||||
*/
|
||||
private BizName bizName;
|
||||
|
||||
/**
|
||||
* 认证权限,看redis是否配置了需要密码auth[可选]
|
||||
*/
|
||||
private String auth;
|
||||
|
||||
/**
|
||||
* 获取range步长[可选,默认:1000]
|
||||
@@ -42,6 +30,7 @@ public class RedisSeqBuilder implements SeqBuilder {
|
||||
*/
|
||||
private long stepStart = 0;
|
||||
|
||||
|
||||
public static RedisSeqBuilder create() {
|
||||
RedisSeqBuilder builder = new RedisSeqBuilder();
|
||||
return builder;
|
||||
@@ -51,11 +40,9 @@ public class RedisSeqBuilder implements SeqBuilder {
|
||||
public Sequence build() {
|
||||
// 利用Redis获取区间管理器
|
||||
RedisSeqRangeMgr redisSeqRangeMgr = new RedisSeqRangeMgr();
|
||||
redisSeqRangeMgr.setIp(this.ip);
|
||||
redisSeqRangeMgr.setPort(this.port);
|
||||
redisSeqRangeMgr.setAuth(this.auth);
|
||||
redisSeqRangeMgr.setStep(this.step);
|
||||
redisSeqRangeMgr.setStringRedisTemplate(null);
|
||||
redisSeqRangeMgr.setStepStart(stepStart);
|
||||
redisSeqRangeMgr.setStringRedisTemplate(SpringContextHolder.getBean(StringRedisTemplate.class));
|
||||
redisSeqRangeMgr.init();
|
||||
// 构建序列号生成器
|
||||
DefaultRangeSequence sequence = new DefaultRangeSequence();
|
||||
@@ -64,20 +51,6 @@ public class RedisSeqBuilder implements SeqBuilder {
|
||||
return sequence;
|
||||
}
|
||||
|
||||
public RedisSeqBuilder ip(String ip) {
|
||||
this.ip = ip;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RedisSeqBuilder port(int port) {
|
||||
this.port = port;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RedisSeqBuilder auth(String auth) {
|
||||
this.auth = auth;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RedisSeqBuilder step(int step) {
|
||||
this.step = step;
|
||||
|
||||
+26
-13
@@ -1,6 +1,8 @@
|
||||
package com.pig4cloud.pigx.common.sequence.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
@@ -9,21 +11,32 @@ import lombok.Data;
|
||||
* 发号器通用属性
|
||||
*/
|
||||
@Data
|
||||
class BaseSequenceProperties {
|
||||
@ConfigurationProperties(prefix = "pigx.xsequence")
|
||||
public class BaseSequenceProperties {
|
||||
|
||||
/**
|
||||
* 获取range步长[可选,默认:1000]
|
||||
*/
|
||||
private int step = 1000;
|
||||
/**
|
||||
* 获取range步长[可选,默认:1000]
|
||||
*/
|
||||
private int step = 10;
|
||||
|
||||
/**
|
||||
* 序列号分配起始值[可选:默认:0]
|
||||
*/
|
||||
private long stepStart = 0;
|
||||
/**
|
||||
* 序列号分配起始值[可选:默认:0]
|
||||
*/
|
||||
private long stepStart = 0;
|
||||
|
||||
/**
|
||||
* 业务名称
|
||||
*/
|
||||
private String bizName = "pigx";
|
||||
/**
|
||||
* 业务名称
|
||||
*/
|
||||
private String bizName = "pigx";
|
||||
|
||||
|
||||
@NestedConfigurationProperty
|
||||
private SequenceSnowflakeProperties snowflake = new SequenceSnowflakeProperties();
|
||||
|
||||
|
||||
@NestedConfigurationProperty
|
||||
private SequenceRedisProperties redis = new SequenceRedisProperties();
|
||||
|
||||
@NestedConfigurationProperty
|
||||
private SequenceDbProperties db = new SequenceDbProperties();
|
||||
}
|
||||
+9
-19
@@ -5,10 +5,7 @@ package com.pig4cloud.pigx.common.sequence.properties;
|
||||
* @date 2019-05-26
|
||||
*/
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
@@ -17,23 +14,16 @@ import org.springframework.stereotype.Component;
|
||||
* 发号器DB配置属性
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "pigx.xsequence.db")
|
||||
public class SequenceDbProperties extends BaseSequenceProperties {
|
||||
public class SequenceDbProperties {
|
||||
|
||||
/**
|
||||
* 默认数据库类型
|
||||
*/
|
||||
private DbType dbType = DbType.MYSQL;
|
||||
/**
|
||||
* 表名称
|
||||
*/
|
||||
private String tableName = "pigx_sequence";
|
||||
|
||||
/**
|
||||
* 表名称
|
||||
*/
|
||||
private String tableName = "pigx_sequence";
|
||||
|
||||
/**
|
||||
* 重试次数
|
||||
*/
|
||||
private int retryTimes = 1;
|
||||
/**
|
||||
* 重试次数
|
||||
*/
|
||||
private int retryTimes = 1;
|
||||
|
||||
}
|
||||
+2
-6
@@ -6,8 +6,6 @@ package com.pig4cloud.pigx.common.sequence.properties;
|
||||
*/
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
@@ -16,8 +14,6 @@ import org.springframework.stereotype.Component;
|
||||
* 发号器Redis配置属性
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "pigx.xsequence.redis")
|
||||
public class SequenceRedisProperties extends BaseSequenceProperties {
|
||||
public class SequenceRedisProperties {
|
||||
|
||||
}
|
||||
}
|
||||
+9
-13
@@ -1,8 +1,6 @@
|
||||
package com.pig4cloud.pigx.common.sequence.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
@@ -11,18 +9,16 @@ import org.springframework.stereotype.Component;
|
||||
* Snowflake 发号器属性
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "pigx.xsequence.snowflake")
|
||||
public class SequenceSnowflakeProperties extends BaseSequenceProperties {
|
||||
public class SequenceSnowflakeProperties {
|
||||
|
||||
/**
|
||||
* 数据中心ID,值的范围在[0,31]之间,一般可以设置机房的IDC[必选]
|
||||
*/
|
||||
private long datacenterId;
|
||||
/**
|
||||
* 数据中心ID,值的范围在[0,31]之间,一般可以设置机房的IDC[必选]
|
||||
*/
|
||||
private long datacenterId;
|
||||
|
||||
/**
|
||||
* 工作机器ID,值的范围在[0,31]之间,一般可以设置机器编号[必选]
|
||||
*/
|
||||
private long workerId;
|
||||
/**
|
||||
* 工作机器ID,值的范围在[0,31]之间,一般可以设置机器编号[必选]
|
||||
*/
|
||||
private long workerId;
|
||||
|
||||
}
|
||||
+14
-11
@@ -9,17 +9,20 @@ import com.pig4cloud.pigx.common.sequence.exception.SeqException;
|
||||
*/
|
||||
public interface SeqRangeMgr {
|
||||
|
||||
/**
|
||||
* 获取指定区间名的下一个区间
|
||||
* @param name 区间名
|
||||
* @return 返回区间
|
||||
* @throws SeqException 异常
|
||||
*/
|
||||
SeqRange nextRange(String name) throws SeqException;
|
||||
/**
|
||||
* 获取指定区间名的下一个区间
|
||||
*
|
||||
* @param name 区间名
|
||||
* @return 返回区间
|
||||
* @throws SeqException 异常
|
||||
*/
|
||||
SeqRange nextRange(String name) throws SeqException;
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
default void init() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
void init();
|
||||
|
||||
}
|
||||
+62
-191
@@ -1,13 +1,15 @@
|
||||
package com.pig4cloud.pigx.common.sequence.range.impl.db;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
|
||||
import com.pig4cloud.pigx.common.core.util.SpringContextHolder;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import com.pig4cloud.pigx.common.sequence.exception.SeqException;
|
||||
import com.pig4cloud.pigx.common.sequence.range.impl.db.provider.SqlProviderFactory;
|
||||
import org.anyline.data.param.ConfigStore;
|
||||
import org.anyline.data.param.init.DefaultConfigStore;
|
||||
import org.anyline.entity.DataRow;
|
||||
import org.anyline.proxy.ServiceProxy;
|
||||
import org.anyline.service.AnylineService;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 操作DB帮助类
|
||||
@@ -15,198 +17,67 @@ import java.sql.*;
|
||||
* @author xuan on 2018/4/29.
|
||||
*/
|
||||
abstract class BaseDbHelper {
|
||||
private static final long DELTA = 100000000L;
|
||||
|
||||
private static final SqlProviderFactory SQL_PROVIDER_FACTORY = SpringContextHolder
|
||||
.getBean(SqlProviderFactory.class);
|
||||
|
||||
private static final long DELTA = 100000000L;
|
||||
/**
|
||||
* 更新区间,乐观策略
|
||||
*
|
||||
* @param tableName 表名
|
||||
* @param newValue 更新新数据
|
||||
* @param oldValue 更新旧数据
|
||||
* @param name 区间名称
|
||||
* @return 成功/失败
|
||||
*/
|
||||
static boolean updateRange(String tableName, Long newValue, Long oldValue, String name) {
|
||||
AnylineService service = ServiceProxy.service();
|
||||
SequenceTable sequenceTable = new SequenceTable();
|
||||
sequenceTable.setValue(newValue);
|
||||
sequenceTable.setGmtModified(LocalDateTime.now());
|
||||
ConfigStore configs = new DefaultConfigStore();
|
||||
configs.and("value", oldValue);
|
||||
return service.update(tableName, sequenceTable, configs) > 0;
|
||||
}
|
||||
|
||||
private final static DefaultIdentifierGenerator identifierGenerator = new DefaultIdentifierGenerator();
|
||||
/**
|
||||
* 查询区间,如果区间不存在,会新增一个区间,并返回null,由上层重新执行
|
||||
*
|
||||
* @param tableName 来源
|
||||
* @param name 区间名称
|
||||
* @param stepStart 初始位置
|
||||
* @return 区间值
|
||||
*/
|
||||
static Long selectRange(String tableName, String name, long stepStart) {
|
||||
AnylineService service = ServiceProxy.service();
|
||||
DataRow dataRow = service.query(tableName, SequenceTable.Fields.name + ":" + name);
|
||||
|
||||
/**
|
||||
* 创建表
|
||||
* @param dataSource DB来源
|
||||
* @param tableName 表名
|
||||
*/
|
||||
static void createTable(DataSource dataSource, String tableName) {
|
||||
if (Objects.isNull(dataRow)) {
|
||||
// 没有此类型数据,需要初始化
|
||||
SequenceTable sequenceTable = new SequenceTable();
|
||||
sequenceTable.setId(RandomUtil.getSecureRandom().nextLong());
|
||||
sequenceTable.setName(name);
|
||||
sequenceTable.setValue(stepStart);
|
||||
sequenceTable.setGmtCreate(LocalDateTime.now());
|
||||
sequenceTable.setGmtModified(LocalDateTime.now());
|
||||
service.insert(tableName, sequenceTable);
|
||||
return stepStart;
|
||||
}
|
||||
long oldValue = dataRow.getLong(SequenceTable.Fields.value);
|
||||
|
||||
Connection conn = null;
|
||||
Statement stmt = null;
|
||||
if (oldValue < 0) {
|
||||
String msg = "Sequence value cannot be less than zero, value = " + oldValue
|
||||
+ ", please check table sequence" + tableName;
|
||||
throw new SeqException(msg);
|
||||
}
|
||||
|
||||
try {
|
||||
conn = dataSource.getConnection();
|
||||
stmt = conn.createStatement();
|
||||
stmt.executeUpdate(SQL_PROVIDER_FACTORY.getCreateTableSql().replace("#tableName", tableName));
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw new SeqException(e);
|
||||
}
|
||||
finally {
|
||||
closeQuietly(stmt);
|
||||
closeQuietly(conn);
|
||||
}
|
||||
}
|
||||
if (oldValue > Long.MAX_VALUE - DELTA) {
|
||||
String msg = "Sequence value overflow, value = " + oldValue + ", please check table sequence"
|
||||
+ tableName;
|
||||
throw new SeqException(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入数据区间
|
||||
* @param dataSource DB来源
|
||||
* @param tableName 表名
|
||||
* @param name 区间名称
|
||||
* @param stepStart 初始位置
|
||||
*/
|
||||
private static void insertRange(DataSource dataSource, String tableName, String name, long stepStart) {
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
Connection conn = null;
|
||||
PreparedStatement stmt = null;
|
||||
|
||||
try {
|
||||
conn = dataSource.getConnection();
|
||||
stmt = conn.prepareStatement(SQL_PROVIDER_FACTORY.getInsertRangeSql().replace("#tableName", tableName));
|
||||
stmt.setLong(1, identifierGenerator.nextId(null));
|
||||
stmt.setString(2, name);
|
||||
stmt.setLong(3, stepStart);
|
||||
stmt.setTimestamp(4, new Timestamp(System.currentTimeMillis()));
|
||||
stmt.setTimestamp(5, new Timestamp(System.currentTimeMillis()));
|
||||
stmt.executeUpdate();
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw new SeqException(e);
|
||||
}
|
||||
finally {
|
||||
closeQuietly(stmt);
|
||||
closeQuietly(conn);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新区间,乐观策略
|
||||
* @param dataSource DB来源
|
||||
* @param tableName 表名
|
||||
* @param newValue 更新新数据
|
||||
* @param oldValue 更新旧数据
|
||||
* @param name 区间名称
|
||||
* @return 成功/失败
|
||||
*/
|
||||
static boolean updateRange(DataSource dataSource, String tableName, Long newValue, Long oldValue, String name) {
|
||||
|
||||
Connection conn = null;
|
||||
PreparedStatement stmt = null;
|
||||
|
||||
try {
|
||||
conn = dataSource.getConnection();
|
||||
stmt = conn.prepareStatement(SQL_PROVIDER_FACTORY.getUpdateRangeSql().replace("#tableName", tableName));
|
||||
stmt.setLong(1, newValue);
|
||||
stmt.setTimestamp(2, new Timestamp(System.currentTimeMillis()));
|
||||
stmt.setString(3, name);
|
||||
stmt.setLong(4, oldValue);
|
||||
int affectedRows = stmt.executeUpdate();
|
||||
return affectedRows > 0;
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw new SeqException(e);
|
||||
}
|
||||
finally {
|
||||
closeQuietly(stmt);
|
||||
closeQuietly(conn);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询区间,如果区间不存在,会新增一个区间,并返回null,由上层重新执行
|
||||
* @param dataSource DB来源
|
||||
* @param tableName 来源
|
||||
* @param name 区间名称
|
||||
* @param stepStart 初始位置
|
||||
* @return 区间值
|
||||
*/
|
||||
static Long selectRange(DataSource dataSource, String tableName, String name, long stepStart) {
|
||||
Connection conn = null;
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet rs = null;
|
||||
long oldValue;
|
||||
|
||||
try {
|
||||
conn = dataSource.getConnection();
|
||||
stmt = conn.prepareStatement(SQL_PROVIDER_FACTORY.getSelectRangeSql().replace("#tableName", tableName));
|
||||
stmt.setString(1, name);
|
||||
|
||||
rs = stmt.executeQuery();
|
||||
if (!rs.next()) {
|
||||
// 没有此类型数据,需要初始化
|
||||
insertRange(dataSource, tableName, name, stepStart);
|
||||
return null;
|
||||
}
|
||||
oldValue = rs.getLong(1);
|
||||
|
||||
if (oldValue < 0) {
|
||||
String msg = "Sequence value cannot be less than zero, value = " + oldValue
|
||||
+ ", please check table sequence" + tableName;
|
||||
throw new SeqException(msg);
|
||||
}
|
||||
|
||||
if (oldValue > Long.MAX_VALUE - DELTA) {
|
||||
String msg = "Sequence value overflow, value = " + oldValue + ", please check table sequence"
|
||||
+ tableName;
|
||||
throw new SeqException(msg);
|
||||
}
|
||||
|
||||
return oldValue;
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw new SeqException(e);
|
||||
}
|
||||
finally {
|
||||
closeQuietly(rs);
|
||||
closeQuietly(stmt);
|
||||
closeQuietly(conn);
|
||||
}
|
||||
}
|
||||
|
||||
private static void closeQuietly(AutoCloseable closeable) {
|
||||
if (null != closeable) {
|
||||
try {
|
||||
closeable.close();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Boolean existTable(DataSource dataSource, String tableName) {
|
||||
|
||||
String existTableSql = SQL_PROVIDER_FACTORY.getExistTableSql();
|
||||
if (StrUtil.isBlank(existTableSql)) {
|
||||
return true;
|
||||
}
|
||||
Connection conn = null;
|
||||
Statement stmt = null;
|
||||
|
||||
try {
|
||||
conn = dataSource.getConnection();
|
||||
stmt = conn.createStatement();
|
||||
ResultSet resultSet = stmt
|
||||
.executeQuery(SQL_PROVIDER_FACTORY.getExistTableSql().replace("#tableName", tableName));
|
||||
|
||||
if (!resultSet.next()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int count = resultSet.getInt(1);
|
||||
|
||||
if (0 == count) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw new SeqException(e);
|
||||
}
|
||||
finally {
|
||||
closeQuietly(stmt);
|
||||
closeQuietly(conn);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
+87
-108
@@ -5,7 +5,6 @@ import com.pig4cloud.pigx.common.sequence.exception.SeqException;
|
||||
import com.pig4cloud.pigx.common.sequence.range.SeqRange;
|
||||
import com.pig4cloud.pigx.common.sequence.range.SeqRangeMgr;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@@ -15,137 +14,117 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
public class DbSeqRangeMgr implements SeqRangeMgr {
|
||||
|
||||
/**
|
||||
* 区间步长
|
||||
*/
|
||||
private int step = 1000;
|
||||
/**
|
||||
* 区间步长
|
||||
*/
|
||||
private int step = 1000;
|
||||
|
||||
/**
|
||||
* 区间起始位置,真实从stepStart+1开始
|
||||
*/
|
||||
private long stepStart = 0;
|
||||
/**
|
||||
* 区间起始位置,真实从stepStart+1开始
|
||||
*/
|
||||
private long stepStart = 0;
|
||||
|
||||
/**
|
||||
* 获取区间失败重试次数
|
||||
*/
|
||||
private int retryTimes = 100;
|
||||
/**
|
||||
* 获取区间失败重试次数
|
||||
*/
|
||||
private int retryTimes = 100;
|
||||
|
||||
/**
|
||||
* DB来源
|
||||
*/
|
||||
private DataSource dataSource;
|
||||
/**
|
||||
* 表名,默认range
|
||||
*/
|
||||
private String tableName = "range";
|
||||
|
||||
/**
|
||||
* 表名,默认range
|
||||
*/
|
||||
private String tableName = "range";
|
||||
@Override
|
||||
public SeqRange nextRange(String name) throws SeqException {
|
||||
if (isEmpty(name)) {
|
||||
throw new SecurityException("[DbSeqRangeMgr-nextRange] name is empty.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeqRange nextRange(String name) throws SeqException {
|
||||
if (isEmpty(name)) {
|
||||
throw new SecurityException("[DbSeqRangeMgr-nextRange] name is empty.");
|
||||
}
|
||||
Long oldValue;
|
||||
Long newValue;
|
||||
|
||||
Long oldValue;
|
||||
Long newValue;
|
||||
for (int i = 0; i < getRetryTimes(); i++) {
|
||||
|
||||
for (int i = 0; i < getRetryTimes(); i++) {
|
||||
oldValue = BaseDbHelper.selectRange(getDataSource(), getRealTableName(), name, getStepStart());
|
||||
oldValue = BaseDbHelper.selectRange(getRealTableName(), name, getStepStart());
|
||||
|
||||
if (null == oldValue) {
|
||||
// 区间不存在,重试
|
||||
continue;
|
||||
}
|
||||
if (null == oldValue) {
|
||||
// 区间不存在,重试
|
||||
continue;
|
||||
}
|
||||
|
||||
newValue = oldValue + getStep();
|
||||
newValue = oldValue + getStep();
|
||||
|
||||
if (BaseDbHelper.updateRange(getDataSource(), getRealTableName(), newValue, oldValue, name)) {
|
||||
return new SeqRange(oldValue + 1, newValue);
|
||||
}
|
||||
if (BaseDbHelper.updateRange(getRealTableName(), newValue, oldValue, name)) {
|
||||
return new SeqRange(oldValue + 1, newValue);
|
||||
}
|
||||
|
||||
// else 1秒后 失败重试
|
||||
ThreadUtil.sleep(1, TimeUnit.SECONDS);
|
||||
}
|
||||
// else 1秒后 失败重试
|
||||
ThreadUtil.sleep(1, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
throw new SeqException("Retried too many times, retryTimes = " + getRetryTimes());
|
||||
}
|
||||
throw new SeqException("Retried too many times, retryTimes = " + getRetryTimes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
checkParam();
|
||||
@Override
|
||||
public void init() {
|
||||
checkParam();
|
||||
}
|
||||
|
||||
// 判断是否需要创建表
|
||||
if (BaseDbHelper.existTable(getDataSource(), getRealTableName())) {
|
||||
BaseDbHelper.createTable(getDataSource(), getRealTableName());
|
||||
}
|
||||
}
|
||||
private boolean isEmpty(String str) {
|
||||
return null == str || str.trim().isEmpty();
|
||||
}
|
||||
|
||||
private boolean isEmpty(String str) {
|
||||
return null == str || str.trim().length() == 0;
|
||||
}
|
||||
private String getRealTableName() {
|
||||
return getTableName();
|
||||
}
|
||||
|
||||
private String getRealTableName() {
|
||||
return getTableName();
|
||||
}
|
||||
private void checkParam() {
|
||||
if (step <= 0) {
|
||||
throw new SecurityException("[DbSeqRangeMgr-checkParam] step must greater than 0.");
|
||||
}
|
||||
if (stepStart < 0) {
|
||||
throw new SecurityException("[DbSeqRangeMgr-setStepStart] stepStart < 0.");
|
||||
}
|
||||
if (retryTimes <= 0) {
|
||||
throw new SecurityException("[DbSeqRangeMgr-setRetryTimes] retryTimes must greater than 0.");
|
||||
}
|
||||
if (isEmpty(tableName)) {
|
||||
throw new SecurityException("[DbSeqRangeMgr-setTableName] tableName is empty.");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkParam() {
|
||||
if (step <= 0) {
|
||||
throw new SecurityException("[DbSeqRangeMgr-checkParam] step must greater than 0.");
|
||||
}
|
||||
if (stepStart < 0) {
|
||||
throw new SecurityException("[DbSeqRangeMgr-setStepStart] stepStart < 0.");
|
||||
}
|
||||
if (retryTimes <= 0) {
|
||||
throw new SecurityException("[DbSeqRangeMgr-setRetryTimes] retryTimes must greater than 0.");
|
||||
}
|
||||
if (null == dataSource) {
|
||||
throw new SecurityException("[DbSeqRangeMgr-setDataSource] dataSource is null.");
|
||||
}
|
||||
if (isEmpty(tableName)) {
|
||||
throw new SecurityException("[DbSeqRangeMgr-setTableName] tableName is empty.");
|
||||
}
|
||||
}
|
||||
//////// getter and setter
|
||||
|
||||
//////// getter and setter
|
||||
public int getStep() {
|
||||
return step;
|
||||
}
|
||||
|
||||
public int getStep() {
|
||||
return step;
|
||||
}
|
||||
public void setStep(int step) {
|
||||
this.step = step;
|
||||
}
|
||||
|
||||
public void setStep(int step) {
|
||||
this.step = step;
|
||||
}
|
||||
public long getStepStart() {
|
||||
return stepStart;
|
||||
}
|
||||
|
||||
public long getStepStart() {
|
||||
return stepStart;
|
||||
}
|
||||
public void setStepStart(long stepStart) {
|
||||
this.stepStart = stepStart;
|
||||
}
|
||||
|
||||
public void setStepStart(long stepStart) {
|
||||
this.stepStart = stepStart;
|
||||
}
|
||||
public int getRetryTimes() {
|
||||
return retryTimes;
|
||||
}
|
||||
|
||||
public int getRetryTimes() {
|
||||
return retryTimes;
|
||||
}
|
||||
public void setRetryTimes(int retryTimes) {
|
||||
this.retryTimes = retryTimes;
|
||||
}
|
||||
|
||||
public void setRetryTimes(int retryTimes) {
|
||||
this.retryTimes = retryTimes;
|
||||
}
|
||||
public String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
public DataSource getDataSource() {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
public String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
public void setTableName(String tableName) {
|
||||
this.tableName = tableName;
|
||||
}
|
||||
public void setTableName(String tableName) {
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.pig4cloud.pigx.common.sequence.range.impl.db;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 存储序列化的区间
|
||||
*
|
||||
* @author lengleng
|
||||
* @date 2024/6/6
|
||||
* "CREATE TABLE IF NOT EXISTS #tableName(" + "id bigint(20) NOT NULL AUTO_INCREMENT,"
|
||||
* + "value bigint(20) NOT NULL," + "name varchar(64) NOT NULL," + "gmt_create DATETIME NOT NULL,"
|
||||
* + "gmt_modified DATETIME NOT NULL," + "PRIMARY KEY (`id`),UNIQUE uk_name (`name`)" + ")";
|
||||
*/
|
||||
@Data
|
||||
@FieldNameConstants
|
||||
public class SequenceTable {
|
||||
|
||||
private Long id;
|
||||
|
||||
private Long value;
|
||||
|
||||
private String name;
|
||||
|
||||
private LocalDateTime gmtCreate;
|
||||
|
||||
private LocalDateTime gmtModified;
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
package com.pig4cloud.pigx.common.sequence.range.impl.db.provider;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 数据源提供者
|
||||
*
|
||||
* @author 达梦数据库支持
|
||||
* @date 2022-04-27
|
||||
*
|
||||
* sql server
|
||||
*/
|
||||
@Component
|
||||
public class DmSqlProvider implements SqlProvider {
|
||||
|
||||
/**
|
||||
* 获取表是否存在
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getExistTableSql() {
|
||||
return "select count(*) from user_tables where table_name =upper('#tableName')";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取建表语句
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getCreateTableSql() {
|
||||
return "CREATE TABLE #tableName (ID BIGINT NOT NULL,VALUE BIGINT NOT NULL"
|
||||
+ ",NAME VARCHAR (64) NOT NULL,GMT_CREATE TIMESTAMP (0) NOT NULL,GMT_MODIFIED TIMESTAMP (0) NOT NULL"
|
||||
+ ",NOT CLUSTER PRIMARY KEY (ID),CONSTRAINT UK_NAME UNIQUE (NAME)) STORAGE (ON MAIN,CLUSTERBTR);";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean support(DbType dbType) {
|
||||
return DbType.DM.equals(dbType);
|
||||
}
|
||||
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
package com.pig4cloud.pigx.common.sequence.range.impl.db.provider;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 瀚高数据源
|
||||
*
|
||||
* @author lengleng
|
||||
* @date 2023-04-26
|
||||
*/
|
||||
@Component
|
||||
public class HighGoSqlProvider implements SqlProvider {
|
||||
|
||||
/**
|
||||
* 获取建表语句
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getCreateTableSql() {
|
||||
return "CREATE TABLE IF NOT EXISTS #tableName (ID int8 PRIMARY KEY NOT NULL"
|
||||
+ ",VALUE int8 NOT NULL,NAME VARCHAR (266) NOT NULL,gmt_create TIMESTAMP (6) NOT NULL"
|
||||
+ ",gmt_modified TIMESTAMP (6) NOT NULL)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean support(DbType dbType) {
|
||||
return DbType.HIGH_GO.equals(dbType);
|
||||
}
|
||||
|
||||
}
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
package com.pig4cloud.pigx.common.sequence.range.impl.db.provider;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2023/4/23 kingbase数据库支持
|
||||
*/
|
||||
@Component
|
||||
public class KingbaseSqlProvider implements SqlProvider {
|
||||
|
||||
/**
|
||||
* 获取建表语句
|
||||
* @return SQL
|
||||
*/
|
||||
@Override
|
||||
public String getCreateTableSql() {
|
||||
return "CREATE TABLE IF NOT EXISTS #tableName (ID INT8 PRIMARY KEY NOT NULL,VALUE INT8 NOT NULL,NAME VARCHAR (266) NOT NULL,gmt_create TIMESTAMP (6) NOT NULL,gmt_modified TIMESTAMP (6) NOT NULL)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean support(DbType dbType) {
|
||||
return DbType.KINGBASE_ES.equals(dbType);
|
||||
}
|
||||
|
||||
}
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
package com.pig4cloud.pigx.common.sequence.range.impl.db.provider;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 数据源提供者
|
||||
*
|
||||
* @author hanyichao
|
||||
* @date 2022-04-27
|
||||
*
|
||||
* sql server
|
||||
*/
|
||||
@Component
|
||||
public class MssqlSqlProvider implements SqlProvider {
|
||||
|
||||
/**
|
||||
* 获取建表语句
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getCreateTableSql() {
|
||||
return "IF NOT EXISTS (\n"
|
||||
+ "SELECT*FROM sys.all_objects WHERE object_id=OBJECT_ID(N'#tableName') AND type IN ('U')) \n"
|
||||
+ "CREATE TABLE #tableName (id bigint NOT NULL,VALUE bigint NOT NULL,name nvarchar (64) COLLATE "
|
||||
+ "Chinese_PRC_CI_AS NOT NULL,gmt_create datetime2 (7) NOT NULL,gmt_modified datetime2 (7) NOT NULL) GO";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean support(DbType dbType) {
|
||||
return DbType.SQL_SERVER2005.equals(dbType);
|
||||
}
|
||||
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
package com.pig4cloud.pigx.common.sequence.range.impl.db.provider;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 数据源提供者
|
||||
*
|
||||
* @author lishangbu
|
||||
* @date 2021/12/29
|
||||
*/
|
||||
@Component
|
||||
public class MysqlSqlProvider implements SqlProvider {
|
||||
|
||||
/**
|
||||
* 获取建表语句
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getCreateTableSql() {
|
||||
return "CREATE TABLE IF NOT EXISTS #tableName(" + "id bigint(20) NOT NULL AUTO_INCREMENT,"
|
||||
+ "value bigint(20) NOT NULL," + "name varchar(64) NOT NULL," + "gmt_create DATETIME NOT NULL,"
|
||||
+ "gmt_modified DATETIME NOT NULL," + "PRIMARY KEY (`id`),UNIQUE uk_name (`name`)" + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean support(DbType dbType) {
|
||||
return DbType.MYSQL.equals(dbType);
|
||||
}
|
||||
|
||||
}
|
||||
-56
@@ -1,56 +0,0 @@
|
||||
package com.pig4cloud.pigx.common.sequence.range.impl.db.provider;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* oracle数据源
|
||||
*
|
||||
* @author lishangbu
|
||||
* @date 2021/12/29
|
||||
*/
|
||||
@Component
|
||||
public class OracleSqlProvider implements SqlProvider {
|
||||
|
||||
/**
|
||||
* 获取表是否存在
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getExistTableSql() {
|
||||
return "select count(*) from user_tables where table_name =upper('#tableName')";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取建表语句
|
||||
* @return SQL
|
||||
*/
|
||||
@Override
|
||||
public String getCreateTableSql() {
|
||||
return "CREATE TABLE #tableName " + "(id NUMBER (20,0) VISIBLE NOT NULL,value NUMBER (20,0) VISIBLE NOT NULL"
|
||||
+ ",name VARCHAR2 (96 BYTE) VISIBLE,gmt_create DATE VISIBLE NOT NULL"
|
||||
+ ",gmt_modified DATE VISIBLE NOT NULL)";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取更新范围语句
|
||||
* @return
|
||||
*/
|
||||
public String getUpdateRangeSql() {
|
||||
return "UPDATE #tableName SET value=?,gmt_modified=? WHERE name=? AND value=?";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取查询范围语句
|
||||
* @return
|
||||
*/
|
||||
public String getSelectRangeSql() {
|
||||
return "SELECT value FROM #tableName WHERE name=?";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean support(DbType dbType) {
|
||||
return DbType.ORACLE.equals(dbType);
|
||||
}
|
||||
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
package com.pig4cloud.pigx.common.sequence.range.impl.db.provider;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 数据源提供者
|
||||
*
|
||||
* @author lengleng
|
||||
* @date 2022-01-13
|
||||
*/
|
||||
@Component
|
||||
public class PostgreSqlProvider implements SqlProvider {
|
||||
|
||||
/**
|
||||
* 获取建表语句
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getCreateTableSql() {
|
||||
return "CREATE TABLE IF NOT EXISTS #tableName (ID int8 PRIMARY KEY NOT NULL"
|
||||
+ ",VALUE int8 NOT NULL,NAME VARCHAR (266) NOT NULL,gmt_create TIMESTAMP (6) NOT NULL"
|
||||
+ ",gmt_modified TIMESTAMP (6) NOT NULL)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean support(DbType dbType) {
|
||||
return DbType.POSTGRE_SQL.equals(dbType);
|
||||
}
|
||||
|
||||
}
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
package com.pig4cloud.pigx.common.sequence.range.impl.db.provider;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
|
||||
/**
|
||||
* 数据源提供者
|
||||
*
|
||||
* @author lishangbu
|
||||
* @date 2021/12/29
|
||||
*/
|
||||
public interface SqlProvider {
|
||||
|
||||
/**
|
||||
* 获取表是否存在
|
||||
* @return
|
||||
*/
|
||||
default String getExistTableSql() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取建表语句
|
||||
* @return
|
||||
*/
|
||||
String getCreateTableSql();
|
||||
|
||||
/**
|
||||
* 获取插入范围语句
|
||||
* @return
|
||||
*/
|
||||
default String getInsertRangeSql() {
|
||||
return "INSERT INTO #tableName (id,name,value,gmt_create,gmt_modified)" + " VALUES(?,?,?,?,?)";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取更新范围语句
|
||||
* @return
|
||||
*/
|
||||
default String getUpdateRangeSql() {
|
||||
return "UPDATE #tableName SET value=?,gmt_modified=? WHERE name=? AND value=?";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取查询范围语句
|
||||
* @return
|
||||
*/
|
||||
default String getSelectRangeSql() {
|
||||
return "SELECT value FROM #tableName WHERE name=?";
|
||||
}
|
||||
|
||||
Boolean support(DbType dbType);
|
||||
|
||||
}
|
||||
-101
@@ -1,101 +0,0 @@
|
||||
package com.pig4cloud.pigx.common.sequence.range.impl.db.provider;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils;
|
||||
import com.pig4cloud.pigx.common.sequence.properties.SequenceDbProperties;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* sql语句提供工厂
|
||||
*
|
||||
* @author lishangbu
|
||||
* @date 2021/12/29
|
||||
*/
|
||||
@Lazy(value = false)
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class SqlProviderFactory {
|
||||
|
||||
private final SequenceDbProperties dbProperties;
|
||||
|
||||
private final List<SqlProvider> sqlProviders;
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
public SqlProvider getSqlProvider() {
|
||||
DbType dbType = null;
|
||||
|
||||
String url = environment.getProperty("spring.datasource.druid.url");
|
||||
if (StrUtil.isNotBlank(url)) {
|
||||
dbType = JdbcUtils.getDbType(url);
|
||||
}
|
||||
|
||||
if (dbType == null) {
|
||||
dbType = dbProperties.getDbType();
|
||||
}
|
||||
|
||||
for (SqlProvider sqlProvider : sqlProviders) {
|
||||
if (sqlProvider.support(dbType)) {
|
||||
return sqlProvider;
|
||||
}
|
||||
}
|
||||
throw new UnsupportedOperationException("不支持的数据源");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插入范围语句
|
||||
*
|
||||
* @return 插入范围语句
|
||||
*/
|
||||
public String getCreateTableSql() {
|
||||
SqlProvider sqlProvider = getSqlProvider();
|
||||
return sqlProvider.getCreateTableSql();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插入范围语句
|
||||
*
|
||||
* @return 插入范围语句
|
||||
*/
|
||||
public String getInsertRangeSql() {
|
||||
SqlProvider sqlProvider = getSqlProvider();
|
||||
return sqlProvider.getInsertRangeSql();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取查询范围语句
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getSelectRangeSql() {
|
||||
SqlProvider sqlProvider = getSqlProvider();
|
||||
return sqlProvider.getSelectRangeSql();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取更新范围语句
|
||||
*
|
||||
* @return 更新范围语句
|
||||
*/
|
||||
public String getUpdateRangeSql() {
|
||||
SqlProvider sqlProvider = getSqlProvider();
|
||||
return sqlProvider.getUpdateRangeSql();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取是否创建表语句
|
||||
*
|
||||
* @return SQL语句
|
||||
*/
|
||||
public String getExistTableSql() {
|
||||
SqlProvider sqlProvider = getSqlProvider();
|
||||
return sqlProvider.getExistTableSql();
|
||||
}
|
||||
|
||||
}
|
||||
+52
-110
@@ -1,10 +1,9 @@
|
||||
package com.pig4cloud.pigx.common.sequence.range.impl.redis;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.pig4cloud.pigx.common.sequence.exception.SeqException;
|
||||
import com.pig4cloud.pigx.common.sequence.range.SeqRange;
|
||||
import com.pig4cloud.pigx.common.sequence.range.SeqRangeMgr;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
|
||||
/**
|
||||
* Redis区间管理器
|
||||
@@ -13,126 +12,69 @@ import redis.clients.jedis.Jedis;
|
||||
*/
|
||||
public class RedisSeqRangeMgr implements SeqRangeMgr {
|
||||
|
||||
/**
|
||||
* 前缀防止key重复
|
||||
*/
|
||||
private final static String KEY_PREFIX = "x_sequence_";
|
||||
/**
|
||||
* 前缀防止key重复
|
||||
*/
|
||||
private final static String KEY_PREFIX = "x_sequence_";
|
||||
|
||||
/**
|
||||
* redis客户端
|
||||
*/
|
||||
private Jedis jedis;
|
||||
/**
|
||||
* redis客户端
|
||||
*/
|
||||
private StringRedisTemplate stringRedisTemplate;
|
||||
|
||||
/**
|
||||
* IP
|
||||
*/
|
||||
private String ip;
|
||||
/**
|
||||
* 区间步长
|
||||
*/
|
||||
private int step = 1000;
|
||||
|
||||
/**
|
||||
* PORT
|
||||
*/
|
||||
private Integer port;
|
||||
/**
|
||||
* 区间起始位置,真实从stepStart+1开始
|
||||
*/
|
||||
private long stepStart = 0;
|
||||
|
||||
/**
|
||||
* 验证权限
|
||||
*/
|
||||
private String auth;
|
||||
/**
|
||||
* 标记业务key是否存在,如果false,在取nextRange时,会取check一把 这个boolean只为提高性能,不用每次都取redis check
|
||||
*/
|
||||
private volatile boolean keyAlreadyExist;
|
||||
|
||||
/**
|
||||
* 区间步长
|
||||
*/
|
||||
private int step = 1000;
|
||||
@Override
|
||||
public SeqRange nextRange(String name) throws SeqException {
|
||||
if (!keyAlreadyExist) {
|
||||
|
||||
/**
|
||||
* 区间起始位置,真实从stepStart+1开始
|
||||
*/
|
||||
private long stepStart = 0;
|
||||
if (Boolean.FALSE.equals(stringRedisTemplate.hasKey(getRealKey(name)))) {
|
||||
// 第一次不存在,进行初始化,setnx不存在就set,存在就忽略
|
||||
stringRedisTemplate.opsForValue().setIfAbsent(getRealKey(name), String.valueOf(stepStart));
|
||||
}
|
||||
keyAlreadyExist = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记业务key是否存在,如果false,在取nextRange时,会取check一把 这个boolean只为提高性能,不用每次都取redis check
|
||||
*/
|
||||
private volatile boolean keyAlreadyExist;
|
||||
Long max = stringRedisTemplate.opsForValue().increment(getRealKey(name), step);
|
||||
Long min = max - step + 1;
|
||||
return new SeqRange(min, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeqRange nextRange(String name) throws SeqException {
|
||||
if (!keyAlreadyExist) {
|
||||
Boolean isExists = jedis.exists(getRealKey(name));
|
||||
if (!isExists) {
|
||||
// 第一次不存在,进行初始化,setnx不存在就set,存在就忽略
|
||||
jedis.setnx(getRealKey(name), String.valueOf(stepStart));
|
||||
}
|
||||
keyAlreadyExist = true;
|
||||
}
|
||||
|
||||
Long max = jedis.incrBy(getRealKey(name), step);
|
||||
Long min = max - step + 1;
|
||||
return new SeqRange(min, max);
|
||||
}
|
||||
private String getRealKey(String name) {
|
||||
return KEY_PREFIX + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
checkParam();
|
||||
jedis = new Jedis(ip, port);
|
||||
if (StrUtil.isNotBlank(auth)) {
|
||||
jedis.auth(auth);
|
||||
}
|
||||
}
|
||||
private boolean isEmpty(String str) {
|
||||
return null == str || str.trim().length() == 0;
|
||||
}
|
||||
|
||||
private void checkParam() {
|
||||
if (isEmpty(ip)) {
|
||||
throw new SecurityException("[RedisSeqRangeMgr-checkParam] ip is empty.");
|
||||
}
|
||||
if (null == port) {
|
||||
throw new SecurityException("[RedisSeqRangeMgr-checkParam] port is null.");
|
||||
}
|
||||
}
|
||||
public long getStepStart() {
|
||||
return stepStart;
|
||||
}
|
||||
|
||||
private String getRealKey(String name) {
|
||||
return KEY_PREFIX + name;
|
||||
}
|
||||
public void setStepStart(long stepStart) {
|
||||
this.stepStart = stepStart;
|
||||
}
|
||||
|
||||
private boolean isEmpty(String str) {
|
||||
return null == str || str.trim().length() == 0;
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public void setIp(String ip) {
|
||||
this.ip = ip;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public int getStep() {
|
||||
return step;
|
||||
}
|
||||
|
||||
public void setStep(int step) {
|
||||
this.step = step;
|
||||
}
|
||||
|
||||
public String getAuth() {
|
||||
return auth;
|
||||
}
|
||||
|
||||
public void setAuth(String auth) {
|
||||
this.auth = auth;
|
||||
}
|
||||
|
||||
public long getStepStart() {
|
||||
return stepStart;
|
||||
}
|
||||
|
||||
public void setStepStart(long stepStart) {
|
||||
this.stepStart = stepStart;
|
||||
}
|
||||
public StringRedisTemplate getStringRedisTemplate() {
|
||||
return stringRedisTemplate;
|
||||
}
|
||||
|
||||
public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate) {
|
||||
this.stringRedisTemplate = stringRedisTemplate;
|
||||
}
|
||||
}
|
||||
+4
@@ -110,6 +110,10 @@ public class DefaultRangeSequence implements RangeSequence {
|
||||
this.seqRangeMgr = seqRangeMgr;
|
||||
}
|
||||
|
||||
public SeqRangeMgr getSeqRangeMgr() {
|
||||
return seqRangeMgr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(BizName name) {
|
||||
this.bizName = name;
|
||||
|
||||
Reference in new issue
Block a user