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

Java 7.3 - 分布式 id

分布式 ID 介绍

什么是 ID?

ID 就是 数据的唯一标识。

什么是分布式 ID?

分布式 ID 是 分布式系统中的 ID,它不存在于现实生活,只存在于分布式系统中。

分库分表:

一个项目,在上线初期使用的是单机 MySQL。但随着需求不断增长,单机 MySQL 已经无法满足当前的需求,我们需要进行分库分表。

分库分表后,数据分布在不同服务器的数据库上,数据库的自增主键无法满足 ID 的唯一性了。此时我们如何为不同的节点生成全局唯一的主键呢?—— 分布式 ID

分布式 ID 需要满足哪些要求?

1、全局唯一

2、高可用:生成分布式 ID 的服务要保证可能性接近 100%

3、高性能:生成速度要快

4、方便易用

以上四点为分布式 ID 的基本要求,一个好的分布式 ID 还需要满足下列需求:

1、安全

2、有序递增

3、有具体的业务含义:生成的 ID 如果能有具体的业务含义,可以让定位问题以及开发更加透明化

4、独立部署:分布式系统专门有一个服务用来生成分布式 ID,可以和业务相关的服务解耦。

分布式 ID 常见的解决方案有哪些?

数据库

数据库主键自增

通过关系型数据库的自增主键来产生唯一 ID

以 MySQL 为例:

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`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

创建一个表,其主键自增。

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

插入数据我们使用 replace into 代替 insert into,解释如下:

这种方式的优缺点——

优点:实现简单

缺点:并发量不大,存在数据库单点问题、ID 没有业务含义、安全问题(通过 ID 自增量来判断每天的订单量)、每次获取 ID 都要访问数据库

数据库号段模式

对于数据库主键自增的方法,每有一个订单就需要访问一次数据库,性能比较差。我们可以通过批量获取,存在内存中,需要用到的时候直接从内存中取即可。

以 MySQL 为例:

1、创建一个数据库表

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`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

current_max_id 和 step 都是用来获取批量 ID,获取的批量 ID 为:current_max_id -- current_max_id + step

version 解决并发问题(乐观锁)

2、插入一行数据

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

3、通过 select 获取指定业务下的批量唯一 ID

SELECT `current_max_id`, `step`,`version` FROM `sequence_id_generator` where
`biz_type` = 101

4、不够用更新后重新 select

UPDATE sequence_id_generator SET current_max_id = 0+100, version=version+1 WHERE
version = 0 AND `biz_type` = 101
SELECT `current_max_id`, `step`,`version` FROM `sequence_id_generator` where
`biz_type` = 101

优缺点 ——

优点:ID 有序递增

缺点:数据库单点问题、ID 没有业务含义、安全问题

NoSQL

一般情况下,NoSQL 方案使用 Redis 多一些。我们通过 Redis 的 incr 命令即可实现对 ID 原子顺序递增。

127.0.0.1:6379> set sequence_id_biz_type 1
OK
127.0.0.1:6379> incr sequence_id_biz_type
(integer) 2
127.0.0.1:6379> get sequence_id_biz_type
"2"

为了提高可用性和并发,我们可以使用 Redis 集群。(Redis Cluster)

优缺点 ——

优点:性能不错且 ID 有序递增

缺点:和数据库主键自增方案缺点类似

算法

UUID

UUID,Universal Unique Identifier(通用唯一标识符)。UUID 包含 32 个 16 进制数字。(8-4-4-4-12)

JDK 提供了现成的生成 UUID 的方法

UUID.randomUUID();

UUID 可以保证唯一性,因为其生成规则包括 MAC 地址、时间戳、名字空间、随机或伪随机数、时序等元素,UUID 不会重复。但虽然 UUID 可以做到全局唯一性,但是我们很少使用它。

UUID 作为 MySQL 主键的时候非常不合适:

1、主键要尽量越短越好

2、UUID 无序,InnoDB 引擎中,数据库主键的无序性会严重影响性能(B+ 树)

UUID 优缺点 —— 

优点:生成速度快、简单易用

缺点:空间消耗大、不安全(MAC 地址泄露)、无序、没有具体业务含义、需要解决重复 ID 问题(机器时间不对的情况下,可能生成重复 ID)

Snowflake(雪花算法)

基于 Snowflake 算法的开源实现,比如美团的 Leaf.

优缺点 ——

优点:生成速度快,ID 有序自增、比较灵活(根据业务加入业务ID)

缺点:需要解决重复 ID 问题(机器时间不对导致重复 ID)

开源框架

UidGenerator

Leaf(团子)

 

Tinyid(滴滴)

 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • QT教程:start()和startTimer()的区别
  • 第五章 Pytorch完成线性回归
  • 小白入门LLM大模型最牛X教程------上交《动手学大模型应用开发》!
  • 语音测试(一)ffmpeg视频转音频
  • 2024年全国大学生数学建模竞赛(A题) 建模解析|“板凳龙” 闹元宵|小鹿学长带队指引全代码文章与思路
  • OpenHarmony轻松玩转GIF数据渲染
  • 语言的自动类型
  • QueryWrapper中的or和and
  • 磁盘加密工具 | VeraCrypt v1.26.15 绿色版
  • STM32基础篇:RTC × Unix时间戳 × BKP
  • [Deepin] 简单使用 RustDesk 实现远程访问Deepin
  • LeetCode 热题100-70 最小栈
  • [数据库][oracle]ORACLE EXP/IMP的使用详解
  • MySQL数据类型-介绍
  • 服务器安装pytorch-阿里云-centos7
  • Apache Zeppelin在Apache Trafodion上的可视化
  • ES6核心特性
  • js ES6 求数组的交集,并集,还有差集
  • JS实现简单的MVC模式开发小游戏
  • Koa2 之文件上传下载
  • Mocha测试初探
  • Python中eval与exec的使用及区别
  • React Transition Group -- Transition 组件
  • Redis 懒删除(lazy free)简史
  • Web标准制定过程
  • 从 Android Sample ApiDemos 中学习 android.animation API 的用法
  • 从PHP迁移至Golang - 基础篇
  • 关于Java中分层中遇到的一些问题
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 力扣(LeetCode)965
  • 聊聊springcloud的EurekaClientAutoConfiguration
  • 手机端车牌号码键盘的vue组件
  • 学习笔记TF060:图像语音结合,看图说话
  • 一道面试题引发的“血案”
  • 一个SAP顾问在美国的这些年
  • 正则表达式
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • $(function(){})与(function($){....})(jQuery)的区别
  • $var=htmlencode(“‘);alert(‘2“); 的个人理解
  • (14)Hive调优——合并小文件
  • (2)Java 简介
  • (9)目标检测_SSD的原理
  • (TOJ2804)Even? Odd?
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (源码分析)springsecurity认证授权
  • (自适应手机端)行业协会机构网站模板
  • ***测试-HTTP方法
  • **PyTorch月学习计划 - 第一周;第6-7天: 自动梯度(Autograd)**
  • .bat批处理(三):变量声明、设置、拼接、截取
  • .NET Core MongoDB数据仓储和工作单元模式封装
  • .NET Core 将实体类转换为 SQL(ORM 映射)
  • .Net OpenCVSharp生成灰度图和二值图
  • .net 后台导出excel ,word
  • .NET 中的轻量级线程安全