问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

雪花算法Snowflake,看完秒懂!

创作时间:
作者:
@小白创作中心

雪花算法Snowflake,看完秒懂!

引用
CSDN
1.
https://m.blog.csdn.net/qq_56158663/article/details/145829364

准备好,咱要用一种不正经但又很认真的方式,来扒一扒雪花算法的底裤! 😜

雪花算法:一个“高富帅”ID生成器

想象一下,你是一个皇帝,要给你的子民们发身份证。如果每个人都叫“张三”、“李四”,那肯定乱套了!所以,你需要一个能保证每个人身份证号都独一无二的算法。雪花算法,就是这个“高富帅”身份证生成器!😎

雪花算法的“身世背景”

雪花算法,英文名叫 Snowflake,听起来就很高冷。它最初是 Twitter 为了解决分布式系统中的ID生成问题而设计的。在分布式世界里,有很多台电脑一起干活,如果每台电脑都自己生成ID,很容易撞衫(ID重复)。雪花算法就是来避免这种尴尬的!

雪花ID的“构成”

雪花ID是一个64位的二进制数字,就像一个人的身份证号一样,每一段都有特殊的含义:

+---+------------------------+----------------+-----------+-----------+
| 1 |           41           |       5        |     5     |    12     |
+---+------------------------+----------------+-----------+-----------+
|   |       timestamp        |  datacenterId  | workerId  | sequence  |
+---+------------------------+----------------+-----------+-----------+
  • 符号位 (1 bit):永远是0,因为我们只想要正数ID。就像一个人的性别,要么男,要么女,这里永远是“正”!💪
  • 时间戳 (41 bits):记录了从某个特定时间(Epoch)开始,到现在的毫秒数。这就像一个人的出生日期,越晚出生,这个数字越大。41位能用69年,够你用了!🎂
  • 数据中心ID (5 bits):标识这个ID是在哪个数据中心生成的。就像一个人的户籍所在地,北京、上海、广州,总得有个地方落户吧?最多支持32个数据中心。🏢
  • 机器ID (5 bits):标识这个ID是在数据中心里的哪台机器上生成的。就像一个人的具体住址,几栋几单元几零几。每个数据中心最多支持32台机器。💻
  • 序列号 (12 bits):如果同一毫秒内,同一台机器要生成多个ID,就靠这个序列号来区分了。就像一个人的名字,如果同一天出生的人太多,就得起个不一样的名字。每毫秒最多可以生成4096个ID。🔢

雪花算法在SpringBoot中的使用,这里使用的是hutool工具包封装的雪花算法

1. 添加 Hutool 依赖

pom.xml 文件中添加 Hutool 依赖:

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.24</version> 
</dependency>

2. 创建 SnowflakeIdWorker 类 (使用 Hutool)

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;

@Component
@Slf4j
public class SnowflakeIdWorker {
    @Value("${snowflake.datacenter-id:0}") // 默认值为 0
    private long datacenterId;
    @Value("${snowflake.worker-id:0}") // 默认值为 0
    private long workerId;
    private Snowflake snowflake; // Hutool 提供的雪花算法工具类

    @PostConstruct
    public void init() {
        // 创建 Snowflake 对象,传入数据中心ID和机器ID
        snowflake = IdUtil.createSnowflake(datacenterId, workerId);
        log.info("SnowflakeIdWorker started with datacenterId: {}, workerId: {}", datacenterId, workerId);
    }

    public long nextId() {
        // 生成下一个 ID
        return snowflake.nextId();
    }

    public String nextIdStr() {
        // 生成下一个 ID (String 类型)
        return snowflake.nextIdStr();
    }
}

代码解释:

  • snowflake = IdUtil.createSnowflake(datacenterId, workerId);:使用 IdUtil.createSnowflake() 方法创建一个 Snowflake 对象,传入数据中心 ID 和机器 ID。
  • snowflake.nextId():调用 Snowflake 对象的 nextId() 方法生成下一个 long 类型的 ID。
  • snowflake.nextIdStr():调用 Snowflake 对象的 nextIdStr() 方法生成下一个 String 类型的 ID。

3. 在 application.yml 中配置 datacenterIdworkerId (可选)

# application.yml
snowflake:
  datacenter-id: 1
  worker-id: 1

4. 使用 SnowflakeIdWorker

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class IdController {
    @Autowired
    private SnowflakeIdWorker idWorker;

    @GetMapping("/nextId")
    public long nextId() {
        long id = idWorker.nextId();
        System.out.println("生成的 long 型 ID: " + id); // 输出结果
        return id;
    }

    @GetMapping("/nextIdStr")
    public String nextIdStr() {
        String id = idWorker.nextIdStr();
        System.out.println("生成的 String 型 ID: " + id); // 输出结果
        return id;
    }
}

代码解释:

  • System.out.println("生成的 long 型 ID: " + id);:在控制台输出生成的 long 型 ID。
  • System.out.println("生成的 String 型 ID: " + id);:在控制台输出生成的 String 型 ID。

5. 运行 Spring Boot 应用并测试

启动 Spring Boot 应用,访问以下 URL:

  • http://localhost:8080/nextId
  • http://localhost:8080/nextIdStr

输出结果:

生成的 long 型 ID: 1699876543210987654
生成的 String 型 ID: 1699876543210987655

雪花算法的“工作原理”

  1. 获取当前时间戳:就像看了一眼现在的日期。⌚
  2. 分配数据中心ID和机器ID:就像确定了你的户籍所在地和具体住址。🏠
  3. 生成序列号:如果同一毫秒内要生成多个ID,就递增序列号。就像同一天出生的宝宝,按顺序起名字。👶
  4. 把这些信息拼起来:用位运算把时间戳、数据中心ID、机器ID和序列号拼成一个64位的数字。就像把你的出生日期、户籍所在地、住址和名字都写在身份证上。

雪花算法的“优点”

  • 全局唯一:只要数据中心ID和机器ID不重复,生成的ID就绝对不会重复。就像每个人的身份证号都是独一无二的。💯
  • 高性能:生成ID的速度非常快,因为主要靠位运算。就像闪电侠一样,嗖嗖嗖就生成一个ID。⚡
  • 趋势递增:生成的ID总体上是递增的,方便数据库索引。就像排队一样,先来后到,井然有序。🚶
  • 简单易用:算法逻辑简单,容易实现。就像傻瓜相机一样,一按快门就能拍照。📸

雪花算法的“缺点”

  • 依赖时钟:如果服务器的时钟发生回拨,可能会生成重复的ID。就像穿越回过去,历史可能会被改变。🕰️
  • 需要配置:需要为每个数据中心和机器分配唯一的ID,增加了部署的复杂性。就像开公司一样,需要注册地址和营业执照。🏢

时钟回拨:雪花算法的“阿喀琉斯之踵”

时钟回拨是指服务器的时钟突然变慢,导致时间戳变小。这可能会导致雪花算法生成重复的ID。

如何应对时钟回拨?

  • 拒绝服务:如果发现时钟回拨,直接拒绝生成ID。就像发现穿越,直接阻止。🚫
  • 等待:如果回拨时间不长,就等待一段时间,让时钟追上来。就像堵车一样,等等就好了。🚗
  • 使用备用方案:如果回拨时间太长,就切换到备用的ID生成方案,比如UUID。就像备胎一样,关键时刻能顶上。🚗💨
  • 调整时间戳:如果回拨时间很短,可以把时间戳调整到上次生成ID的时间戳。就像把表拨快一点,假装没事发生。⌚➡️

总结

雪花算法是一个简单、高效、可靠的分布式ID生成算法。虽然它有一些缺点,但只要我们注意时钟回拨问题,并采取相应的措施,就能让它在分布式系统中发挥巨大的作用! 🚀

希望这个幽默版的讲解能让你更好地理解雪花算法! 记住,技术再高深,也要用轻松的心态去学习! 😉

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号