当前位置: 首页> 教育> 就业 > 泉州市第一建设有限公司网站_网站如何进行推广_zac seo博客_电商网站建设步骤

泉州市第一建设有限公司网站_网站如何进行推广_zac seo博客_电商网站建设步骤

时间:2025/7/12 6:07:54来源:https://blog.csdn.net/cuishujian_2003/article/details/146141323 浏览次数:1次
泉州市第一建设有限公司网站_网站如何进行推广_zac seo博客_电商网站建设步骤

雪花算法(Snowflake)

雪花算法是一种由Twitter开源的分布式ID生成算法,广泛应用于分布式系统中,用于生成全局唯一的ID。这些ID不仅具有唯一性,还按照时间顺序递增,便于排序和查询。以下是雪花算法的详细解析:

一、算法原理

雪花算法生成的ID是一个64位的二进制数,通常表示为long型整数。这64位被划分为以下几个部分:

  1. 符号位(1位)

    • 固定为0,表示生成的ID是正数。
  2. 时间戳(41位)

    • 记录ID生成的时间,精确到毫秒。
    • 可以表示大约69年(从自定义的纪元时间开始计算,例如2015年1月1日)。
    • 提供排序功能,根据时间戳可以对数据进行排序。
  3. 数据中心ID(5位)

    • 标识不同的数据中心。
    • 可以支持最多32个数据中心(25=32)。
  4. 机器ID(5位)

    • 标识同一数据中心内的不同机器。
    • 可以支持每个数据中心最多32台机器(25=32)。
    • 数据中心ID和机器ID组合起来,可以支持最多1024个节点(32×32=1024)。
  5. 序列号(12位)

    • 在同一毫秒内生成不同的ID。
    • 支持每个节点每毫秒生成4096个唯一的ID(212=4096)。

二、ID生成过程

  1. 获取当前时间戳

    • 记录当前时间的毫秒值,与自定义的纪元时间相减,得到时间戳差值。
  2. 获取数据中心ID和机器ID

    • 每个节点在部署时配置唯一的数据中心ID和机器ID。
  3. 生成序列号

    • 如果是同一毫秒内首次生成ID,序列号从0开始。
    • 同一毫秒内每生成一个ID,序列号递增1。
    • 如果序列号达到最大值(4095),则等待下一毫秒,序列号重置为0。
  4. 组合生成ID

    • 将时间戳差值、数据中心ID、机器ID和序列号拼接起来,形成一个64位的ID。

三、算法特点

  1. 全局唯一性

    • 通过时间戳、数据中心ID、机器ID和序列号的组合,确保生成的ID在全局范围内唯一。
  2. 有序递增

    • 由于ID中包含时间戳部分,因此生成的ID在时间上是有序递增的,便于排序和查询。
  3. 高并发性能

    • 每秒可以生成数百万个唯一的ID,满足高并发场景下的需求。
    • 生成ID的过程主要依赖于位运算和位移操作,效率高。
  4. 不依赖第三方系统

    • 不依赖数据库等第三方系统,以服务的方式部署,稳定性高。

四、应用场景

雪花算法广泛应用于分布式系统中的唯一ID生成,包括但不限于以下场景:

  • 订单号生成:在电商平台中,为每个订单生成唯一的订单号。
  • 分布式数据库主键:在分布式数据库中,为数据表的主键生成唯一的ID。
  • 分布式锁:在分布式系统中,为分布式锁生成唯一的标识。

五、注意事项

  1. 时钟回拨问题

    • 雪花算法依赖系统时钟生成时间戳。如果系统时钟回拨,可能会导致生成的ID重复。
    • 解决方案包括:
      • 拒绝生成ID,直到时间戳大于等于上一次生成ID的时间戳。
      • 使用备用策略,如记录事件并报警。
  2. 机器ID的唯一性

    • 在分布式环境中,需要确保每台机器的数据中心ID和机器ID唯一。
    • 如果机器ID重复,会导致生成的ID冲突。
  3. 高并发场景下的处理

    • 在高并发场景下,同一毫秒内可能生成大量ID。
    • 需要合理设置序列号位数,避免序列号溢出。

六、代码实现示例(Java)

以下是一个简化的雪花算法Java实现示例:

public class SnowflakeIdWorker {// 开始时间截 (自定义纪元时间,例如2015-01-01)private final long twepoch = 1420041600000L;// 机器id所占的位数private final long workerIdBits = 5L;// 数据标识id所占的位数private final long datacenterIdBits = 5L;// 支持的最大机器idprivate final long maxWorkerId = -1L ^ (-1L << workerIdBits);// 支持的最大数据标识idprivate final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);// 序列在id中占的位数private final long sequenceBits = 12L;// 机器ID向左移12位private final long workerIdShift = sequenceBits;// 数据标识id向左移17位(12+5)private final long datacenterIdShift = sequenceBits + workerIdBits;// 时间截向左移22位(5+5+12)private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;// 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095)private final long sequenceMask = -1L ^ (-1L << sequenceBits);// 工作机器ID(0~31)private long workerId;// 数据中心ID(0~31)private long datacenterId;// 毫秒内序列(0~4095)private long sequence = 0L;// 上次生成ID的时间截private long lastTimestamp = -1L;// 构造函数public SnowflakeIdWorker(long workerId, long datacenterId) {if (workerId > maxWorkerId || workerId < 0) {throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));}if (datacenterId > maxDatacenterId || datacenterId < 0) {throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));}this.workerId = workerId;this.datacenterId = datacenterId;}// 获得下一个IDpublic synchronized long nextId() {long timestamp = timeGen();// 如果当前时间小于上一次ID生成的时间戳, 说明系统时钟回退过,这个时候应当抛出异常if (timestamp < lastTimestamp) {throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));}// 如果是同一时间生成的, 则进行毫秒内序列if (lastTimestamp == timestamp) {sequence = (sequence + 1) & sequenceMask;// 毫秒内序列溢出if (sequence == 0) {// 阻塞到下一个毫秒, 获得新的时间戳timestamp = tilNextMillis(lastTimestamp);}} else {// 时间戳改变,毫秒内序列重置sequence = 0L;}// 上次生成ID的时间截lastTimestamp = timestamp;// 移位并通过或运算拼到一起组成64位的IDreturn ((timestamp - twepoch) << timestampLeftShift)| (datacenterId << datacenterIdShift)| (workerId << workerIdShift)| sequence;}// 返回以毫秒为单位的当前时间protected long timeGen() {return System.currentTimeMillis();}// 阻塞到下一个毫秒,直到获得新的时间戳protected long tilNextMillis(long lastTimestamp) {long timestamp = timeGen();while (timestamp <= lastTimestamp) {timestamp = timeGen();}return timestamp;}
}


七、总结

雪花算法是一种高效、可靠的分布式ID生成算法,通过组合时间戳、数据中心ID、机器ID和序列号,确保生成的ID在全局范围内唯一且有序递增。它广泛应用于分布式系统中的唯一ID生成,为系统的数据管理和查询提供了便利。然而,在使用雪花算法时,也需要注意时钟回拨、机器ID唯一性等问题,以确保算法的正确性和稳定性。

关键字:泉州市第一建设有限公司网站_网站如何进行推广_zac seo博客_电商网站建设步骤

版权声明:

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

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

责任编辑: