您的位置:首页 > 健康 > 美食 > 网站推广文章_推荐一款男人都懂得app_企业查询宝_宁德市医院东侨院区

网站推广文章_推荐一款男人都懂得app_企业查询宝_宁德市医院东侨院区

2024/10/5 16:23:41 来源:https://blog.csdn.net/qq_42192693/article/details/142498470  浏览:    关键词:网站推广文章_推荐一款男人都懂得app_企业查询宝_宁德市医院东侨院区
网站推广文章_推荐一款男人都懂得app_企业查询宝_宁德市医院东侨院区

1,雪花算法

【雪花算法】雪花算法(Snowflake Algorithm)是Twitter开源的用于生成唯一ID的算法,它可以在分布式系统中生成唯一的64位长整数ID。这种ID生成方式既保证了趋势递增,又保证了在不同数据中心、不同机器上生成的ID的唯一性。

  • 符号位:占用1位。

  • 时间戳:通常占用41位,表示从某个固定时间点(如1970年1月1日)起的毫秒数。这使得生成的ID具有时间排序性。

  • 机器ID:占用10位,表示生成ID的机器节点,以确保不同机器生成的ID不冲突。

  • 序列号:占用12位,允许同一毫秒内生成多个ID,通常用于支持高并发。

public class SnowflakeIdGenerator {private static final long EPOCH = 1640995200000L; // 自定义的开始时间戳(2022年1月1日)private static final long MACHINE_ID_BITS = 10L; // 机器ID的位数private static final long SEQUENCE_BITS = 12L; // 序列号的位数private static final long MAX_MACHINE_ID = ~(-1L << MACHINE_ID_BITS); // 机器ID最大值private static final long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS); // 序列号最大值private long machineId; // 当前机器IDprivate long sequence = 0L; // 当前序列号private long lastTimestamp = -1L; // 上次生成ID的时间戳public SnowflakeIdGenerator(long machineId) {if (machineId > MAX_MACHINE_ID || machineId < 0) {throw new IllegalArgumentException("Machine ID can't be greater than " + MAX_MACHINE_ID + " or less than 0");}this.machineId = machineId;}public synchronized long generateId() {long timestamp = System.currentTimeMillis();// 如果当前时间小于上次生成ID的时间戳,说明系统时钟回拨,抛出异常if (timestamp < lastTimestamp) {throw new RuntimeException("Clock is moving backwards. Rejecting requests until " + lastTimestamp);}// 如果在同一毫秒内,增加序列号if (lastTimestamp == timestamp) {sequence = (sequence + 1) & SEQUENCE_MASK; // 使用位运算确保序列号循环// 如果序列号溢出,等待下一毫秒if (sequence == 0) {timestamp = waitForNextMillis(lastTimestamp);}} else {sequence = 0L; // 如果是新的毫秒,重置序列号}lastTimestamp = timestamp; // 更新上次生成ID的时间戳// 组合IDreturn ((timestamp - EPOCH) << (MACHINE_ID_BITS + SEQUENCE_BITS)) | (machineId << SEQUENCE_BITS) | sequence;}private long waitForNextMillis(long lastTimestamp) {long timestamp = System.currentTimeMillis();while (timestamp <= lastTimestamp) {timestamp = System.currentTimeMillis(); // 等待下一毫秒}return timestamp;}
}

2,雪花算法变种

【雪花算法-修正版】

/** Long: 1,000,000,000,000,000,000-9,223,372,036,854,775,807,共19位* 雪花算法变种实现: {HHmmssSSS-9位}+{系统号-2位}+{毫秒递增seq-4位}+{随机数-3位}* */
public class TiDBRandomPrimaryKeyGenerator {//机器号private String machineId;public static AtomicInteger machineIndex = new AtomicInteger(0);//序列号private long sequence = 0L;//上一个时间戳,用于保证同一毫秒内序列号不重复。private long lastTimestamp = -1L;//序列号最大值private static final long SEQUENCE_MASK = 9999;private String pattern = "HHmmssSSS";public TiDBRandomPrimaryKeyGenerator() {machineId = getInerMachineId();this.sequence = (long) (Math.random() * SEQUENCE_MASK);}public synchronized long nextId() {Date currentDate = new Date();String dateTime = DateFormatUtils.format(currentDate, pattern);String seq = getInerSequence(currentDate.getTime());String random = generateRandomString(3);StringBuilder id = new StringBuilder(32);id.append(dateTime).append(machineId).append(seq).append(random);return Long.parseLong(String.valueOf(id));}private synchronized String getInerSequence(long timestamp) {if (timestamp < lastTimestamp) {throw new RuntimeException("Clock moved backwards. Refusing to generate id for " + (lastTimestamp - timestamp) + " milliseconds");}// 如果是同一毫秒内的时间戳if (lastTimestamp == timestamp) {sequence = (sequence + 1) % SEQUENCE_MASK;} else {sequence = 0;}lastTimestamp = timestamp;return String.format("%04d", sequence);}private String getInerMachineId( ) {String machineId = String.format("%02d", machineIndex.intValue());this.machineIndex.incrementAndGet();return machineId;}public static String generateRandomString(int length) {Random random = new Random();StringBuilder sb = new StringBuilder();for (int i = 0; i < length; i++) {// 生成0到9之间的随机数,并转换为字符char randomChar = (char) (random.nextInt(10) + '0');sb.append(randomChar);}return sb.toString();}
}

3,基于DB自增

算法:{机器号}+{数据库id自增}+{伪随机}

@Service
public class UniqueIDGenerator {@AutowiredPrefixRepository prefixRepository;// 队列最小容量阈值private static final int QUEUE_MIN_SIZE = 10000;private static final int QUEUE_CAPACITY = 12000;private static final int RANDOM_UPPER_LIMIT = 9999;// 递增前缀private long prefix;// 随机数队列private BlockingQueue<String> idQueue = new ArrayBlockingQueue<>(QUEUE_CAPACITY);// 线程安全锁private final Lock lock = new ReentrantLock();public String getUniqueId() throws InterruptedException {String uniqueId;uniqueId = idQueue.poll();if (uniqueId == null) {lock.lock();try {refillQueue();} finally {lock.unlock();}uniqueId = idQueue.take();}return uniqueId;}private long fetchDBPrefix() {Prefix prefix_from_db = prefixRepository.findById(1).get();this.prefix = prefix_from_db.getNext_value();prefix_from_db.setNext_value(prefix_from_db.getNext_value() + 1);prefixRepository.save(prefix_from_db);return prefix;}private void refillQueue() {//前1w个已经用完,重新获取前缀prefix = fetchDBPrefix();Random random = new Random();while (idQueue.size() < QUEUE_MIN_SIZE) {int randomPart = random.nextInt(RANDOM_UPPER_LIMIT + 1);String id = String.format("%014d", prefix) + String.format("%04d", randomPart);idQueue.offer(id);}}
}
public interface PrefixRepository  extends JpaRepository<Prefix, Integer> {}
@Entity
@Table(name = "unique_id_table")
public class Prefix{@Id@Column(name = "id")@GeneratedValue(strategy = GenerationType.IDENTITY)private int id;@Column(name = "next_value")private long next_value;public int getId() {return id;}public void setId(int id) {this.id = id;}public long getNext_value() {return next_value;}public void setNext_value(long nextValue) {this.next_value = nextValue;}
}
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:test
spring.datasource.username=sa
spring.datasource.password=spring.sql.init.mode=always
spring.sql.init.schema-locations=classpath:/sql/schema.sql
spring.sql.init.data-locations=classpath:/sql/data.sqlspring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
DROP TABLE IF EXISTS `unique_id_table`;
CREATE TABLE `unique_id_table`
(`id` int,`next_value`   bigint
);INSERT INTO `unique_id_table` (`id`, `next_value`) VALUES (1,1);

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com