分佈式ID生成方案(六):SpringBoot2.X集成百度UidGenerator

簡介

uid-generator是由百度技術部開發,項目GitHub地址 https://github.com/baidu/uid-generator

UidGenerator是Java實現的, 基於Snowflake算法的唯一ID生成器。

Snowflake算法

在這裏插入圖片描述
Snowflake算法描述:指定機器 & 同一時刻 & 某一併發序列,是唯一的。據此可生成一個64 bits的唯一ID(long)。默認採用上圖字節分配方式:

  • sign(1bit)
    固定1bit符號標識,即生成的UID爲正數。

  • delta seconds (28 bits)
    當前時間,相對於時間基點"2016-05-20"的增量值,單位:秒,最多可支持約8.7年

  • worker id (22 bits)
    機器id,最多可支持約420w次機器啓動。內置實現爲在啓動時由數據庫分配,默認分配策略爲用後即棄,後續可提供複用策略。

  • sequence (13 bits)
    每秒下的併發序列,13 bits可支持每秒8192個併發。

集成步驟

官方文檔上的集成教程都是基於Spring + Mybatis XML配置的,不適用於SpringBoot,所以自己做了一些改造。

1. 將項目導入本地環境,執行maven install

在這裏插入圖片描述
2. 創建數據表

DROP TABLE IF EXISTS WORKER_NODE;
CREATE TABLE WORKER_NODE
(
ID BIGINT NOT NULL AUTO_INCREMENT COMMENT 'auto increment id',
HOST_NAME VARCHAR(64) NOT NULL COMMENT 'host name',
PORT VARCHAR(64) NOT NULL COMMENT 'port',
TYPE INT NOT NULL COMMENT 'node type: ACTUAL or CONTAINER',
LAUNCH_DATE DATE NOT NULL COMMENT 'launch date',
MODIFIED TIMESTAMP NOT NULL COMMENT 'modified time',
CREATED TIMESTAMP NOT NULL COMMENT 'created time',
PRIMARY KEY(ID)
)
 COMMENT='DB WorkerID Assigner for UID Generator',ENGINE = INNODB;

3. 項目中引入uid-generator依賴,並排除其中的mybatis依賴

由於自己的項目是SpringBoot+Mybatisplus,UidGenerator是Spring+Mybatis,直接引入uid-generator之後,本地項目啓動就會出現創建SqlSessionFactory報錯,所以,我直接將uid-generator中的mybatis相關依賴排除。

<dependency>
    <groupId>com.baidu.fsg</groupId>
    <artifactId>uid-generator</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <exclusions>
        <exclusion>
            <groupId>org.mybatis</groupId>
            <artifactId>*</artifactId>
        </exclusion>
    </exclusions>
</dependency>

4. 利用代碼生成工具,將worker_node對應的代碼生成,並拷貝相關源碼

將源碼中的xml中的方法拷貝到自己的xml文件中:

	<resultMap id="workerNodeRes"
               type="com.example.mybatisplus.entity.WorkerNode">
        <id column="ID" jdbcType="BIGINT" property="id" />
        <result column="HOST_NAME" jdbcType="VARCHAR" property="hostName" />
        <result column="PORT" jdbcType="VARCHAR" property="port" />
        <result column="TYPE" jdbcType="INTEGER" property="type" />
        <result column="LAUNCH_DATE" jdbcType="DATE" property="launchDate" />
        <result column="MODIFIED" jdbcType="TIMESTAMP" property="modified" />
        <result column="CREATED" jdbcType="TIMESTAMP" property="created" />
    </resultMap>

    <insert id="addWorkerNode" useGeneratedKeys="true" keyProperty="id"
            parameterType="com.example.mybatisplus.entity.WorkerNode">
		INSERT INTO WORKER_NODE
		(HOST_NAME,
		PORT,
		TYPE,
		LAUNCH_DATE,
		MODIFIED,
		CREATED)
		VALUES (
		#{hostName},
		#{port},
		#{type},
		#{launchDate},
		NOW(),
		NOW())
	</insert>

    <select id="getWorkerNodeByHostPort" resultMap="workerNodeRes">
		SELECT
		ID,
		HOST_NAME,
		PORT,
		TYPE,
		LAUNCH_DATE,
		MODIFIED,
		CREATED
		FROM
		WORKER_NODE
		WHERE
		HOST_NAME = #{host} AND PORT = #{port}
	</select>

將源碼中的mapper方法拷貝到自己的mapper中:

public interface WorkerNodeMapper extends BaseMapper<WorkerNode> {
    /**
     * Get {@link WorkerNode} by node host
     *
     * @param host
     * @param port
     * @return
     */
    WorkerNode getWorkerNodeByHostPort(@Param("host") String host, @Param("port") String port);

    /**
     * Add {@link WorkerNode}
     *
     * @param workerNodeEntity
     */
    void addWorkerNode(WorkerNode workerNodeEntity);

}

5. 自定義DisposableWorkerIdAssigner

將源碼DisposableWorkerIdAssigner類加入到自己的項目中,並將其中的mapper方法修改成自己項目中的方法
在這裏插入圖片描述
6. 添加全局配置類,項目啓動則可以增加機器節點

@Configuration
public class WorkerNodeConfig {

    @Bean("disposableWorkerIdAssigner")
    public DisposableWorkerIdAssigner disposableWorkerIdAssigner(){
        DisposableWorkerIdAssigner disposableWorkerIdAssigner = new DisposableWorkerIdAssigner();
        return  disposableWorkerIdAssigner;
    }

    @Bean("cachedUidGenerator")
    public UidGenerator uidGenerator(DisposableWorkerIdAssigner disposableWorkerIdAssigner){
        CachedUidGenerator cachedUidGenerator = new CachedUidGenerator();
        cachedUidGenerator.setWorkerIdAssigner(disposableWorkerIdAssigner);
        return cachedUidGenerator;
    }
}

6. 在自己service實現中,直接引用UidGenerator方法生成id

@Service
public class WorkerNodeServiceImpl extends ServiceImpl<WorkerNodeMapper, WorkerNode> implements IWorkerNodeService {

    @Resource
    private UidGenerator uidGenerator;

    @Override
    public long genUid() {
        return uidGenerator.getUID();
    }
}

7. controller接口測試結果

 /**
  * 集成百度uid-generator生成id
  * @return
  */
 @GetMapping("/baidu/uid")
 public long baiduUid(){
     long uid = workerNodeService.genUid();
     return uid;
 }

完整代碼地址:SpringBoot2.X+MybatisPlus+UidGenerator

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章