分布式id生成解决方案
百度uid-generator生成
依赖
<dependency>
<groupId>com.baidu.fsg</groupId>
<artifactId>uid-generator</artifactId>
<version>1.0.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</exclusion>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</exclusion>
</exclusions>
</dependency>
数据库脚本
CREATE TABLE `sy_worker_node` (
`work_node_id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`host_name` varchar(64) NOT NULL COMMENT '主机名称',
`port` varchar(64) NOT NULL COMMENT '端口',
`type` int NOT NULL COMMENT '类型(ACTUAL or CONTAINER)',
`launch_date` date NOT NULL COMMENT '年月日',
`modeified` timestamp NOT NULL COMMENT '修改时间',
`created` timestamp NOT NULL COMMENT '创建时间',
PRIMARY KEY (`work_node_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
实体
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;
import lombok.Setter;
import java.util.Date;
@TableName("sy_worker_node")
@Getter
@Setter
public class WorkNode {
@TableId(value = "work_node_id", type = IdType.AUTO)
private Long work_node_id;
@TableField(value = "host_name")
private String host_name;
@TableField(value = "port")
private String port;
@TableField(value = "type")
private Integer type;
@TableField(value = "launch_date")
private Date launch_date;
@TableField(value = "modeified")
private Date modeified;
@TableField(value = "created")
private Date created;
}
mapper
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tutaojin.backend.domain.id.po.WorkNode;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface WorkerNodeMapper extends BaseMapper<WorkNode> {
}
service
import com.baomidou.mybatisplus.extension.service.IService;
import com.tutaojin.backend.domain.id.po.WorkNode;
public interface IWorkNodeService extends IService<WorkNode> {
public WorkNode getWorkerNodeByHostPort(String host, String port);
public void addWorkerNode(WorkNode workNode);
}
service实现
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tutaojin.backend.domain.id.infrastructure.dao.WorkerNodeMapper;
import com.tutaojin.backend.domain.id.po.WorkNode;
import com.tutaojin.backend.domain.id.service.IWorkNodeService;
import org.springframework.stereotype.Service;
import java.util.Date;
@Service("workNodeService")
public class WorkNodeServiceImpl extends ServiceImpl<WorkerNodeMapper, WorkNode> implements IWorkNodeService {
@Override
public WorkNode getWorkerNodeByHostPort(String host, String port) {
QueryWrapper<WorkNode> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(WorkNode::getHost_name, host).eq(WorkNode::getPort, port);
return getOne(queryWrapper);
}
@Override
public void addWorkerNode(WorkNode workNode) {
workNode.setCreated(new Date());
workNode.setModeified(new Date());
save(workNode);
}
}
配置类
import com.baidu.fsg.uid.impl.CachedUidGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class IdGeneratorConfiguration {
/*
该类是在默认的基础上修改的
*/
@Bean
public DisposableWorkerIdAssigner disposableWorkerIdAssigner() {
return new DisposableWorkerIdAssigner();
}
//默认注入的id生成器,使用时只需从容器取即可
@Bean
public CachedUidGenerator cachedUidGenerator() {
CachedUidGenerator cachedUidGenerator = new CachedUidGenerator();
cachedUidGenerator.setWorkerIdAssigner(disposableWorkerIdAssigner());
return cachedUidGenerator;
}
}
import com.baidu.fsg.uid.utils.DockerUtils;
import com.baidu.fsg.uid.utils.NetUtils;
import com.baidu.fsg.uid.worker.WorkerIdAssigner;
import com.baidu.fsg.uid.worker.WorkerNodeType;
import com.tutaojin.backend.domain.id.po.WorkNode;
import com.tutaojin.backend.domain.id.service.IWorkNodeService;
import org.apache.commons.lang.math.RandomUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
public class DisposableWorkerIdAssigner implements WorkerIdAssigner {
private static final Logger LOGGER = LoggerFactory.getLogger(DisposableWorkerIdAssigner.class);
/*
@Autowired
private WorkerNodeMapper workerNodeMapper;
*/
//修改默认注入mapper为service接口
@Autowired
private IWorkNodeService workNodeService;
/**
* Assign worker id base on database.<p>
* If there is host name & port in the environment, we considered that the node runs in Docker container<br>
* Otherwise, the node runs on an actual machine.
*
* @return assigned worker id
*/
@Transactional
public long assignWorkerId() {
// build worker node entity
WorkNode workNode = buildWorkerNode();
// add worker node for new (ignore the same IP + PORT)
workNodeService.addWorkerNode(workNode);
LOGGER.info("Add worker node:" + workNode);
return workNode.getWork_node_id();
}
/**
* Build worker node entity by IP and PORT
*/
private WorkNode buildWorkerNode() {
WorkNode workNode = new WorkNode();
if (DockerUtils.isDocker()) {
workNode.setType(WorkerNodeType.CONTAINER.value());
workNode.setHost_name(DockerUtils.getDockerHost());
workNode.setPort(DockerUtils.getDockerPort());
workNode.setLaunch_date(new Date());
} else {
workNode.setType(WorkerNodeType.ACTUAL.value());
workNode.setHost_name(NetUtils.getLocalAddress());
workNode.setPort(System.currentTimeMillis() + "-" + RandomUtils.nextInt(100000));
workNode.setLaunch_date(new Date());
}
return workNode;
}
}
生成id 工具类
import com.baidu.fsg.uid.UidGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class RandomUUidUtils {
public static RandomUUidUtils randomUUidUtils;
@Autowired
private UidGenerator uidGenerator;
@PostConstruct
public void init() {
randomUUidUtils = this;
}
public static Long getUUid() {
return randomUUidUtils.uidGenerator.getUID();
}
}