C# 雪花算法生成Id工具类

news2024/11/23 11:25:47

写在前面

传说自然界中并不存在两片完全一样的雪花的,每一片雪花都拥有自己漂亮独特的形状、独一无二;雪花算法也表示生成的ID如雪花般独一无二,该算法源自Twitter。

雪花算法主要用于解决分布式系统的唯一Id生成问题,在生产环境中可以部署一个单独的服务来运行雪花算法,然后通过请求该服务获取全局Id。

相对于UUID来说,其长度短,生成快,做数据库主键时方便建立索引,所以整体效率要高很多。

代码实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class IdWorker
{
    //机器ID
    private static long workerId;
    private static long twepoch = 687888001020L; //唯一时间,这是一个避免重复的随机量,自行设定不要大于当前时间戳
    private static long sequence = 0L;
    private static int workerIdBits = 4; //机器码字节数。4个字节用来保存机器码(定义为Long类型会出现,最大偏移64位,所以左移64位没有意义)
    public static long maxWorkerId = -1L ^ -1L << workerIdBits; //最大机器ID
    private static int sequenceBits = 10; //计数器字节数,10个字节用来保存计数码
    private static int workerIdShift = sequenceBits; //机器码数据左移位数,就是后面计数器占用的位数
    private static int timestampLeftShift = sequenceBits + workerIdBits; //时间戳左移动位数就是机器码和计数器总字节数
    public static long sequenceMask = -1L ^ -1L << sequenceBits; //一微秒内可以产生计数,如果达到该值则等到下一微妙在进行生成
    private long lastTimestamp = -1L;

    /// <summary>
    /// 机器码
    /// </summary>
    /// <param name="workerId"></param>
    public IdWorker(long workerId)
    {
        if (workerId > maxWorkerId || workerId < 0)
            throw new Exception(string.Format("worker Id can't be greater than {0} or less than 0 ", workerId));
        IdWorker.workerId = workerId;
    }

    public long nextId()
    {
        lock (this)
        {
            long timestamp = timeGen();
            if (this.lastTimestamp == timestamp)
            { //同一微妙中生成ID
                IdWorker.sequence = (IdWorker.sequence + 1) & IdWorker.sequenceMask; //用&运算计算该微秒内产生的计数是否已经到达上限
                if (IdWorker.sequence == 0)
                {
                    //一微妙内产生的ID计数已达上限,等待下一微妙
                    timestamp = tillNextMillis(this.lastTimestamp);
                }
            }
            else
            { //不同微秒生成ID
                IdWorker.sequence = 0; //计数清0
            }
            if (timestamp < lastTimestamp)
            { //如果当前时间戳比上一次生成ID时时间戳还小,抛出异常,因为不能保证现在生成的ID之前没有生成过
                throw new Exception(string.Format("Clock moved backwards.  Refusing to generate id for {0} milliseconds",
                    this.lastTimestamp - timestamp));
            }
            this.lastTimestamp = timestamp; //把当前时间戳保存为最后生成ID的时间戳
            long nextId = (timestamp - twepoch << timestampLeftShift) | IdWorker.workerId << IdWorker.workerIdShift | IdWorker.sequence;
            return nextId;
        }
    }

    /// <summary>
    /// 获取下一微秒时间戳
    /// </summary>
    /// <param name="lastTimestamp"></param>
    /// <returns></returns>
    private long tillNextMillis(long lastTimestamp)
    {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp)
        {
            timestamp = timeGen();
        }
        return timestamp;
    }

    /// <summary>
    /// 生成当前时间戳
    /// </summary>
    /// <returns></returns>
    private long timeGen()
    {
        return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
    }
}

/// <summary>
/// 生成雪花ID
/// </summary>
public static class SnowFlake
{
    private static long _workerId = 9;
    private static IdWorker _idWorker = null;

    public static string NewId()
    {
        if (_idWorker == null)
            _idWorker = new IdWorker(_workerId);
        return _idWorker.nextId().ToString();
    }
}

调用示例

    var id = SnowFlake.NewId();
    MessageBox.Show(id.ToString());

注意事项

需要注意的是雪花算法严重依赖时间,所以当发生服务器时钟回拨的问题是会导致可能产生重复的id。当然实际基本不会发生这种情况,生产环境中很少会回调服务器系统时间,如果实在要回拨时间也可以通过调整步长参数来解决。

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

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

相关文章

科普|直流负载的工作方式有哪些

直接供电方式&#xff1a;这是最常见的直流负载工作方式&#xff0c;即直流电源直接为负载提供电能。例如&#xff0c;电池、太阳能电池板等可以直接为电动玩具、手电筒等直流负载提供电能。 间接供电方式&#xff1a;这种方式是通过交流电源转换为直流电源后&#xff0c;再为直…

基于Java SSM框架实现文物管理系统项目【项目源码+论文说明】

基于java的SSM框架实现文物管理系统演示 摘要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#…

2023美图创造力大会开幕,美图发布AI视觉大模型4.0

12月5-6日&#xff0c;主题为“未来AI设计”的美图创造力大会&#xff08;Meitu Creativity Conference&#xff0c;简称MCC&#xff09;在厦门举行。 本届大会由美图公司与站酷联合举办&#xff0c;聚焦于设计师生态和AI设计趋势。大会现场发布《2023年度AI设计实践报告》&am…

Windows 上安装nvm node版本管理工具 windows安装nvm 管理工具

Windows 上安装nvm node版本管理工具 windows安装nvm 管理工具 1、nvm2、安装2.1、下载 NVM 安装程序进行安装2.2、打开nvm的安装路径&#xff0c;运行终端测试是否安装成功2.3、配置环境变量&#xff0c;让nvm能在电脑全局使用2.3.1、nvm配置淘宝镜像2.3.2、nvm环境变量设置 1…

图像识别经典轻量级网络模型总结梳理、原理解析与优劣对比分析

在前面的很多博文中&#xff0c;我们不止一次提到过&#xff0c;在实际业务项目开发过程中&#xff0c;我们会经常使用到轻量级的网络模型&#xff0c;本文主要是总结梳理前面经常使用到的一些轻量级的图像识别模型。 【MobileNetv1】 MobileNetv1 是一种轻量级的卷积神经网络&…

(十四)Flask之闪现flash

闪现—flash 这可不是LOL或是王者荣耀里的闪现哦~ Flask 中的 “闪现”&#xff08;flash&#xff09;是一种在请求之间传递消息的机制。它允许你将一条消息保存在一个请求中&#xff0c;在下一个请求中获取并显示该消息&#xff0c;然后立即将其删除【设置完之后阅后即焚&am…

『App自动化测试之Appium基础篇』| 从定义、原理、环境搭建、安装问题排查等深入了解Appium

『App自动化测试之Appium基础篇』| 从定义、原理、环境搭建、安装问题排查等深入了解Appium 1 关于Android UI自动化测试2 Appium简介3 Appium原理3.1 Android端过程3.2 iOS端过程 4 补充内容5 JDK下载6 JDK配置7 SDK下载8 SDK配置9 配置Android环境10 安装NodeJs11 解决node安…

MyBatis 常见面试题

目录 1.MyBatis——概述1.1.什么是 ORM 框架&#xff1f;1.2.✨谈谈对 MyBatis 的理解。1.3.使用 MyBatis 相对于直接使用 SQL 有哪些优点&#xff1f;1.4.MyBatis 有什么优缺点&#xff1f;1.5.✨MyBatis 的分层结构是什么样的&#xff1f;1.6.✨MyBatis 的执行流程是什么样的…

echerts 循环图 显示获取不到id

报错&#xff1a;Uncaught TypeError: Cannot read properties of null (reading getAttribute)&#xff0c; 我所出现的问题是 1&#xff0c;我在循环方法的时候 id没有从0开始&#xff0c;把id变成从0开始循环 2&#xff0c;设置myChart 全局属性 呈现效果 代码 html 动态绑…

Web开发-问题-前后端交互数据不一致

0x01 问题描述 所用的技术&#xff1a;VueSpring Boot后端传给前端数据&#xff1a; [Student(studentId1, personorg.fatmansoft.teach.models.Person4abe6020, major软件工程, className一班, grade一年级), Student(studentId2, personorg.fatmansoft.teach.models.Person…

Ant Design Vue(v1.7.8)a-table组件的插槽功能

<template slot"unitShow" slot-scope"text, record"> slot"unitShow" 表示插槽名&#xff08;见具名插槽&#xff09; slot-scope"text, record" 表示作用域插槽接收从<a-table>组件传递进来的两个参数&#xff0c;其中…

回溯算法:复原IP地址 子集 子集II

93.复原IP地址 思路&#xff1a; 与分割回文串相似&#xff0c;复原ip地址是将给定字符串分割成点分十进制的四段&#xff0c;切割问题就可以使用回溯搜索法把所有可能性搜出来。回溯三部曲&#xff1a; 递归参数&#xff1a;除了传入的需要分割的字符串&#xff0c;仍然需要…

介绍几个有意思的 GitHub 仓库

大家好&#xff0c;我是风筝。 今天介绍几个很有意思的 github 开源项目&#xff0c;看过之后就会发现&#xff0c;github 果然深意暗藏。 GitHub对于程序员来说&#xff0c;再熟悉不过了&#xff0c;绝大多数时候&#xff0c;我们到上面都是为了学习高质量的源代码&#xff…

Windows循环检测,直到网络通/断后执行指定命令

前言 前几天&#xff0c;一个朋友让我帮他做个脚本或者批处理&#xff0c;要实现的功能很简单&#xff1a;开机时检测网络是否联通&#xff0c;如果联通了就执行一个指定的程序&#xff0c;然后脚本就可以退出了。 批处理的解决方法 手动操作时&#xff0c;我们通常使用ping…

【hacker送书第9期】算法训练营(入门篇)

第9期图书推荐 内容简介作者简介精彩书评图书目录概述参与方式 内容简介 本书以海量图解的形式&#xff0c;详细讲解常用的数据结构与算法&#xff0c;又融入大量的竞赛实例和解题技巧。通过对本书的学习&#xff0c;读者可掌握12种初级数据结构、15种常用STL函数、10种二叉树和…

HarmonyOS鸿蒙操作系统架构

目录 1. 分布式架构&#xff1a; 2. 统一的开发平台&#xff1a; 3. 多内核共享&#xff1a; 4. 自适应界面&#xff1a; 5. AR、VR、MR支持&#xff1a; 6. 安全和隐私保护&#xff1a; 7. AI集成&#xff1a; 8. 应用生态系统&#xff1a; 9. 开源和开放&#xff1a…

Maxwell学习笔记

1 概述 Maxwell 是由美国 Zendesk 开源&#xff0c;用 Java 编写的 MySQL 实时抓取软件。 实时读取MySQL 二进制日志 Binlog&#xff0c;并生成 JSON 格式的消息&#xff0c;作为生产者发送给 Kafka&#xff0c;Kinesis、RabbitMQ、Redis、Google Cloud Pub/Sub、文件或其它平台…

webpack学习-2.管理资源

webpack学习-2.管理资源 1.这章要干嘛2.加载css注意顺序&#xff01; 3.总结 1.这章要干嘛 管理资源&#xff0c;什么意思呢&#xff1f;管理什么资源&#xff1f;项目中经常会 导入各种各样的css文件&#xff0c;图片文件&#xff0c;字体文件&#xff0c;数据文件等等&#…

<Linux>(极简关键、省时省力)《Linux操作系统原理分析之文件管理(3)》(24)

《Linux操作系统原理分析之文件管理&#xff08;3&#xff09;》&#xff08;24&#xff09; 7 文件管理7.5 文件存储空间的管理7.6 文件的共享和保护7.6.1 文件存取控制7.6.2 文件共享的实现方法7.6.3 文件的备份转储 7 文件管理 7.5 文件存储空间的管理 位示图 对每个磁盘…

使用 PyTorch 完全分片数据并行技术加速大模型训练

本文&#xff0c;我们将了解如何基于 PyTorch 最新的 完全分片数据并行 (Fully Sharded Data Parallel&#xff0c;FSDP) 功能用 Accelerate 库来训练大模型。 动机 &#x1f917; 随着机器学习 (ML) 模型的规模、大小和参数量的不断增加&#xff0c;ML 从业者发现在自己的硬件…