雪花算法node-ts版本

    83

简介

Snowflake,雪花算法是由Twitter开源的分布式ID生成算法,以划分命名空间的方式将 64-bit位分割成多个部分,每个部分代表不同的含义。

二进制

位运算异或( ^ ) ,左移( << ) ,与( & ),或( | )

具体实现

class SnowflakeIdGenerate {
  private START_STMP = 0;
  private SEQUENCE_BIT = 12;
  private MACHINE_BIT = 5;
  private DATACENTER_BIT = 5;
  private MAX_DATACENTER_NUM = -1 ^ (-1 << this.DATACENTER_BIT);
  private MAX_MACHINE_NUM = -1 ^ (-1 << this.MACHINE_BIT);
  private MAX_SEQUENCE = -1 ^ (-1 << this.SEQUENCE_BIT);

  private MACHINE_LEFT = this.SEQUENCE_BIT;
  private DATACENTER_LEFT = this.SEQUENCE_BIT + this.MACHINE_BIT;
  private TIMESTMP_LEFT = this.DATACENTER_LEFT + this.DATACENTER_BIT;

  private datacenterId; //数据中心
  private machineId; //机器标识
  private sequence = 0; //序列号
  private lastStmp = -1; //上一次时间戳

  constructor(machineId = 1, datacenterId = 1) {
    if (this.machineId > this.MAX_MACHINE_NUM || this.machineId < 0) {
      throw new Error(
        'config.worker_id must max than 0 and small than maxWrokerId-[' +
          this.MAX_MACHINE_NUM +
          ']'
      );
    }
    if (this.datacenterId > this.MAX_DATACENTER_NUM || this.datacenterId < 0) {
      throw new Error(
        'config.data_center_id must max than 0 and small than maxDataCenterId-[' +
          this.MAX_DATACENTER_NUM +
          ']'
      );
    }
    this.machineId = machineId;
    this.datacenterId = datacenterId;
  }

  private getNewstmp = (): number => {
    return Date.now();
  };

  private getNextMill = (): number => {
    let timestamp = this.getNewstmp();
    while (timestamp <= this.lastStmp) {
      timestamp = this.getNewstmp();
    }
    return timestamp;
  };

  nextId = (): string => {
    let timestamp: number = this.getNewstmp();
    if (timestamp < this.lastStmp) {
      throw new Error(
        'Clock moved backwards. Refusing to generate id for ' +
          (this.lastStmp - timestamp)
      );
    }
    if (this.lastStmp === timestamp) {
      this.sequence = (this.sequence + 1) & this.MAX_SEQUENCE;
      if (this.sequence === 0) {
        timestamp = this.getNextMill();
      }
    } else {
      this.sequence = 0;
    }
    this.lastStmp = timestamp;
    const timestampPos =
      BigInt(timestamp - this.START_STMP) *
      BigInt(2) ** BigInt(this.TIMESTMP_LEFT);
    const dataCenterPos = BigInt(this.datacenterId << this.DATACENTER_LEFT);
    const workerPos = BigInt(this.machineId << this.MACHINE_LEFT);
    return (
      timestampPos |
      dataCenterPos |
      workerPos |
      BigInt(this.sequence)
    ).toString();
  };
}

chatgpt的实现

class Snowflake {  
  private readonly epoch: number = 1620950400000; // 开始时间戳,2021-05-14 00:00:00 UTC+8  
  private readonly workerIdBits: number = 5; // 机器 ID 所占的位数  
  private readonly datacenterIdBits: number = 5; // 数据中心 ID 所占的位数  
  private readonly maxWorkerId: number = ~(-1 << this.workerIdBits); // 最大机器 ID,2^5-1  
  private readonly maxDatacenterId: number = ~(-1 << this.datacenterIdBits); // 最大数据中心 ID,2^5-1  
  private readonly sequenceBits: number = 12; // 序列号所占的位数  
  private readonly workerIdShift: number = this.sequenceBits; // 机器 ID 左移位数,即序列号占用的位数  
  private readonly datacenterIdShift: number = this.sequenceBits + this.workerIdBits; // 数据中心 ID 左移位数  
  private readonly timestampLeftShift: number =  
    this.sequenceBits + this.workerIdBits + this.datacenterIdBits; // 时间戳左移位数  
  private sequenceMask: number = ~(-1 << this.sequenceBits); // 序列号的掩码,2^12-1  
  private sequence: number = 0; // 当前序列号  
  private lastTimestamp: number = -1; // 上次生成雪花 ID 的时间戳  
  private readonly workerId: number; // 当前机器 ID  private readonly datacenterId: number; // 当前数据中心 ID  
  /**   * 构造函数  
   * @param workerId 机器 ID  
   * @param datacenterId 数据中心 ID  
   */  constructor(workerId: number, datacenterId: number) {  
    if (workerId > this.maxWorkerId || workerId < 0) {  
      throw new Error(`workerId must be between 0 and ${this.maxWorkerId}`);  
    }  
    if (datacenterId > this.maxDatacenterId || datacenterId < 0) {  
      throw new Error(`datacenterId must be between 0 and ${this.maxDatacenterId}`);  
    }  
    this.workerId = workerId;  
    this.datacenterId = datacenterId;  
  }  
  
  /**  
   * 生成下一个雪花 ID  
   * @returns 64 位的雪花 ID  
   */  nextId(): string {  
    let timestamp = this.timeGen();  
    if (timestamp < this.lastTimestamp) {  
      throw new Error(  
        `Clock moved backwards. Refusing to generate id for ${  
          this.lastTimestamp - timestamp  
        } milliseconds`,  
      );  
    }  
    if (this.lastTimestamp === timestamp) {  
      this.sequence = (this.sequence + 1) & this.sequenceMask;  
      if (this.sequence === 0) {  
        timestamp = this.tilNextMillis(this.lastTimestamp);  
      }  
    } else {  
      this.sequence = 0;  
    }  
    this.lastTimestamp = timestamp;  
    const id =  
      ((timestamp - this.epoch) << this.timestampLeftShift) |  
      (this.datacenterId << this.datacenterIdShift) |  
      (this.workerId << this.workerIdShift) |  
      this.sequence;  
    return id.toString();  
  }  
  
  /**  
   * 获取当前时间  
   *  
   */  
  private timeGen(): number {  
    return Date.now();  
  }  
  
  /**  
  
   等待下一毫秒,直到返回新的时间戳  
   @param lastTimestamp 上次生成雪花 ID 的时间戳  
   @returns 新的时间戳  
   */  
  private tilNextMillis(lastTimestamp: number): number {  
    let timestamp = this.timeGen();  
    while (timestamp <= lastTimestamp) {  
      timestamp = this.timeGen();  
    }  
    return timestamp;  
  }  
}
评论区
共有评论 0
暂无评论