分布式唯一ID生成(四):tinyid

文章目录

  • 本系列
  • 前言
  • 号段模式
  • 多DB支持
  • tinyid-client

本系列

  • 漫谈分布式唯一ID
  • 分布式唯一ID生成(二):leaf
  • 分布式唯一ID生成(三):uid-generator
  • 分布式唯一ID生成(四):tinyid(本文)

前言

tinyid的主要特性有:

  • 生成全局唯一的64位数字ID
  • 趋势递增的id:趋势递增的意思是,id是递增但不一定是连续的
  • 支持生成1,3,5,7,9…序列的ID
  • 支持配置多个db,每次随机从一个db获取号段,提高可用性
  • 支持client获取一批ID,然后本地发号,提升性能

适用场景只要求ID是数字,趋势递增的系统
不适用场景:类似于订单的业务,因为生成的ID大部分是连续的,容易被扫库、或者推算出订单量等信息

本文侧重介绍leaf上没有的一些特性

源码:https://github.com/didi/tinyid


号段模式

号段模式的分布式ID需要在db中记录上一次分配到哪了,号段有多长等信息。表结构如下:

CREATE TABLE `tiny_id_info` (  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主键',  `biz_type` varchar(63) NOT NULL DEFAULT '' COMMENT '业务类型,唯一',  `begin_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '开始id,仅记录初始值,无其他含义。初始化时begin_id和max_id应相同',  `max_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '当前最大id',  `step` int(11) DEFAULT '0' COMMENT '步长',  `delta` int(11) NOT NULL DEFAULT '1' COMMENT '每次id增量',  `remainder` int(11) NOT NULL DEFAULT '0' COMMENT '余数',  `create_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '创建时间',  `update_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '更新时间',  `version` bigint(20) NOT NULL DEFAULT '0' COMMENT '版本号',  PRIMARY KEY (`id`),  UNIQUE KEY `uniq_biz_type` (`biz_type`)  
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT 'id信息表';

重点介绍这些字段:

  • biz_type:代表业务类型,不同业务的id隔离
  • max_id:上一个号段最大分配到哪个ID了
  • step:号段的长度,可以根据每个业务的qps来设置一个合理的长度
  • version:乐观锁,每次更新都加上version,保证并发更新的正确性
  • delta和remainder用于支持多DB,下文分析

通过乐观锁的方式获取号段:

先查出biz_type对应的maxId,step,version:

select id, biz_type, begin_id, max_id, step, delta, remainder, create_time, update_time, version 
from tiny_id_info where biz_type = ?

查到max_id后,将其更新为 max_id + step,执行更新sql:

update tiny_id_info set max_id= ?, update_time=now(), version=version+1 
where id=? and max_id=? and version=? and biz_type=?

如果更新成功,就获得了 [ max_id+1 : max_id + step ] 这个区间的号段

和leaf一样,tinyid也在内存中维护了双buffer,默认为当前号段消耗到 20% 时,就异步去db加载下一个号段。这样当前号段用完时,能马上切换到写一个号段,解决TP999高的问题,可以参考分布式唯一ID生成(二):leaf


关于鉴权,tinyid把权限数据存储到了另一张表tiny_id_token,和leaf一样,提前把这部分数据全量加载到本地内存,请求到来时直接在内存中鉴权,大大提高性能,


多DB支持

当只有一个db时,有严重的单点问题,无法做到高可用。tinyId支持多个DB,每次获取号段时,可以从任意一个db上获取,因此只要有一个db都能让服务可用
那么如果从多个DB都获取到了同一号段,我们怎么保证生成的id不重呢?tinyid是这么做的,引入了 步长delta余数remainder 的概念

  • delta:代表从号段中每次获取ID增加的步长
  • remainder:代表当前号段只能获得 % delta,余数为remainder 的ID

假设在3个db中分别有如下记录

db1:

idbiz_typemax_idstepdeltaremainderversion
1bizA10001000300

db2:

idbiz_typemax_idstepdeltaremainderversion
1bizA10001000310

db3:

idbiz_typemax_idstepdeltaremainderversion
1bizA10001000320

那么:
从db1拿到号段生成的的序列为:0,3,6,9...
从db2拿到号段生成的的序列为:1,4,7,10...
从db3拿到号段生成的的序列为:2,5,8,11...

对应源码如下:

public void init() {  if (isInit) {  return;  }  synchronized (this) {  if (isInit) {  return;  }  long id = currentId.get();  /**  * 例如:delta=3, remainder在3个db上分别为0,1,2  * 从db1拿到的序列为:0,3,6,9...  * 从db2拿到的序列为:1,4,7,10...  * 从db3拿到的序列为:2,5,8,11...  */       if (id % delta == remainder) {  isInit = true;  return;  }  for (int i = 0; i <= delta; i++) {  id = currentId.incrementAndGet();  if (id % delta == remainder) {  // 避免浪费 减掉系统自己占用的一个id  currentId.addAndGet(0 - delta);  isInit = true;  return;  }  }  }  
}

tinyid-client

使用http获取一个id,存在网络开销,是否可以本地生成id?
为此提供了tinyid-client,可以向tinyid-server发送请求来获取可用号段,之后在本地构建双号段、本地发号

最终架构图如下:
在这里插入图片描述

优点为:

  • 性能大大提升,如此id生成则变成纯本地操作
  • client和server可以跨机房部署,因为一个号段只用调一次server,就算跨机房延迟高也不会影响业务
  • 可用性也大大提升,因为本地缓存了一部分ID,可以容忍tinyid-server一段时间宕机
  • 降低对tiny-server的压力,访问tiny-server的频率从变为原来的1/step

缺点为:

  • 如果client启动频繁,可能浪费很多id

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

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

相关文章

JavaWeb:文件上传2

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…

April tag坐标定义

朝右的方向为x轴正向&#xff0c; 朝下的方向为y轴正方向&#xff0c; z 轴垂直纸面向里。 4个角点的坐标定义如下图所示。

江行智能×图扑软件:输煤皮带数字孪生管控系统

在现代矿业和电力行业中&#xff0c;输煤皮带系统是运输环节的核心。然后&#xff0c;随着智能化生产的高要求&#xff0c;智慧矿山输煤皮带系统的传统管理模式已显得力不从心。产业引入的三维可视化和数字孪生技术&#xff0c;一改传统输煤皮带系统由于设备老化、管理不善等原…

【Python】从入门开始抓取你想要的电影,一周可掌握基础,附完整源码

Python学习很简单&#xff0c;只是你走进了误区。 为什么你一定要先掌握枯燥的基础点后&#xff0c;再去做实际操作呢&#xff1f; 其实&#xff0c;你根本坚持不了那么长时间&#xff0c;但实际上你可以直接去做python项目。 不信&#xff1f;看看我做这个项目的思路&#x…

【C++】map和set的介绍及使用

前言&#xff1a; map和 set 是 C STL&#xff08;标准模板库&#xff09;中的两种非常重要的容器&#xff0c;它们基于一种叫做平衡二叉搜索树&#xff08;通常是红黑树&#xff09;的数据结构来实现。在 C 中&#xff0c;map 是一个键值对容器&#xff0c;set 只存储唯一的键…

NumPy 数组属性

1.NumPy 数组的基本属性 NumPy 数组的维数称为秩&#xff08;rank&#xff09;&#xff0c;秩就是轴的数量&#xff0c;即数组的维度&#xff0c;一维数组的秩为 1&#xff0c;二维数组的秩为 2&#xff0c;以此类推。NumPy中&#xff0c;每个线性的数组称为轴&#xff08;axis…

Spring源码(十二):Spring MVC之Spring Boot

本篇将详细讨论Spring Boot 的启动/加载、处理请求的具体流程。我们先从一个简单的Spring Boot项目日志开始分析&#xff08;这里假设读者已经仔细阅读完了前面的文章&#xff0c;且对Spring源码有一定深度的了解&#xff0c;否则会看得一脸懵逼&#xff09;。 本文为2024重置…

游戏引擎学习第四天

视频参考:https://www.bilibili.com/video/BV1aDmqYnEnc/ BitBlt 是 Windows GDI&#xff08;图形设备接口&#xff09;中的一个函数&#xff0c;用于在设备上下文&#xff08;device context, DC&#xff09;之间复制位图数据。BitBlt 的主要用途是将一个图像区域从一个地方复…

双指针算法的妙用:提高代码效率的秘密(2)

双指针算法的妙用&#xff1a;提高代码效率的秘密&#xff08;2&#xff09; 前言&#xff1a; 小编在前几日讲述了有关双指针算法两道题目的讲解&#xff0c;今天小编继续进行有关双指针算法习题的讲解&#xff0c;老规矩&#xff0c;今天还是两道题目的讲解&#xff0c;希望…

[CKS] K8S NetworkPolicy Set Up

最近准备花一周的时间准备CKS考试&#xff0c;在准备考试中发现有一个题目关于不安全项目修复的题目。 What’s the NetworkPolicy 关于network policy的介绍可以查看&#xff1a; https://kubernetes.io/docs/concepts/services-networking/network-policies/ Question 1 …

python全栈开发《62.获取两个集合的并集》

目录 1.什么是并集2.union的功能3.union的用法4.代码 1.什么是并集 集合a&#xff1a;1&#xff0c;2&#xff0c;3&#xff0c;4 集合b&#xff1a;3&#xff0c;4&#xff0c;5&#xff0c;6 a和b一共拥有的不重复的元素有1&#xff0c;2&#xff0c;3&#xff0c;4&#xff…

DICOM图像知识:DICOM图像排序与坐标系解析

目录 引言 1. 概述 2. DICOM图像排序规则 2.1 Patient的Study按Study Date排序 2.2 Study的Series按Series Number排序 2.3 Series的SOP按Instance Number或Slice Location排序 2.3.1 Instance Number排序 2.3.2 Slice Location排序 2.3.3 使用Image Position (Patien…

B-Spline(B样条)插值

B-Spline&#xff08;B样条&#xff09;详细介绍 B-Spline&#xff08;B样条&#xff09;是一种常用于计算机图形学和数据拟合的数学方法。它由一系列控制点和节点&#xff08;Knots&#xff09;以及一组基函数&#xff08;Basis Functions&#xff09;组成。B-Spline 能够通过…

HarmonyOS Next 并发 taskpool 和 worker

HarmonyOS Next 并发 taskpool 和 worker 总览 介绍 并发&#xff0c;指的是同一时间内&#xff0c;多段代码同时执行。在ArkTs编程中&#xff0c;并发分为异步并发和多线程并发。 异步并发 异步并发并不是真正的并发&#xff0c;比如在单核设备中&#xff0c;同时执行多端…

4.3软件设计:面对对象的设计

面对对象设计 1、面对对象的架构设计1.1 第一步&#xff1a;构造系统的物理模型1.2 第二步&#xff1a;设计子系统划分各个子系统的方式定义子系统之间的关系定义子系统的接口 1.3 第三步&#xff1a;非功能需求设计 2、面对对象的用例设计与类设计2.1 类2.2 类间关系2.3 细化用…

华为OD机试 - 求小球落地5次后所经历的路程和第5次反弹的高度 (Java 2024 E卷 100分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题 点这里。 实战项目访问&#xff1a;http://javapub.net.cn/ 专栏导读 本专栏收录于 《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;E卷D卷A卷B卷C卷&#xff09;》 。 刷的越多&#xff0c;抽中的概率越大&…

VBA08-if语句

一、单行 If 语句 If x > 10 Then MsgBox "x is greater than 10"二、多行 If...Then...End If 语句 If x > 10 ThenMsgBox "x is greater than 10"y x 5 End If 三、If...Then...Else 语句 If condition Then 当条件为真时执行的代码块stateme…

JS 函数的基本知识

目录 1. 介绍函数 2. 使用函数 3. 函数传参 3.1 传递默认值 3.2 传递数组 3.3 传递变量 4. 函数返回值 5. 匿名函数 6. 立即执行函数 7. 注意 1. 介绍函数 在学习 CSS 样式过程中&#xff0c;经常有如下操作&#xff1a; 2. 使用函数 函数声明&#xff1a; 函数命名规…

澳鹏通过高质量数据支持 Onfido 优化AI反欺诈功能

“Appen 在 Onfido 的发展中发挥了至关重要的作用&#xff0c;并已成为我们运营的重要组成部分。我们很高兴在 Appen 找到了可靠的合作伙伴。” – Onfido 数据和分析总监 Francois Jehl 简介&#xff1a;利用人工智能和机器学习增强欺诈检测 在当今日益数字化的世界&#xff…

【大模型】Spring AI Alibaba 对接百炼平台大模型使用详解

目录 一、前言 二、Spring AI概述 2.1 spring ai是什么 2.2 Spring AI 核心能力 2.3 Spring AI 应用场景 三、Spring AI Alibaba 介绍 3.1 Spring AI Alibaba 是什么 3.2 Spring AI Alibaba 核心特点 3.3 Spring AI Alibaba 应用场景 四、SpringBoot 对接Spring AI Al…