001/* 002 * Copyright 2024-2025, Warm-Flow (290631660@qq.com). 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.dromara.warm.flow.core.keygen; 017 018/** 019 * warm 生成15位有序id 020 * 021 * @author HUANGJIANSHISHENG 022 */ 023public class SnowFlakeId15 implements KenGen { 024 // 开始时间戳 (任意设置,建议为项目的开始时间) 025 private final long epoch = 1609459200000L; // 2021-01-01 00:00:00 026 027 // 各部分的位数 028 private final long sequenceBits = 6L; // 序列号占用6位 029 private final long machineIdBits = 4L; // 机器ID占用4位 030 031 // 各部分的最大值 032 private final long maxMachineId = -1L ^ (-1L << machineIdBits); 033 private final long maxSequence = -1L ^ (-1L << sequenceBits); 034 035 // 各部分的偏移量 036 private final long sequenceShift = 0; 037 private final long machineIdShift = sequenceBits; 038 private final long timestampShift = machineIdBits + sequenceBits; 039 040 private long machineId; 041 private long sequence = 0L; 042 private long lastTimestamp = -1L; 043 044 public SnowFlakeId15(long machineId) { 045 if (machineId > maxMachineId || machineId < 0) { 046 throw new IllegalArgumentException("Machine ID is out of bounds."); 047 } 048 this.machineId = machineId; 049 } 050 051 @Override 052 public synchronized long nextId() { 053 long timestamp = timeGen(); 054 055 if (timestamp < lastTimestamp) { 056 throw new RuntimeException("Clock moved backwards. Refusing to generate id."); 057 } 058 059 if (timestamp == lastTimestamp) { 060 // 当前毫秒内,则+1 061 sequence = (sequence + 1) & maxSequence; 062 if (sequence == 0) { 063 timestamp = tilNextMillis(lastTimestamp); 064 } 065 } else { 066 sequence = 0L; 067 } 068 069 lastTimestamp = timestamp; 070 071 // 生成ID并保证其为15位 072 long id = ((timestamp - epoch) << timestampShift) 073 | (machineId << machineIdShift) 074 | sequence; 075 076 return id % 10_000_000_000_000_000L; // 保证生成的ID为15位 077 } 078 079 private long tilNextMillis(long lastTimestamp) { 080 long timestamp = timeGen(); 081 while (timestamp <= lastTimestamp) { 082 timestamp = timeGen(); 083 } 084 return timestamp; 085 } 086 087 private long timeGen() { 088 return System.currentTimeMillis(); 089 } 090 091}