分布式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();
    }
}
posted @ 2022-06-14 10:58  紫川先生  阅读(67)  评论(0编辑  收藏  举报