Java分布式全局ID(一)

news2024/11/16 23:36:25
随着互联网的不断发展,互联网企业的业务在飞速变化,推动着系统架构也在不断地发生变化。		
如今微服务技术越来越成熟,很多企业都采用微服务架构来支撑内部及对外的业务,尤其是在高
并发大流量的电商业务场景下,微服务更是企业首选的架构模式。随着业务发展壮大,用户量暴
涨,单节点处理能力就会成为瓶颈,如果并发量居高不下,服务器很容易因负载过高而导致崩溃
宕机。出于高并发,高可用的考虑,项目就应该演变到分布式架构了。然而分布式环境下我们又
会面临更多的挑战需要去应对。比如:
	1、分布式系统中接口繁多,重试机制必不可少,接口幂等性问题?
	2、如果下单、付款分布在不同的服务上,如何保证跨服务事务?
	3、高并发场景下资源共享问题?
	4、分库分表后,引发了ID重复问题?
	那么,我们需要如何解决分布式呢?

文章目录

    • 🔥分布式全局唯一ID
    • 🔥分布式全局唯一ID解决方案
    • 🔥什么是雪花算法SonwFlake
    • 🔥雪花算法SonwFlake落地实现
    • 🔥雪花算法SonwFlake落地实现之Mybatis Plus

🔥分布式全局唯一ID

在这里插入图片描述

何为 ID
日常开发中,我们需要对系统中的各种数据使用 ID 唯一表示,比如用户 ID 对应且仅对应一个人,商品 ID 对应且仅对应一件商品,订单 ID 对应且仅对应一个订单。
在这里插入图片描述

为什么需要分布式ID
随着系统数据量越来越大,单数据库压力太大无法维持性能,所以可能就需要变成一主多从这样读写分离,随着继续扩大一主多从也无法支撑了。这时就需要分库分表,这样的话就会出现不同库表之间的数据id不能再依赖数据库自增的id,而需要外部一种方式生成全局统一的唯一id。

在这里插入图片描述

分布式ID需要满足什么条件

在这里插入图片描述

⭐唯一性:全局必须唯一。
⭐高性能:不能在生成id上浪费过多的时间,使其成为功能的性能瓶颈。
⭐高可用:必须保证可用性。
⭐趋势递增:这个不是必须的,但是最好还是满足,因为比如innodb索引就是按照键值排序的,所以有序性可以让维护索引的效率提高。

🔥分布式全局唯一ID解决方案

在这里插入图片描述

UUID
Java本身提供了UUID,这是一个唯一的字符串,它可以不依赖其他工具在本地生成。

优点
⭐代码实现简单
⭐本地生成,没有性能问题
⭐全球唯一的,数据迁移容易
缺点
⭐每次生成的ID是无序的,不满足趋势递增
⭐UUID是字符串,而且比较长,占用空间大,查询效率低
⭐ID没有含义,可读性差

依靠数据库自增字段生成
一个数据库压力大就搞多个数据库,之后搞一个Step步长的概念,每个数据库的自增起始值不同,但是他们的增长Step相同。如下图所示。
在这里插入图片描述

优点
⭐返回的分布式ID是趋势递增的id唯一。解决了单点问题,即使一个宕机其他的还可以提供服务。

缺点
⭐单点压力还是很大,因为DB本身写操作就耗时间。最主要的问题还是扩容困难,比如要加一台DB3是很难加进来的,除非停机,将所有DB的id进行修改,同时修改步长。

号段模式
它没有采用新插入记录返回id的方案,而是一个业务类型就是一行数据,用一行数据来维护这个业务的自增id。服务来修改这行数据的max_id,比如当前max_id值是0,那么来给max_id加上1000,如果返回成功,就代表这个服务获得了1-1000这段分布式id,之后将这段缓存在服务内部,用完之后再来表中取。
在这里插入图片描述

优点
⭐效率很高,db的压力减小,而且一张表可以维护很多业务的分布式id。

缺点
⭐复杂性提高,需要系统为了这个生成方案对号段进行缓存。

Redis自增key方案
通过incr命令让一个key自增,自增后的值作为分布式id。
在这里插入图片描述

优点
⭐有序递增,可读性强
⭐性能较高

缺点
⭐占用带宽,依赖Redis

雪花算法(SnowFlake)

SnowFlake生成的是一个Long类型的值,Long类型的数据占用8个字节,也就是64位。SnowFlake将64进行拆分,每个部分具有不同的含义,当然机器码、序列号的位数可以自定义也可以。
在这里插入图片描述

优点
⭐本地生成,不依赖中间件。
⭐生成的分布式id足够小,只有8个字节,而且是递增的。

缺点
⭐时钟回拨问题,强烈依赖于服务器的时间,如果时间出现时间回拨就可能出现重复的id。

🔥什么是雪花算法SonwFlake

在这里插入图片描述

Snowflake常称为雪花算法,是Twitter开源的分布式ID生成算法,生成后是一个64bit的long型数值,组成部分引入了时间戳,基本保持了自增。

雪花算法作用
⭐生成的所有的id都是随着时间递增
⭐分布式系统内不会产生重复的id

SnowFlake算法优点
⭐高性能高可用:生成时不依赖于数据库,完全在内存中生成
⭐高吞吐:每秒钟能生成数百个的自增ID
⭐ ID自增:存入数据库中,索引效率高

SnowFlake算法的缺点
依赖系统时间,如果系统时间被回调,或者改变,可能会造成ID冲突或者重复

雪花算法组成
在这里插入图片描述

注意:
⭕1位,不用,二进制中的最高位是符号位,1表示负数,0表示正数,由于我们生成的雪花算法都是正整数,所以这里是0 。
⭕41位,这里的时间戳是表示的是从起始时间算起,到生成id时间所经历的时间戳,也就是(当前时间戳-起始时间戳(固定)) 这里一共是41位,范围就是(0~ 2^41-1),这么大的毫秒数转化成时间就是大约69年 。
⭕10位,这里的10位代表工作机器id,一共可以部署在(2^10=1024)台机器上面,10位又可以分为前面五位是数据中心id(0~31),后面五位是机器id(0-31) 。
⭕共12位,序列位,一共可用(0 ~ 2^12-1)共4096个数字。

🔥雪花算法SonwFlake落地实现

在这里插入图片描述

Hutool简介
Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。

引入相关依赖
hutool工具包已经提供雪花算法ID生成的工具类。

<!--
https://mvnrepository.com/artifact/cn.hutool/hu
tool-all -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.7.13</version>
</dependency>

Snowflake
分布式系统中,有一些需要使用全局唯一ID的场景,有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。Twitter的Snowflake 算法就是这种生成器。

//参数1为机器标识
//参数2为数据标识
Snowflake snowflake = IdUtil.getSnowflake(1,
1);
long id = snowflake.nextId();
//简单使用
long id = IdUtil.getSnowflakeNextId();
String id = snowflake.getSnowflakeNextIdStr();

雪花算法SpringBoot引用
config文件

package com.example.demo.config;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.IdUtil;
import lombok.extern.slf4j.Slf4j;
import
org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Slf4j
@Component
public class IdGeneratorSnowflake {
    private long workerId = 0;  //第几号机房
    private long datacenterId = 1;  //第几号机器
    private Snowflake snowflake =
IdUtil.getSnowflake(workerId, datacenterId);
    @PostConstruct  //构造后开始执行,加载初始化工作
    public void init(){
        try{
            //获取本机的ip地址编码
            workerId =
NetUtil.ipv4ToLong(NetUtil.getLocalhostStr());
            log.info("当前机器的workerId: " +
workerId);
       }catch (Exception e){
            e.printStackTrace();
            log.warn("当前机器的workerId获取失败 -
---> " + e);
            workerId =
NetUtil.getLocalhostStr().hashCode();
       }
   }
    /**
分布式全局唯一ID实现_雪花算法SonwFlake落地实现之
Mybatis Plus
初始化工程
     * 生成id
     * @return
     */
    public synchronized long snowflakeId(){
        return snowflake.nextId();
   }
}

🔥雪花算法SonwFlake落地实现之Mybatis Plus

在这里插入图片描述

初始化工程

<dependencies>
        <dependency>
          
<groupId>org.springframework.boot</groupId>
            <artifactId>spring-bootstarter</artifactId>
        </dependency>
        <dependency>
          
<groupId>org.projectlombok</groupId>
 <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-bootstarter</artifactId>
            <version>3.4.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connectorjava</artifactId>
        </dependency>
        <dependency>
          
<groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-startertest</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                  
<groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintageengine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

编写相关配置
application.yml 配置文件中添加 MySQL 数据库的相关配置:

spring.datasource.driver-classname=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.66.1
00:3306/test?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456

开启MapperScan扫描
在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹:

@SpringBootApplication
@MapperScan("com.itbaizhan.sonwflake.mapper")
public class Application {
    public static void main(String[] args) {
      
SpringApplication.run(Application.class,
args);
   }
}

编码
编写实体类 User.java

@Data
public class User {
    @TableId(type = IdType.ASSIGN_ID)// 雪花算法
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

编写Mapper

public interface UserMapper extends
BaseMapper<User> {
}

添加测试类

  @Test
    void createUser() {
        User user = new User();
        user.setName("张三");
        user.setAge(18);
        user.setEmail("23472@qq.com");
        userMapper.insert(user);
   }

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

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

相关文章

[1.#]第一章 计算机系统概述——知识回顾

第一章 计算机系统概述 知识回顾 &#xff08;对于考研408而言&#xff09; 这个章节主要以选择题形式考察。 总的来说&#xff0c;这个章节考察的深度、难度不会太大。另外&#xff0c;这个章节的分值占比是比较低的。 不过&#xff0c;对第一章的学习&#xff0c;有助于我们…

使用 Sublime Text 4 优雅地写C++

使用 Sublime Text 4 优雅地写C 进入sublime官网下载sublime的安装包&#xff08;当然也可以在官网下载页面下载portable版本&#xff0c;不过建议下载默认的setup版本&#xff09; 双击安装包&#xff1a; 应该一会就下载完成了。 此时可以在应用列表看到sublime&#xff1a;…

谈谈 爬虫遇到的 Access denied Error code 1020

这几天在练习爬虫的时候&#xff0c;遇到一个问题&#xff0c; 通过 python 代码从站点中拿到了目标图片的 url &#xff0c; 但是&#xff0c;在持久化到本地时&#xff0c;出现了错误&#xff0c;所有保存下来的图片都报错&#xff1a;文件损坏&#xff0c; 而且&#xff0c;…

【博学谷学习记录】超强总结,用心分享|狂野大数据课程【DataFrame的相关API】的总结分析

操作dataFrame一般有二种操作的方式, 一种为SQL方式, 另一种为DSL方式 SQL方式: 通过编写SQL语句完成统计分析操作DSL方式: 领域特定语言 指的通过DF的特有API完成计算操作(通过代码形式)从使用角度来说: SQL可能更加的方便一些, 当适应了DSL写法后, 你会发现DSL要比SQL更加…

LeetCode:最长回文子串(动态规划)

一、题目 https://leetcode.cn/problems/longest-palindromic-substring/description/ 二、 算法思想 使用动态规划思想解决&#xff0c;如果一个子串是回文的&#xff0c;并且它的左右两边各加上一个字符后仍然是回文的&#xff0c;那么这个子串加上这两个字符后也一定是回文…

浅谈 TCP 握手/数据传输/挥手过程以及 tcpdump 抓包工具使用

前言浅谈 OSITCP三次握手数据传输四次挥手Socket 服务端/客户端通信测试服务端代码客户端代码tcpdump 命令监控命令总结FAQ怎么确认数据包的大小&#xff1f;TCP 拥塞如何避免&#xff1f;如何理解 TCP keep-alive 原理?总结前言 在网络知识体系&#xff0c;TCP 这块的三次握…

【计算机组成原理】指令系统

目录 指令格式 按指令数目分类&#xff1a; 零地址指令 一地址指令 二地址指令 三地址指令 四地址指令 按指令长度分类&#xff1a; 指令字长 机器字长 存储字长 按操作码的长度分类 定长操作码 可变长操作码 定长指令字结构可变长操作码------>拓展操作码指令…

女子举重问题

一、问题的描述 问题及要求 1、搜集各个级别世界女子举重比赛的实际数据。分别建立女子举重比赛总成绩的线性模型、幂函数模型、幂函数改进模型&#xff0c;并最终建立总冠军评选模型。 应用以上模型对最近举行的一届奥运会女子举重比赛总成绩进行排名&#xff0c;并对模型及…

Java分布式事务(二)

文章目录&#x1f525;分布式事务处理_认识本地事务&#x1f525;关系型数据库事务基础_并发事务带来的问题&#x1f525;关系型数据库事务基础_MySQL事务隔离级别&#x1f525;MySQL事务隔离级别_模拟异常发生之脏读&#x1f525;MySQL事务隔离级别_模拟异常发生之不可重复读&…

信息安全与数学基础-笔记-②同余

知识目录同余完全剩余系剩余类完全剩余系❀简化剩余系❀欧拉函数逆元&#xff01;欧拉定理 &#xff01;同余 a,b 两个数字&#xff0c;都模m&#xff0c;当两个数字模m后余的数一样即为同余。 例子&#xff1a; a bq r (mod m)&#xff0c;这里的a 和 r 就是同余 &#xff…

如何使用Unity3d实现多人对战联机游戏

所需资源 课程来源&#xff08;请支持正版课程&#xff09; 安装Unity Hub 安装Visual Studio 角色模型 环境准备 ①Unity设置 不设置的话编写有些代码没有自动补全 点开 Preferences 选择 visual studio ②角色导入 点击 windows—>Package Manager 左上角 My Ass…

数据结构与算法(七):排序算法

排序算法是《数据结构与算法》中最基本的算法之一&#xff0c;排序算法可以分为内部和外部排序。 内部排序&#xff1a;数据记录在内存中进行排序。 外部排序&#xff1a;因排序的数据很大&#xff0c;一次不能容纳全部的排序记录&#xff0c;在排序过程中需要访问外存。 常…

xgboost:分割Sparsity-aware Split Finding

Sparsity-aware Split Finding1 在许多现实问题中&#xff0c;输入xxx是稀疏的是很常见的。造成稀疏性的可能原因有很多: 1)数据中存在缺失值&#xff1b; 2)统计中频繁出现零项&#xff1b; 3)特征工程的处理结果&#xff0c;如独热编码。 重要的是使算法意识到数据中的稀…

RocketMQ5.1.0单机安装与启动

RocketMQ单机安装与启动系统要求下载地址安装步骤RocketMq启动NameServer查看是否启动成功启动BrokerProxy查看是否启动成功修改tool.sh测试消息产生消息的消费关闭服务器系统要求 下载地址 官网下载地址 二进制包是已经编译完成后可以直接运行的&#xff0c;源码包是需要编译…

javaWeb核心02-RequestResponse

文章目录Request&Response1&#xff0c;Request和Response的概述2&#xff0c;Request对象2.1 Request继承体系2.2 Request获取请求数据2.2.1 获取请求行数据2.2.2 获取请求头数据2.2.3 获取请求体数据2.2.4 获取请求参数的通用方式基于上述理论&#xff0c;request对象为我…

python:使用 Jupyter notebook(测试 matplotlib 和 opencv)

环境&#xff1a; window1python 3.10.6 参考&#xff1a; https://jupyter.org/https://opencv.org/ 一、创建虚拟环境 这个步骤可以跳过&#xff08;因为笔者不喜欢在全局环境安装任何东西&#xff0c;所以搞一个新环境&#xff09;。 先选中一个目录&#xff1a;D:\jackl…

论文笔记 | Conducting research in marketing with quasi-experiments

这篇论文是Journal of Marketing上的论文&#xff0c;讲了使用准实验来进行论文研究的一些事项。外生性识别的来源、几种准实验方法的注意点还有内生性的解决。 这篇论文对于准实验或者是平常论文的展开有一个非常友善的指导功能&#xff0c;可以阅读~ 摘要&#xff1a;本文旨…

多线程实现的三种方法、线程名称的获取

文章目录多线程实现的三种方法1、通过继承Thread&#xff0c;并重写里面的run()方法2、实现Runnable接口&#xff0c;并重写其中run()方法将runnable类传递给Thread类中3、实现Callable接口&#xff0c;重写其中的call()方法Callable接口时有泛型的&#xff0c;该泛型值call()方…

字符串模式匹配,经典KMP算法你还不会?我可不允许你不会!

文章目录重点1. 简单模式匹配算法2. 部分匹配值PM的算法&#xff08;Move j-1 PM[j-1]&#xff09;3. 部分匹配值PM的两次改进&#xff08;Move j-next[j]&#xff09;4. 快速得到next数组5. KMP匹配算法重点 童鞋们看网上讲解的时候一定要分清楚序列是从0开始还是从1开始&…

大数据框架之Hive:第1章 Hive入门

1.1 什么是Hive 1&#xff09;Hive简介 Hive是由Facebook开源&#xff0c;基于Hadoop的一个数据仓库工具&#xff0c;可以将结构化的数据文件映射为一张表&#xff0c;并提供类SQL查询功能。 那为什么会有Hive呢&#xff1f;它是为了解决什么问题而诞生的呢&#xff1f; 下…