首页 > 其他分享 >【分布式】分布式ID

【分布式】分布式ID

时间:2024-03-19 14:14:41浏览次数:19  
标签:sequence 数据库 ID version NULL id 分布式

本文为分布式学习笔记,参考了JavaGuide


设计分布式ID有两种思路:

  1. 第一种是让所有获取ID的机器从同一个地方获取,ID生成器只需要简单自增即可。
  2. 第二种是通过一定的算法,使各个机器产生的ID不重复,这也是一种方式。

同一ID生成方式

数据库

数据库主键自增

利用数据库主键自增来产生唯一ID,通过在同一个事务中replace into插入,让着通过last_insert_id()函数来获取ID。

例子:

首先创建一张表

CREATE TABLE `sequence_id`
(
    `id`   bigint(20) unsigned NOT NULL AUTO_INCREMENT,
    `stub` char(10)            NOT NULL DEFAULT '站位字段',
    PRIMARY KEY (`id`),
    UNIQUE KEY `stub` (`stub`)
);

stub为占位字段,方便插入修改数据,有唯一索引。

然后通过一下方式获取一个唯一ID:

BEGIN;
REPLACE INTO sequence_id (stub) VALUES ('stub');
SELECT LAST_INSERT_ID();
COMMIT;

优缺点:

  • 优点:实现起来比较简单、ID 有序递增、存储消耗空间小
  • 缺点:支持的并发量不大、存在数据库单点问题、ID 没有具体业务含义、安全问题(比如根据订单 ID 的递增规律就能推算出每天的订单量,商业机密啊!)、每次获取 ID 都要访问一次数据库(增加了对数据库的压力,获取速度也慢)

数据库号段模式

相比第一种每次获取ID都需要访问一次数据库,第二种方式是批量获取ID,然后放在内存中,避免了每次都需要访问数据库的弊端。

TinyID 就是基于这种原理。

例子:


CREATE TABLE `sequence_id_generator`
(
    `id`             int(10)    NOT NULL,
    `current_max_id` bigint(20) NOT NULL COMMENT '当前最大id',
    `step`           int(10)    NOT NULL COMMENT '号段的长度',
    `version`        int(20)    NOT NULL COMMENT '版本号',
    `biz_type`       int(20)    NOT NULL COMMENT '业务类型',
    PRIMARY KEY (`id`)
);

current_max_idstep用来获取ID,version用来解决并发问题,biz_type用来区分业务类型。

插入一条初始数据:

INSERT INTO `sequence_id_generator` (`id`, `current_max_id`, `step`, `version`, `biz_type`)
VALUES (1, 0, 100, 0, 101);

每次获取ID时,先查询然后再更新,如果更新没成功则需要重新查询并更新:

select id, current_max_id, step, version, biz_type
from sequence_id_generator
where biz_type = 101;
-- 1,100,100,1,101

UPDATE sequence_id_generator
SET current_max_id = 0 + 100,
    version = version + 1
WHERE version = 0
  AND `biz_type` = 101;

相比于数据库主键自增方式,数据库的号段模式对于数据库的访问次数更少,数据库压力更小,并且可以使用主从模式提高可用性。

优缺点:

  • 优点:ID 有序递增、存储消耗空间小
  • 缺点:存在数据库单点问题、ID 没有具体业务含义、安全问题

开源实现有TinyID和Leaf。

NoSQL

Redis

一般NoSQL使用Redis比较多,通过Redis的incr命令可以实现ID原子顺序递增。

本地:db0> set seq 1
OK
本地:db0> incr seq
2
本地:db0> get seq
2

为了提高可用性和高并发,可以将Redis集群化,可以使用官方集群解决方案Redis Cluster或者Codis。

Redis基于内存,防止宕机后数据丢失,需要开启持久化,两种持久化方式:RDB和AOF,RDB是快照模式,AOF是保存修改命令方式。

优缺点:

  • 优点:性能优良、ID有序自增
  • 缺点:和数据库ID自增类似

MongoDB

MongoDB ObjectId也会拿来做分布式ID。

MongoDB ObjectId 一共需要 12 个字节存储:

  • 0~3:时间戳
  • 3~6:代表机器 ID
  • 7~8:机器进程 ID
  • 9~11:自增值

优缺点:

  • 优点:性能优良、ID有序自增
  • 缺点:ID可能重复(时间不对时)、安全问题

算法

UUID

UUID包含32个16进制数,一般不会用来做数据库主键。

  • 主键尽量越短越好,UUID为32位字符串,总共128位
  • UUID 是无顺序的,InnoDB 引擎下,数据库主键的无序性会严重影响数据库性能

优缺点:

  • 优点:生成速度快、简单易用
  • 缺点:存储消耗空间大、无序、需要解决重复ID问题(时间设置重置后可能会有重复ID)

雪花算法

雪花算法由64 bit二进制数字组成,其中每一部分都有特定含义:

1 + 41 + 10 + 12

  • sign(1bit):符号位(标识正负),始终为 0,代表生成的 ID 为正数。
  • timestamp (41 bits):一共 41 位,用来表示时间戳,单位是毫秒,可以支撑 2 ^41 毫秒(约 69 年)
  • datacenter id + worker id (10 bits):一般来说,前 5 位表示机房 ID,后 5 位表示机器 ID
  • sequence (12 bits):一共 12 位,用来表示序列号。 序列号为自增值,代表单台机器每毫秒能够产生的最大 ID 数(2^12 = 4096),也就是说单台机器每毫秒最多可以生成 4096 个 唯一 ID

优缺点:

  • 优点:生成速度比较快、生成的 ID 有序递增、比较灵活(可以简单改造,比如加入业务ID)
  • 缺点:需要解决重复 ID 问题(ID生成依赖时间,时间回拨时会生成重复ID)、依赖机器ID对分布式环境不友好

一般使用雪花算法不需要自己造轮子,有许多开源实现,比如Leaf(支持数据库号段模式和雪花算法模式)、UidGenerator(改良雪花算法)、IdGenerator等。

标签:sequence,数据库,ID,version,NULL,id,分布式
From: https://www.cnblogs.com/code-blog/p/18082617

相关文章

  • Qt 编译qt-material-widgets皮肤的方法
    编译qt-material-widgets皮肤的方法首先qt-material-widgets的源代码直接拉下来是无法编译的,我们只能根据报错一步步寻找如何编译。1.必须先编译components项目得到lib文件2.然后编译examples,但是发现编译失败3.因为在examples,pro默认为linux库,修改其中内容,libcomponents.a......
  • 面对 Nvidia 的主导地位:非大型科技公司的敏捷机器学习开发策略(在供应和成本挑战中)
    在真正的大玩家中建立游戏业务从来都不是一件容易的事。2023年,在真正令人费解的突破的推动下,人工智能领域的竞争达到了前所未有的高度。OpenAI的发布GPT-4,整合与Bing聊天GPT,谷歌推出诗人,以及Meta备受争议的“开源”骆驼2发布。听起来像是一长串大人物的名......
  • 永恒的T800 —— 终结者T800 —— 智能机器人(双足机器人、人形机器人、humanoid)
    终结者T800全身像墨生青铜雕像摆件工艺品艺术品铸铜收藏品铜手办网店地址:https://item.taobao.com/item.htm?id=745037184577&skuId=5234347429545&spm=a21m98.27004841......
  • android.mk语法记录
    遇到的android.mk语法在此记录,持续更新ifeq($(TEST_PATH),)//如果TEST_PATH为空的话继续往下执行LOCAL_PATH:=$(abspath$(callmy-dir)/../..)//my-dir返回当前的路径,abspath取绝对路径TEST_PATH:=$(abspath$(LOCAL_PATH)/../../../..)elseLOCAL_PATH:=......
  • IDEA + Tomcat控制台乱码问题
    1.进入IDEA安装目录,进入bin文件夹,找到idea64.exe.vmoptions和idea.exe.vmoptions这两个文件,在每个文件新增2行,加入-Dfile.encoding=UTF-8和-Dconsole.encoding=UTF-82.打开IDEA,file—settings—Editor—FileEncodings的GlobalEncoding和ProjectEncoding和Defaultenc......
  • Maven Archetype自定义工程模板(Eclipse中,其他IDE同理)
    1.问题在Eclipse中,我们想创建一个web项目,使用web-app脚手架进行创建,但是里面的模板并不是我们想要的比如我想自定义pom.xml里面的内容,设定jdk版本,groupID等等,配置Web项目基本依赖以及我想要设置一个基本的index.jsp(符合基本模板的)和web.xml中设置web-app的版本为3.1......
  • 功能齐全的免费 IDE Visual Studio 2022 社区版
    面向学生、开放源代码和单个开发人员的功能齐全的免费IDE下载地址VisualStudio2022社区版-下载最新的免费版本VisualStudio2022CommunityEdition–DownloadLatestFreeVersion准备安装选择需要安装的程序安装进行中使用C++学习程序设计相关知识并培......
  • Android实现手电筒demo
    需求:做一个手电筒APK,要求如下:   1:手电筒应用打开后需要有具体的界面打开和关闭按钮。按Home,Recent键保持长亮,按 Back键关闭   2:手电筒的状态必须和下拉栏的手电筒状态一致   3:手电筒打开和关闭,需要有一个弹框提醒用户确认或者取消,弹框风格请自定义vi......
  • IDE-使用阿里云-通义灵码
    什么是通义灵码?通义灵码,是阿里云出品的一款基于通义大模型的智能编码辅助工具,提供行级/函数级实时续写、自然语言生成代码、单元测试生成、代码优化、注释生成、代码解释、研发智能问答、异常报错排查等能力,并针对阿里云的云服务使用场景调优,助力开发者高效、流畅的编码。......
  • node 使用 redlock 分布式锁
    'usestrict';constService=require('egg').Service;constmoment=require('moment');constredis=require('redis');constRedlockClass=require('redlock');const{port,host,password}=require(&#......