当前位置: 首页 > news >正文

分布式全局id

分布式全局id

snowflake 算法是 twitter 开源的分布式 id 生成算法,采用 Scala 语言实现,是把一个 64 位的 long 型的 id,1 个 bit 是不用的,用其中的 41 bits 作为毫秒数,用 10 bits 作为工作机器 id,12 bits 作为序列号。

  • 1 bit:不用,为啥呢?因为二进制里第一个 bit 为如果是 1,那么都是负数,但是我们生成的 id 都是正数,所以第一个 bit 统一都是 0。
  • 41 bits:表示的是时间戳,单位是毫秒。41 bits 可以表示的数字多达 2^41 - 1 ,也就是可以标识 2^41 - 1 个毫秒值,换算成年就是表示 69 年的时间。
  • 10 bits:记录工作机器 id,代表的是这个服务最多可以部署在 2 ^ 10 台机器上,也就是 1024 台机器。但是 10 bits 里 5 个 bits 代表机房 id,5 个 bits 代表机器 id。意思就是最多代表 2^5 个机房(32 个机房),每个机房里可以代表 2^5 个机器(32 台机器)。
  • 12 bits:这个是用来记录同一个毫秒内产生的不同 id,12 bits 可以代表的最大正整数是 2^12 - 1 = 4096 ,也就是说可以用这个 12 bits 代表的数字来区分同一个毫秒内的 4096 个不同的 id。
0 | 0001100 10100010 10111110 10001001 01011100 00 | 10001 | 1 1001 | 0000 00000000

在这里插入图片描述

:::details 实现不用看,有工具实现得更好

public class IdWorker {private long workerId;private long datacenterId;private long sequence;public IdWorker(long workerId, long datacenterId, long sequence) {// sanity check for workerId// 这儿不就检查了一下,要求就是你传递进来的机房id和机器id不能超过32,不能小于0if (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));}System.out.printf("worker starting. timestamp left shift %d, datacenter id bits %d, worker id bits %d, sequence bits %d, workerid %d",timestampLeftShift, datacenterIdBits, workerIdBits, sequenceBits, workerId);this.workerId = workerId;this.datacenterId = datacenterId;this.sequence = sequence;}private long twepoch = 1288834974657L;private long workerIdBits = 5L;private long datacenterIdBits = 5L;// 这个是二进制运算,就是 5 bit最多只能有31个数字,也就是说机器id最多只能是32以内private long maxWorkerId = -1L ^ (-1L << workerIdBits);// 这个是一个意思,就是 5 bit最多只能有31个数字,机房id最多只能是32以内private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);private long sequenceBits = 12L;private long workerIdShift = sequenceBits;private long datacenterIdShift = sequenceBits + workerIdBits;private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;private long sequenceMask = -1L ^ (-1L << sequenceBits);private long lastTimestamp = -1L;public long getWorkerId() {return workerId;}public long getDatacenterId() {return datacenterId;}public long getTimestamp() {return System.currentTimeMillis();}public synchronized long nextId() {// 这儿就是获取当前时间戳,单位是毫秒long timestamp = timeGen();if (timestamp < lastTimestamp) {System.err.printf("clock is moving backwards.  Rejecting requests until %d.", lastTimestamp);throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));}if (lastTimestamp == timestamp) {// 这个意思是说一个毫秒内最多只能有4096个数字// 无论你传递多少进来,这个位运算保证始终就是在4096这个范围内,避免你自己传递个sequence超过了4096这个范围sequence = (sequence + 1) & sequenceMask;if (sequence == 0) {timestamp = tilNextMillis(lastTimestamp);}} else {sequence = 0;}// 这儿记录一下最近一次生成id的时间戳,单位是毫秒lastTimestamp = timestamp;// 这儿就是将时间戳左移,放到 41 bit那儿;// 将机房 id左移放到 5 bit那儿;// 将机器id左移放到5 bit那儿;将序号放最后12 bit;// 最后拼接起来成一个 64 bit的二进制数字,转换成 10 进制就是个 long 型return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift)| (workerId << workerIdShift) | sequence;}private long tilNextMillis(long lastTimestamp) {long timestamp = timeGen();while (timestamp <= lastTimestamp) {timestamp = timeGen();}return timestamp;}private long timeGen() {return System.currentTimeMillis();}// ---------------测试---------------public static void main(String[] args) {IdWorker worker = new IdWorker(1, 1, 1);for (int i = 0; i < 30; i++) {System.out.println(worker.nextId());}}}

:::

思考

需要用到雪花算法一般都是大型分布式系统,而分布式意味着同一套代码的重复部署,所以上面的雪花算法还有两个最重要的问题没有解决。

  1. 分布式系统中的workerId/datacenterId 怎么确保强唯一
  2. timeStamp 怎么确保系统时钟不回拨

业界大牛的实现

  • https://github.com/baidu/uid-generator/blob/master/README.zh_cn.md

UidGenerator是Java实现的, 基于Snowflake算法的唯一ID生成器。UidGenerator以组件形式工作在应用项目中, 支持自定义workerId位数和初始化策略, 从而适用于docker等虚拟化环境下实例自动重启、漂移等场景。 在实现上, UidGenerator通过借用未来时间来解决sequence天然存在的并发限制; 采用RingBuffer来缓存已生成的UID, 并行化UID的生产和消费, 同时对CacheLine补齐,避免了由RingBuffer带来的硬件级「伪共享」问题. 最终单机QPS可达600万。

  • https://tech.meituan.com/2017/04/21/mt-leaf.html

在复杂分布式系统中,往往需要对大量的数据和消息进行唯一标识。如在美团点评的金融、支付、餐饮、酒店、猫眼电影等产品的系统中,数据日渐增长,对数据分库分表后需要有一个唯一ID来标识一条数据或消息,数据库的自增ID显然不能满足需求;特别一点的如订单、骑手、优惠券也都需要有唯一ID做标识。此时一个能够生成全局唯一ID的系统是非常必要的。概括下来,那业务系统对ID号的要求有哪些呢?

  1. 全局唯一性:不能出现重复的ID号,既然是唯一标识,这是最基本的要求。
  2. 趋势递增:在MySQL InnoDB引擎中使用的是聚集索引,由于多数RDBMS使用B-tree的数据结构来存储索引数据,在主键的选择上面我们应该尽量使用有序的主键保证写入性能。
  3. 单调递增:保证下一个ID一定大于上一个ID,例如事务版本号、IM增量消息、排序等特殊需求。
  4. 信息安全:如果ID是连续的,恶意用户的扒取工作就非常容易做了,直接按照顺序下载指定URL即可;如果是订单号就更危险了,竞对可以直接知道我们一天的单量。所以在一些应用场景下,会需要ID无规则、不规则。

相关文章:

分布式全局id

分布式全局id snowflake 算法是 twitter 开源的分布式 id 生成算法&#xff0c;采用 Scala 语言实现&#xff0c;是把一个 64 位的 long 型的 id&#xff0c;1 个 bit 是不用的&#xff0c;用其中的 41 bits 作为毫秒数&#xff0c;用 10 bits 作为工作机器 id&#xff0c;12 …...

springboot 房屋租赁系统

spring boot mysql mybatis 前台后端...

TypeScript接口、对象

目录 1、TypeScript 接口 1.1、实例 1.2、联合类型和接口 1.3、接口和数组 1.4、接口和继承 1.5、单继承实例 1.6、多继承实例 2、TypeScript 对象 2.2、对象实例 2.3、TypeScript类型模板 2.4、鸭子类型&#xff08;Duck typing&#xff09; 1、TypeScript 接口 接口…...

Flask 菜品管理

common/libs/Helper.py getDictFilterField() 方法 用于在web/templates/food/index.html中展示菜品分类 如何能够通过food里面的cat_id获取分类信息呢&#xff1f;只能通过for循环&#xff0c;这样会很麻烦&#xff0c;所以定义了这个方法。 这个方法可以的查询返回结果…...

亚马逊实时 AI 编程助手 CodeWhisperer使用体验

文章目录 1&#xff1a;什么是CodeWhisperer &#xff1f;2&#xff1a;试用3&#xff1a;上手体验 1&#xff1a;什么是CodeWhisperer &#xff1f; 最近ChatGPT展现出强大AI能力给我们带来了深刻的影响&#xff0c;AI现在不是一个概念&#xff0c;基于AI的产品一定在各行各业…...

[机缘参悟-123] :实修 - 东西方各种思想流派实修的要旨与比较?

目录 前言&#xff1a; 一、东方各种思想流派实修的要旨&#xff1f; 1.1 儒、释、道、法的主要思想 1.2 儒、释、道、法各种追求的目标 1.3 儒、释、道、法各自修行的法门或修行的途径 二、西方灵修的各种派别的要旨&#xff1f; 2.0 西方灵修的各种派别 2.1 玛雅星系…...

基于51单片机的数字时钟系统设计

标题&#xff1a;基于51单片机的数字时钟系统设计与实现 摘要&#xff1a; 本文详细介绍了基于STC89C51单片机设计一款具有精确计时功能的数字时钟系统的全过程。该系统利用了单片机内部的定时器/计数器资源&#xff0c;结合液晶显示屏和按键输入模块&#xff0c;实现了时间显…...

《每天十分钟》-红宝书第4版-基本引用类型

引用值&#xff08;或者对象&#xff09;是某个特定引用类型的实例。在 ECMAScript 中&#xff0c;引用类型是把数据和功能组织到一起的结构&#xff0c;经常被人错误地称作“类”。虽然从技术上JavaScript 是一门面向对象语言&#xff0c;但ECMAScript 缺少传统的面向对象编程…...

【EAI 005】EmbodiedGPT:通过具身思维链进行视觉语言预训练的具身智能大模型

论文描述&#xff1a;EmbodiedGPT: Vision-Language Pre-Training via Embodied Chain of Thought 论文作者&#xff1a;Yao Mu, Qinglong Zhang, Mengkang Hu, Wenhai Wang, Mingyu Ding, Jun Jin, Bin Wang, Jifeng Dai, Yu Qiao, Ping Luo 作者单位&#xff1a;The Universi…...

一文读懂「Chain of Thought,CoT」思维链

前言: 思维链,在人工智能领域,是一个非常非常新的概念。强大的逻辑推理是大语言模型“智能涌现”出的核心能力之一,好像AI有了人的意识一样。而推理能力的关键在于——思维链(Chain of Thought,CoT)。 相关概念: 语言智能可以被理解为“使用基于自然语言的概念对经验事…...

杨中科 ASP.NET Core 中的依赖注入的使用

ASP.NET CORE中服务注入的地方 1、在ASP.NET Core项目中一般不需要自己创建ServiceCollection、IServiceProvider。在Program.cs的builder.Build()之前向builderServices中注入 2、在Controller中可以通过构造方法注入服 务。 3、演示 新建一个calculator类 注入 新建TestC…...

Spring Boot 和 Spring 有什么区别

Spring Boot 和 Spring 是两个不同的概念&#xff0c;它们服务于不同的目的&#xff0c;但它们之间有着紧密的联系。下面是它们之间的主要区别&#xff1a; 目的和定位&#xff1a; Spring&#xff1a;Spring 是一个开源的 Java 平台&#xff0c;它最初由 Rod Johnson 创建&am…...

Linux——以太网

一、Linux下的以太网架构 1、Linux 系统网络协议层架构 PHY 驱动的功能处于链路层&#xff1a; 2、以太网物理层与硬件连接 我们重点关注以下两点&#xff1a; &#xff08;1&#xff09;与 MAC 设备的接口&#xff0c;即是 gmii 还是 rgmii。 &#xff08;2&#xff09; Phy…...

HTTP 代理原理及实现(二)

在上篇《HTTP 代理原理及实现&#xff08;一&#xff09;》里&#xff0c;我介绍了 HTTP 代理的两种形式&#xff0c;并用 Node.js 实现了一个可用的普通 / 隧道代理。普通代理可以用来承载 HTTP 流量&#xff1b;隧道代理可以用来承载任何 TCP 流量&#xff0c;包括 HTTP 和 H…...

JavaScript 地址信息与页面跳转

在JavaScript中&#xff0c;你可以使用各种方法来处理地址信息并进行页面跳转。以下是一些常见的方法&#xff1a; 1.使用window.location对象&#xff1a; window.location对象包含了当前窗口的URL信息&#xff0c;并且可以用来进行页面跳转。 * 获取URL的某一部分&#xf…...

力扣(leetcode)第383题赎金信(Python)

383.赎金信 题目链接&#xff1a;383.赎金信 给你两个字符串&#xff1a;ransomNote 和 magazine &#xff0c;判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以&#xff0c;返回 true &#xff1b;否则返回 false 。 magazine 中的每个字符只能在 ransomNote…...

提升网络安全重要要素IP地址

在数字化时代&#xff0c;网络安全已经成为人们关注的焦点。本文将深入探讨网络安全与IP地址之间的紧密联系&#xff0c;以及IP地址在构建数字世界的前沿堡垒中的关键作用。 网络安全是当今数字社会中不可忽视的挑战之一。而IP地址&#xff0c;作为互联网通信的基础协议&#…...

解析c++空指针解引用奔溃

空指针解引用引起程序奔溃是c/c中最常见的稳定性错误之一。 显然并非所有使用空指针的语句都会导致奔溃&#xff0c;那什么情况下使用空指针才会引起程序奔溃呢&#xff1f;有一个判断标准&#xff1a;判断空指针是否会导致访问非法内存的情况&#xff0c;如果会导致访问非法内…...

Oracle START WITH 递归语句的使用方法及示例

Oracle数据库中的START WITH语句经常与CONNECT BY子句一起使用&#xff0c;以实现对层次型数据的查询。这种查询模式非常适用于处理具有父子关系的数据&#xff0c;如组织结构、分类信息等。 理解START WITH和CONNECT BY 在层次型查询中&#xff0c;START WITH定义了层次结构…...

使用Windbg动态调试目标进程的一般步骤详解

目录 1、概述 2、将Windbg附加到已经启动起来的目标进程上&#xff0c;或者用Windbg启动目标程序 2.1、将Windbg附加到已经启动起来的目标进程上 2.2、用Windbg启动目标程序 2.3、Windbg关联到目标进程上会中断下来&#xff0c;输入g命令将该中断跳过去 3、分析实例说明 …...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...