雪花算法Snowflake

雪花算法常用于分布式的项目中,是为了解决大数据产生的多表分表中,保证id的唯一性。

1.分布式的特点

  • 全局唯一性:不能出现有重复ID的标识;
  • 地增性:确保生成的ID对用于用户或业务是递增的;
  • 高可用性:确保任何时候都能生成正确的ID;
  • 高并发性:在高并发环境下表现良好;

2.分布式ID的常见解决方案

  • UUID:Java自带的生成一串唯一随机36位字符串(32个字符串+4个“-”)的算法。它可以保证唯一性,且据说够用N亿年,但是其业务可读性差,无法有序递增。
  • SnowFlake:是Twitter开源的由64位整数组成分布式ID,性能较高,并且在单机上递增。
  • UidGenerator:UidGenerator是百度开源的分布式ID生成器,其基于雪花算法实现
  • Leaf:Leaf是美团开源的分布式ID生成器,能保证全局唯一,趋势递增,但需要依赖关系数据库、Zookeeper等中间件。

3.雪花算法介绍

雪花算法的原理就是生成一个的 64 位比特位的 long 类型的唯一 id

  1. 第一位 最高 1 位固定值 0,因为生成的 id 是正整数,如果是 1 就是负数;
  2. 时间戳 占用41bit,精确到毫秒,总共可以容纳约69年的时间。
  3. 工作机器id 占用10bit,其中高位5bit是数据中心ID,低位5bit是工作节点ID,做多可以容纳1024个节点。
  4. .序列号 占用12bit,每个节点每毫秒0开始不断累加,最多可以累加到4095,一共可以产生4096个ID。

4.雪花算法源码

/*** Twitter的SnowFlake算法,使用SnowFlake算法生成一个整数,然后转化为62进制变成一个短地址URL* Snowflake生成的是Long类型的ID,一个Long类型占8个字节,每个字节占8比特,也就是说一个Long类型占64个比特。* Snowflake ID组成结构:正数位(占1比特)+ 时间戳(占41比特)+ 机器ID(占5比特)+ 数据中心(占5比特)+ 自增值(占12比特),总共64比特组成的一个Long类型。* ● 第一个bit位(1bit):Java中long的最高位是符号位代表正负,正数是0,负数是1,一般生成ID都为正数,所以默认为0。* ● 时间戳部分(41bit):毫秒级的时间,不建议存当前时间戳,而是用(当前时间戳 - 固定开始时间戳)的差值,可以使产生的ID从更小的值开始;41位的时间戳可以使用69年,(1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69年* ● 工作机器id(10bit):也被叫做workId,这个可以灵活配置,机房或者机器号组合都可以。* ● 序列号部分(12bit),自增值支持同一毫秒内同一个节点可以生成4096个ID* 根据这个算法的逻辑,只需要将这个算法用Java语言实现出来,封装为一个工具方法,那么各个业务应用可以直接使用该工具方法来获取分布式ID,只需保证每个业务应用有自己的工作机器id即可,而不需要单独去搭建一个获取分布式ID的应用。*/
public class SnowFlakeUtil {/*** 起始的时间戳*/private final static long START_TIMESTAMP = 1480166465631L;/*** 每一部分占用的位数*/private final static long SEQUENCE_BIT = 12;   //序列号占用的位数private final static long MACHINE_BIT = 5;     //机器标识占用的位数private final static long DATA_CENTER_BIT = 5; //数据中心占用的位数/*** 每一部分的最大值*/private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);  // 4095private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT); //private final static long MAX_DATA_CENTER_NUM = -1L ^ (-1L << DATA_CENTER_BIT);/*** 每一部分向左的位移*/private final static long MACHINE_LEFT = SEQUENCE_BIT;private final static long DATA_CENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;private final static long TIMESTAMP_LEFT = DATA_CENTER_LEFT + DATA_CENTER_BIT;private long dataCenterId;  //数据中心private long machineId;     //机器标识private long sequence = 0L; //序列号private long lastTimeStamp = -1L;  //上一次时间戳/*** 获取到下一毫秒的时间戳** @return long*/private long getNextMill() {long mill = getNewTimeStamp();while (mill <= lastTimeStamp) {mill = getNewTimeStamp();}return mill;}/*** 获取到当前时间戳** @return long*/private long getNewTimeStamp() {return System.currentTimeMillis();}/*** 根据指定的数据中心ID和机器标志ID生成指定的序列号*  机器id总共占5位,低12位序号id12位.因此要左移12位*  数据中心id(机房id)占5位,低17位为机器id5位和序号id12位,因此要左移17位* @param dataCenterId 数据中心ID* @param machineId    机器标志ID*/public SnowFlakeUtil(long dataCenterId, long machineId) {if (dataCenterId > MAX_DATA_CENTER_NUM || dataCenterId < 0) {throw new IllegalArgumentException("DtaCenterId can't be greater than MAX_DATA_CENTER_NUM or less than 0!");}if (machineId > MAX_MACHINE_NUM || machineId < 0) {throw new IllegalArgumentException("MachineId can't be greater than MAX_MACHINE_NUM or less than 0!");}this.dataCenterId = dataCenterId;this.machineId = machineId;}/*** 产生下一个ID* id号只有12位.同一毫秒内最多生产4096个.* 超过时,申请下一个毫秒值* @return*/public synchronized long nextId() {
//        1.获取到当前时间戳long currTimeStamp = getNewTimeStamp();
//        2.如果当前时间戳小于上一次ID生成的时间戳,说明系统时钟回退过,这个时候应当抛出异常if (currTimeStamp < lastTimeStamp) {throw new RuntimeException("Clock moved backwards.  Refusing to generate id");}//        3.在同一毫秒内if (currTimeStamp == lastTimeStamp) {
//        4.相同毫秒内,序列号自增   MAX_SEQUENCE=4095(12位,序列号最大值)
//          sequence + 1 =4096时sequence为0(相当于4095&4096)sequence = (sequence + 1) & MAX_SEQUENCE;//同一毫秒的序列数已经达到最大if (sequence == 0L) {
//         5.获取下一个毫秒并赋值给当前毫秒currTimeStamp = getNextMill();}} else {//不同毫秒内,序列号置为0sequence = 0L;}lastTimeStamp = currTimeStamp;return (currTimeStamp - START_TIMESTAMP) << TIMESTAMP_LEFT //时间戳部分 低22位 数据中心id5位,机器标识id5位,序号id12位,因此左移22位| dataCenterId << DATA_CENTER_LEFT       //数据中心部分| machineId << MACHINE_LEFT             //机器标识部分| sequence;                             //序列号部分}public static void main(String[] args) {SnowFlakeUtil snowFlake = new SnowFlakeUtil(2L, 3L);for (int i = 0; i < (1 << 4); i++) {//10进制System.out.println(snowFlake.nextId());}}
}

5.雪花算法的优缺点

优点

  • 高并发分布式环境下生成不重复 id,每秒可生成百万个不重复 id。
  • 基于时间戳,以及同一时间戳下序列号自增,基本保证 id 有序递增。
  • 不依赖第三方库或者中间件。
  • 算法简单,在内存中进行,效率高。

缺点

  • 依赖服务器时间,服务器时钟回拨时可能会生成重复 id。算法中可通过记录最后一个生成 id 时的时间戳来解决,每次生成 id 之前比较当前服务器时钟是否被回拨,避免生成重复 id。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1541811.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

施耐德EcoStruxure Machine SCADA Expert(EMSE)与SQL数据库连接(十五)

我习惯使用SQL Server 数据库与EMSE进行连接。 用的是sql 2017 关于数据库软件的安装教程 网上一大把。 1.新建数据库 打开数据库管理工具&#xff0c;新建数据库 2.新建表单 &#xff08;ps:这里先做一个小测试-----目的是验证与EMSE软件的链接是否顺畅。) 添加两个元素进去…

flask的学习记录

结构如下&#xff1a; app.py from App import create_appapp create_app()if __name__ __main__:app.run(debugTrue,host0.0.0.0,port5000) App/__init__.py from flask import Flask, render_template, request, redirect, url_for from .views import blue from .exts …

VisualPromptGFSS

COCO-20 i ^i i太大&#xff0c;不建议复现

golang学习笔记1-go程序执行流程

声明&#xff1a;本人已有C&#xff0c;C,Python基础&#xff0c;只写本人认为的重点&#xff0c;方便自己回顾。 命令行执行go程序有两种方式&#xff0c;其流程如下图 注意第一种方式会得到可执行文件&#xff0c;第二种不会。 例1 在当前目录下编译hello.go go build hel…

TypeScript入门 (三)数据类型

引言 大家好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者。本系列文章是我跟随DataWhale 2024年9月学习赛的TypeScript学习总结文档。本文旨在全面介绍 TypeScript 中的各种数据类型&#xff0c;帮助读者深入理解每种数据类型的用法、内置属性…

Matlab simulink建模与仿真 第十九章(生成C代码)

一、Configuration Parameters模型参数配置 1、仿真时间 &#xff08;1&#xff09;在Solver选项卡中可以设置仿真的起始时间和结束时间&#xff0c;一般起始时间设为0&#xff0c;而结束时间按需设置。 &#xff08;2&#xff09;如果希望仿真不会自动暂停&#xff08;也就…

Qwen大型语言模型系列的最新成果 ----Qwen2.5

通义千问2.5-7B-Instruct-GGUF 模型库 (modelscope.cn) apt install git-lfsgit lfs installgit clone https://www.modelscope.cn/qwen/Qwen2.5-7B-Instruct-GGUF.git

(done) 声音信号处理基础知识(3) (一个TODO: modulation 和 timbre 的关联)(强度、响度、音色)

来源&#xff1a;https://www.youtube.com/watch?vJkoysm1fHUw sound power 通常可以被认为是能量传输的速率 声源往所有方向传输的每时间单位能量 用 瓦特(W) 作为单位测量 Sound intensity 声音强度&#xff0c;每单位面积的 sound power W/m^2 人类实际上能听到非常小强…

Mybatis+Druid+MybatisPlus多数据源配置

MybatisDruidMybatisPlus多数据源配置 平常我们使用的是 properties 或者 yaml 来配置数据库的地址、用户名、密码等 但是这样只能配置一个数据源 现在我们想在一个项目里面配置多个数据源&#xff0c;那么我们就需要配置自己的配置类 配置类和配置文件 Mybatismysqldruid配置…

此框架你到底了解多少???

1.简述对Spring中IOC/DI的理解 IOC&#xff1a;控制反转&#xff0c;将创建和管理的对象的任务交给外部的Spring容器 DI&#xff1a;依赖注入&#xff0c;对象之间存在依赖关系&#xff0c;创建对象时&#xff0c;对其依赖的对应直接进行赋值 2.有哪些依赖注入的方式 基于注…

在线教程丨1 步生成 SOTA 级别图像,Hyper-SD 一键启动教程上线!

近年来&#xff0c;扩散模型在文生图任务中得到了广泛的应用&#xff0c;但其在实现高质量图像生成的过程中&#xff0c;通常需要多步推理进行去噪&#xff0c;这显然大大增加了计算资源成本。 针对于此&#xff0c;研究人员引入蒸馏算法&#xff0c;推出了扩撒感知蒸馏算法来…

超实用的 Typora 插件

&#x1f33c;&#x1f4da;Typora 是一款高效、易用且跨平台的 Markdown 编辑器和阅读器&#xff0c;其具有小巧、快速、实时预览等特点&#xff0c;非常受大家的欢迎。今天给大家推荐一款如虎添翼的 Typora 插件(Typora Plugin)&#xff0c;它可以通过插件增强 Typora 的功能…

什么是调制?FM 和 AM 有什么区别?

来源&#xff1a;https://www.bilibili.com/video/BV1pp411d7Zg/?spm_id_fromautoNext&vd_source7a1a0bc74158c6993c7355c5490fc600 一张图说明一切 原因&#xff1a;低频信号传输距离很近&#xff0c;高频信号传输距离较远。 为了把低频信号传出去&#xff0c;需要把低…

【数据结构C语言】【入门】【首次万字详细解析】入门阶段数据结构可能用到的C语言知识,一章让你看懂数据结构!!!!!!!

前言&#xff1a;欢迎各位光临本博客&#xff0c;这里小编带你直接手撕入门阶段的数据结构的C语言知识&#xff0c;让你不再看见数据结构就走不动道。文章并不复杂&#xff0c;愿诸君耐其心性&#xff0c;忘却杂尘&#xff0c;道有所长&#xff01;&#xff01;&#xff01;&am…

图片马赛克处理(Java)

1.需求 给图片的指定区域打码给整张图片打码马赛克方格取色支持中心点取色和随机取色马赛克支持灰度处理 2.源码 package com.visy.utils;import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOE…

我们如何通过两个关键测试原则,进行自动化 Kubernetes 配置和Secret测试

现如今&#xff0c;一个上规模的应用程序几乎都会使用 Kubernetes 作为管理环境实现自动扩展、负载平衡&#xff08;auto scaling, load balancing &#xff09;等机制。与之相应的&#xff0c;我们通常会使用一个 repository 专门管理一个组织内部各项不同应用程序在各个环境的…

领夹麦克风怎么样,无线领夹麦克风哪个牌子好,家用麦克风推荐

​作为消费类电子产品&#xff0c;麦克风随着市场需求和技术进步&#xff0c;每年都有新产品系列涌现&#xff0c;特别是领夹麦克风&#xff0c;近年来经历了显著的市场变革和技术突破。从早期的新闻采访、节目录制和影视后期录音中常用的无线小蜜蜂话筒&#xff0c;到如今在网…

如何选择公司

前言&#xff1a; 了不起学弟&#xff1a;学长啊&#xff0c;我这手上有几个offer&#xff0c;有几家不同种类的公司&#xff0c;我这该怎么选啊。。。 了不起&#xff1a;这确实是在正在找工作的同学一定会遇到的问题&#xff0c;如何选择公司。那我就给你讲一讲吧。 正文&…

6张图掌握提示词工程师工作范围与工作技巧(提示词原理篇)

在人工智能的疆域中&#xff0c;提示词工程师扮演着至关重要的角色。他们精心设计的话语&#xff0c;是引导AI模型理解人类需求、激发创造力的关键。如同指挥官的号令&#xff0c;提示词工程师的每一个提问&#xff0c;都让AI的潜力得到释放&#xff0c;让技术与智慧的对话更加…

u-code-input结合u-keyboard实现支付密码+数字键盘

u-code-input结合u-keyboard实现支付密码数字键盘 一、需求描述、框架&#xff08;一&#xff09;技术框架&#xff08;二&#xff09;需求 二、效果图三、代码实现&#xff08;一&#xff09;u-code-input组件小改造&#xff08;二&#xff09;功能实现 一、需求描述、框架 &…