<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          百度開源的分布式 ID 生成器,太強(qiáng)大了!

          共 13256字,需瀏覽 27分鐘

           ·

          2021-05-29 09:22

          點(diǎn)擊關(guān)注公眾號,Java干貨及時(shí)送達(dá)

          來源:https://lilinchao.com/archives/1226.html

          一、UidGenerator是什么

          UidGenerator是百度開源的一款分布式高性能的唯一ID生成器,是基于snowflake模型的一種ID生成器。

          二、UidGenerator的優(yōu)勢

          1. 解決了時(shí)鐘回調(diào)的問題
          2. 使用ringbuffer,無鎖進(jìn)行id的生產(chǎn)與消費(fèi),速度非???/section>
          3. 適用于多線程,不會有單線程瓶頸

          三、整合

          本次通過SpringBoot2.x和MyBatis對百度UidGenerator進(jìn)行整合。

          3.1 UidGenerator引入

          一般使用兩種方式引入U(xiǎn)idGenerator:

          1)從官網(wǎng)下載源碼作為自己項(xiàng)目的一個(gè)Module引入到項(xiàng)目中

          官網(wǎng)地址:https://github.com/baidu/uid-generator/blob/master/README.zh_cn.md

          2)互聯(lián)網(wǎng)jar包引入(本文采取的是該種方式)

          因?yàn)閁idGenerator自帶引入了mybatis,和自己項(xiàng)目有沖突的可以進(jìn)行排除

          <dependency>
              <groupId>com.xfvape.uid</groupId>
              <artifactId>uid-generator</artifactId>
              <version>0.0.4-RELEASE</version>
          </dependency>

          排除沖突依賴

          uid-generator中依賴了logback和mybatis。一般在項(xiàng)目搭建過程中,springboot中已經(jīng)有了logback依賴,mybatis會作為單獨(dú)的依賴引入。如果版本和uid-generator中的依賴不一致的話,就會導(dǎo)致沖突。

          Spring Boot 基礎(chǔ)就不介紹了,新手請看這個(gè)學(xué)習(xí)教程和示例倉庫:https://github.com/javastacks/spring-boot-best-practice

          排除沖突的依賴如下:

          <dependency>
              <groupId>com.xfvape.uid</groupId>
              <artifactId>uid-generator</artifactId>
              <version>0.0.4-RELEASE</version>
              <exclusions>
                   <exclusion>
                       <groupId>org.slf4j</groupId>
                       <artifactId>log4j-over-slf4j</artifactId>
                   </exclusion>
                   <exclusion>
                       <groupId>ch.qos.logback</groupId>
                       <artifactId>logback-classic</artifactId>
                   </exclusion>
                   <exclusion>
                       <groupId>org.slf4j</groupId>
                       <artifactId>slf4j-api</artifactId>
                   </exclusion>
                    <exclusion>
                       <groupId>org.mybatis</groupId>
                       <artifactId>mybatis-spring</artifactId>
                   </exclusion>
                   <exclusion>
                       <groupId>org.mybatis</groupId>
                       <artifactId>mybatis</artifactId>
                   </exclusion>
              </exclusions>
          </dependency>

          3.2 創(chuàng)建表

          在 MySQL數(shù)據(jù)庫中建一個(gè)名為 WORKER_NODE的數(shù)據(jù)表,其 sql如下:

          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;

          建表時(shí)可能會報(bào)錯(cuò),原因是該建表語句定義了兩個(gè)TIMESTAMP字段,因?yàn)閙ysql 低版本控制比較嚴(yán)格。MySQL 開發(fā)的 36 條軍規(guī)建議看看。

          解決辦法:

          方式一:

          直接把TIMESTAMP改成DATETIME 即可

          方式二:

          建表前先設(shè)置sql_mode:

          set sql_mode="NO_ENGINE_SUBSTITUTION";

          3.3 將uid-generator核心對象裝配為spring的bean

          uid-generator提供了兩種生成器: DefaultUidGenerator、CachedUidGenerator。如對UID生成性能有要求, 請使用CachedUidGenerator。

          @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;
              }
          }

          直接創(chuàng)建WorkerNodeConfig類,復(fù)制以上代碼。

          3.4 重寫WorkerIdAssigner接口

          public class DisposableWorkerIdAssigner implements WorkerIdAssigner {

              @Resource
              private WorkerNodeMapper workerNodeMapper;
              @Override
              @Transactional
              public long assignWorkerId() {
                  WorkerNode workerNode = buildWorkerNode();

                  workerNodeMapper.addWorkerNode(workerNode);

                  return workerNode.getId();
              }

              private WorkerNode buildWorkerNode() {
                  WorkerNode workNode = new WorkerNode();
                  if (DockerUtils.isDocker()) {
                      workNode.setType(WorkerNodeType.CONTAINER.value());
                      workNode.setHostName(DockerUtils.getDockerHost());
                      workNode.setPort(DockerUtils.getDockerPort());
                      workNode.setLaunchDate(new Date());
                  } else {
                      workNode.setType(WorkerNodeType.ACTUAL.value());
                      workNode.setHostName(NetUtils.getLocalAddress());
                      workNode.setPort(System.currentTimeMillis() + "-" + RandomUtils.nextInt(100000));
                      workNode.setLaunchDate(new Date());
                  }

                  return workNode;
              }
          }

          創(chuàng)建一個(gè)DisposableWorkerIdAssigner類直接復(fù)制以上代碼。

          3.5 引入WorkerNodeMapper.xml

          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
          <mapper namespace="com.uidgenerator.mapper.WorkerNodeMapper">
            <resultMap id="BaseResultMap"
                       type="com.uidgenerator.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.uidgenerator.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="BaseResultMap ">
                  SELECT
                      ID,
                      HOST_NAME,
                      PORT,
                      TYPE,
                      LAUNCH_DATE,
                      MODIFIED,
                      CREATED
                  FROM
                      WORKER_NODE
                  WHERE
                      HOST_NAME = #{host} AND PORT = #{port}
              </select>
          </mapper>

          可以通過mybatis生成工具直接生成文件和實(shí)體類,然后將插入和查詢方法復(fù)制。關(guān)注公眾號Java技術(shù)棧,在后臺回復(fù):面試,可以獲取我整理的 Java、MyBatis 系列面試題和答案,非常齊全。

          注意修改resultMap中的type和insert中的keyProperty為自身項(xiàng)目的實(shí)體類地址。

          在application.yml文件中增加如下配置

          mybatis:
            mapper-locations: classpath:mybatis/*.xml

          3.6實(shí)體類

          使用插件生成的實(shí)體類

          3.7創(chuàng)建Mapper

          @Mapper
          public interface WorkerNodeMapper {

              int addWorkerNode(WorkerNode workerNodeEntity);

           WorkerNode getWorkerNodeByHostPort(@Param("host") String host, @Param("port") String port);

          }

          3.8 Service

          IWorkerNodeService接口

          public interface IWorkerNodeService {
              public long genUid();
          }

          WorkerNodeServiceImpl實(shí)現(xiàn)類

          @Service
          public class WorkerNodeServiceImpl implements IWorkerNodeService {
              @Resource
              private UidGenerator uidGenerator;

              @Override
              public long genUid() {
                  Long uu_id = UidGeneratorComponent.uu_id;
                  return uidGenerator.getUID();
              }
          }

          3.8 Controller

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

          3.9 訪問接口測試

          http://127.0.0.1:8099/test/baidu/uid

          項(xiàng)目目錄結(jié)構(gòu)

          最后,關(guān)注公眾號Java技術(shù)棧,在后臺回復(fù):面試,可以獲取我整理的 Java 系列面試題和答案,非常齊全。






          關(guān)注Java技術(shù)??锤喔韶?/strong>



          獲取 Spring Boot 實(shí)戰(zhàn)筆記!
          瀏覽 179
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  人妻洗澡被强公日日澡 | 青娱乐亚洲日韩 | 99热12 | 国产成人无码AV一区二区网站 | 啪啪啪免费网址 |