UNPKG

mm_os

Version:

MM_OS服务端架构,用于快速构建应用程序,支持网站建设、小程序后台、AI应用、物联网(IOT/AIOT)、游戏服务端等多种场景。

135 lines (116 loc) 3.5 kB
/** * ID生成器 * 基于雪花算法实现,生成唯一ID */ class IdGen { /** * 构造函数 * @param {object} config 配置参数 * @param {number} config.worker_id 工作机器ID (0-31) * @param {number} config.dc_id 数据中心ID (0-31) * @param {number} config.sequence 序列号 */ constructor(config = {}) { this.worker_id = config.worker_id || 0; this.dc_id = config.dc_id || 0; this.sequence = config.sequence || 0; this.worker_id_bits = 5; this.dc_id_bits = 5; this.max_worker_id = -1 ^ (-1 << this.worker_id_bits); this.max_dc_id = -1 ^ (-1 << this.dc_id_bits); this.sequence_bits = 12; this.worker_id_shift = this.sequence_bits; this.dc_id_shift = this.sequence_bits + this.worker_id_bits; this.timestamp_left_shift = this.sequence_bits + this.worker_id_bits + this.dc_id_bits; this.sequence_mask = -1 ^ (-1 << this.sequence_bits); this.last_timestamp = -1; this.twepoch = 1288834974657; if (this.worker_id > this.max_worker_id || this.worker_id < 0) { throw new TypeError(`工作机器ID必须在0-${this.max_worker_id}之间`); } if (this.dc_id > this.max_dc_id || this.dc_id < 0) { throw new TypeError(`数据中心ID必须在0-${this.max_dc_id}之间`); } } } /** * 获取当前时间戳 * @returns {number} 当前时间戳 */ IdGen.prototype._timeGen = function () { return Date.now(); }; /** * 等待下一毫秒 * @param {number} last_timestamp 上次时间戳 * @returns {number} 新的时间戳 */ IdGen.prototype._tilNextMillis = function (last_timestamp) { var timestamp = this._timeGen(); while (timestamp <= last_timestamp) { timestamp = this._timeGen(); } return timestamp; }; /** * 生成下一个ID * @returns {string} 唯一ID */ IdGen.prototype.nextId = function () { var timestamp = this._timeGen(); if (timestamp < this.last_timestamp) { throw new Error('时钟回拨,拒绝生成ID'); } if (this.last_timestamp === timestamp) { this.sequence = (this.sequence + 1) & this.sequence_mask; if (this.sequence === 0) { timestamp = this._tilNextMillis(this.last_timestamp); } } else { this.sequence = 0; } this.last_timestamp = timestamp; var id = (BigInt(timestamp - this.twepoch) << BigInt(this.timestamp_left_shift)) | (BigInt(this.dc_id) << BigInt(this.dc_id_shift)) | (BigInt(this.worker_id) << BigInt(this.worker_id_shift)) | BigInt(this.sequence); return id.toString(); }; /** * 生成带前缀的ID * @param {string} prefix 前缀 * @returns {string} 带前缀的唯一ID */ IdGen.prototype.genId = function (prefix) { if (typeof prefix !== 'string') { throw new TypeError('前缀必须是字符串'); } return prefix + '_' + this.nextId(); }; /** * 解析ID信息 * @param {string} id ID字符串 * @returns {object} ID信息对象 */ IdGen.prototype.parseId = function (id) { if (typeof id !== 'string') { throw new TypeError('ID必须是字符串'); } var num = BigInt(id.replace(/^[a-zA-Z_]+_/, '')); var timestamp = Number((num >> 22n) + BigInt(this.twepoch)); var dc_id = Number((num >> 17n) & 31n); var worker_id = Number((num >> 12n) & 31n); var sequence = Number(num & 4095n); return { timestamp: timestamp, datetime: new Date(timestamp).toISOString(), dc_id: dc_id, worker_id: worker_id, sequence: sequence }; }; var idGen = new IdGen(); module.exports = { IdGen, idGen };