【SpringCloud微服务项目实战-mall4cloud项目(5)】——mall4cloud-leaf

news2024/12/24 2:42:17

mall4cloud-leaf 基于美团leaf的生成id服务

  • 分布式id介绍
  • 具体代码及使用
    • 项目中的生成id模式
    • 具体代码
    • 分布式id生成使用

分布式id介绍

分布式ID(Distributed ID)是在分布式计算环境中生成的唯一标识符或标识号。在分布式系统中,通常需要唯一标识不同的实体或数据,以确保数据的一致性、唯一性和跟踪性。分布式ID的生成可以避免多个节点或服务生成相同的标识符,从而避免数据冲突和不一致性。
在这里插入图片描述

分布式ID的好处包括:

唯一性:分布式ID是全局唯一的,无论在系统中的哪个节点生成,都不会与其他节点的ID冲突。
数据一致性:分布式ID可用于唯一标识数据库中的记录,确保不同节点的数据操作不会导致冲突或数据不一致性。
分布式系统中的跟踪:通过在分布式系统中的操作和事件中使用唯一ID,可以轻松跟踪和审计系统中发生的事情,有助于故障排除和性能分析。
降低数据库压力:分布式ID生成可以减少对数据库的写入压力,因为不需要立即查询数据库以获取唯一ID。这有助于提高性能。
去中心化:使用分布式ID生成服务,而不是依赖于中心化的ID生成器,有助于降低单点故障的风险。
提高性能:分布式ID生成服务通常经过优化,可以提供高性能的ID生成,适用于高吞吐量的应用程序。通过使用Leaf服务生成唯一ID,可以减少对数据库的写入请求,因为不再需要插入数据后立即查询以获取生成的ID。

美团Leaf的实现方式可以基于Twitter Snowflake算法,它的主要组成部分包括:

时间戳:Leaf服务使用时间戳来确保生成的ID在一定时间内是唯一的。时间戳通常占据了ID的高位,以确保生成的ID是递增的。
数据中心ID:数据中心ID是一个数字,用于标识不同的数据中心。在大型分布式系统中,可能存在多个数据中心,每个数据中心中的节点需要具有唯一的数据中心ID。这有助于确保生成的ID不会与其他数据中心中的ID冲突。通常,数据中心ID是分配给数据中心的唯一标识符,如数字1、2、3等。
机器节点ID:机器节点ID用于在同一数据中心内标识不同的节点或服务器。每个节点都应具有唯一的机器节点ID,以防止在同一数据中心内的不同节点生成ID时出现冲突。通常,机器节点ID是分配给机器或节点的唯一标识符
序列号:序列号部分用于解决同一毫秒内的ID冲突。当在同一毫秒内多次请求ID时,序列号递增以确保ID的唯一性。

也可以基于数据库方式生成,项目中使用的是该方式:

具体代码及使用

项目中的生成id模式

在本项目中,使用的是Leaf-segment号段模式,该模式是对直接用数据库自增ID充当分布式ID的一种优化,减少对数据库的频率操作。相当于从数据库批量的获取自增ID,每次从数据库取出一个号段范围,例如 (1,1000] 代表1000个ID,业务服务将号段在本地生成1~1000的自增ID并加载到内存。

由于号段模式依赖于数据库表,我们先看一下相关的数据库表:
在这里插入图片描述
biz_tag:针对不同业务需求,用biz_tag字段来隔离,如果以后需要扩容时,只需对biz_tag分库分表即可
max_id:当前业务号段的最大值,用于计算下一个号段
step:步长,也就是每次获取ID的数量
random_step: 每次getid时随机增加的长度
之后在nacos的配置,只需连接数据库即可。

具体代码

在代码中,leaf作为一个独立的服务,获取id时都是通过fegin调用的。所以主要代码如下:

@FeignClient(value = "mall4cloud-leaf",contextId ="segment")
public interface SegmentFeignClient {

	/**
	 * 获取id
	 * @param key
	 * @return
	 */
	@GetMapping(value = FeignInsideAuthConfig.FEIGN_INSIDE_URL_PREFIX + "/insider/segment")
	ServerResponseEntity<Long> getSegmentId(@RequestParam("key") String key);


}

在这里插入图片描述

@RestController
public class SegmentFeignController implements SegmentFeignClient {

	private static final Logger logger = LoggerFactory.getLogger(SegmentFeignController.class);


	@Autowired
	private SegmentService segmentService;

	@Override
	public ServerResponseEntity<Long> getSegmentId(String key) {
		//通过不同服务的key获取分布式id
		return ServerResponseEntity.success(get(key, segmentService.getId(key)));
	}


	private Long get(String key, Result id) {
		Result result;
		if (key == null || key.isEmpty()) {
			throw new NoKeyException();
		}
		result = id;
		if (Objects.equals(result.getStatus(), Status.EXCEPTION)) {
			throw new LeafServerException(result.toString());
		}
		return result.getId();
	}
}

封装的fegin方法中,主要就是通过key去获取id,这个key就是表中的biz_tag。下面看一下leaf的具体代码。

@Override
public Result get(final String key) {
    // 检查初始化是否成功
    if (!initOk) {
        // 如果初始化失败,返回异常结果
        return new Result(EXCEPTION_ID_IDCACHE_INIT_FALSE, Status.EXCEPTION);
    }
    
    // 从缓存中获取名为 'key' 的SegmentBuffer对象
    SegmentBuffer buffer = cache.get(key);
    
    if (buffer != null) {
        // 如果找到了缓存中的SegmentBuffer
        if (buffer.isInitOk()) {
            // 检查SegmentBuffer是否已成功初始化

            synchronized (buffer) {
                // 同步块,确保线程安全

                if (buffer.isInitOk()) {
                    // 再次检查SegmentBuffer是否已成功初始化
                    try {
                        // 尝试从数据库中更新SegmentBuffer
                        updateSegmentFromDb(key, buffer.getCurrent());
                        logger.info("Init buffer. Update leafkey {} {} from db", key, buffer.getCurrent());
                        // 更新成功后,将SegmentBuffer的初始化标志设置为true
                        buffer.setInitOk(true);
                    }
                    catch (Exception e) {
                        // 如果更新出现异常,记录警告日志
                        logger.warn("Init buffer {} exception", buffer.getCurrent(), e);
                    }
                }
            }
        }
        // 从SegmentBuffer中获取ID并返回
        return getIdFromSegmentBuffer(cache.get(key));
    }
    
    // 如果未找到名为 'key' 的SegmentBuffer,返回异常结果
    return new Result(EXCEPTION_ID_KEY_NOT_EXISTS, Status.EXCEPTION);
}

这段代码来自类SegmentIDGenImpl,后面我们加一篇对于leaf的源码分析文章。

分布式id生成使用

我们请求一个注册用户的接口,之后通过fegin调用leaf接口产生用户id。
在这里插入图片描述
可以看到,产生的id是106806。
之后向下请求,它产生的id是上一个id增加(1~10)之间的随机数产生的数字,和数据表中的random_step字段对应。

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

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

相关文章

Vcenter实战利用方式总结

目录 0x01 指纹特征 0x02 查看Vcenter版本 0x03 CVE-2021-21972 0x04 CVE-2021-22005 0x05 CVE-2021-44228 0x06 获取vcenter-web控制台权限 重置密码 cookie登录 不重置获取密码&#xff08;ESXI&#xff09; 1、获取解密key 2、获取数据库账号密码 3、使用脚本解…

PHP 函数、PHP 简单后门

函数 基本结构 语法结构 function 函数名(形式参数1,形式参数2...){//函数体return 返回值 }定义并执行一个简单函数 // funtion.phpfunction test(){echo "This is function ".__FUNCTION__; }test();函数传参 // function.phpfunction add($x, $y){$sum $x …

JAVA-编程基础-11-03-java IO 字节流

Lison <dreamlison163.com>, v1.0.0, 2023.05.07 JAVA-编程基础-11-03-java IO 字节流 文章目录 JAVA-编程基础-11-03-java IO 字节流字节输出流&#xff08;OutputStream&#xff09;FileOutputStream类**FileOutputStrea 的构造方法**使用文件名创建FileOutputStream…

【RocketMQ系列十三】RocketMQ的集群核心概念之消费重试死信队列幂等消息的出现以及处理

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精…

基于拦截器Interceptor实现简易权限控制及行为记录功能

一、业务需求 使用拦截器(Interceptor)&#xff0c;实现Controller中方法的权限控制&#xff0c;并记录访问行为。要求仅在Controller方法上加注解&#xff0c;就可以实现权限控制。具体为&#xff1a; 1、拦截未登录用户的访问&#xff1b; 2、拦截不具有权限用户的访问&#…

ASPICE标准快速掌握「3.1. 实践示例」

实践示例 本章内容是最重要的,建议慢下来跟着博主的思路一步一步前进 1. 示例背景说明 假设我们现在是一个Tier1的车窗控制软件开发商,我们给OEM提供软件解决方案 1.1. 本过程目标 根据客户、上级部门、安全团队与质量团队等提出的要求,本项目要求SYS.1过程达到ASPICE过…

【源码】C/C++学生信息管理系统 1024程序员节日快乐

文章目录 题目介绍源码效果展示报告内容 更多源码&#xff1a; 点我跳转目录 题目介绍 1024程序员节日快乐! 使用语言&#xff1a; 此源码包含两个版本: 版本1&#xff1a;C语言 版本2&#xff1a; C 代码量&#xff1a; 650 题目&#xff1a; 学生信息管理系统&#xff0c; …

JAVA-编程基础-11-04-java IO 字符流

Lison <dreamlison163.com>, v1.0.0, 2023.05.07 JAVA-编程基础-11-04-java IO 字符流 文章目录 JAVA-编程基础-11-04-java IO 字符流字符流Reader 和 Writer字符输入流&#xff08;Reader&#xff09;**FileReader构造方法****FileReader读取字符数据** 字符输出流&am…

解决样本不均衡问题

一、样本不均衡问题 样本&#xff08;类别&#xff09;不平衡指的是分类任务中不同类别的训练样例数目差别很大的情况&#xff0c;一般地&#xff0c;样本类别比例&#xff08;多数类VS少数类&#xff09;明显大于1&#xff1a;1&#xff08;例如4&#xff1a;1&#xff09;就…

软考信息安全工程师备考

软考信息安全工程师备考 报名 公告地址 通知是否有考试和考试安排的公告 https://www.ruankao.org.cn/arrange报名地址 https://bm.ruankao.org.cn/sign/welcome刷题 51cto刷题小程序 5cto题库点击进去选择信息安全工程师 可以刷选择题和大题 还可以刷真题非常好用 …

Mysql数据库指定某数据库或某表赋予增删改查操作权限各类划分权限的方法总结实战

一、mysql创建用户只赋予指定数据库的增删改查操作权限 在日常生产运维工作中&#xff0c;我们经常需要给其他厂商或者合作伙伴提供数据库的账号&#xff0c;并且需要指定某个用户只能查询指定的数据库&#xff0c;并且赋予增删改查的指定权限。 &#xff08;1&#xff09;创…

面试算法38:每日温度

题目 输入一个数组&#xff0c;它的每个数字是某天的温度。请计算每天需要等几天才会出现更高的温度。例如&#xff0c;如果输入数组[35&#xff0c;31&#xff0c;33&#xff0c;36&#xff0c;34]&#xff0c;那么输出为[3&#xff0c;1&#xff0c;1&#xff0c;0&#xff…

软硬件架构分层总结

一、前言 软件系统很多架构图我们经常看到是这样的三段 就是这三段就可以演化出很多层 二、硬件架构分层 硬件层&#xff0c;基本是计算机硬件的体系结构&#xff0c;包括硬盘设备&#xff0c;cpu&#xff0c;内存&#xff0c;控制器&#xff0c;运算器&#xff0c;寄存器&am…

清除excel中换行符方法

1、选择要删除或替换换行符的单元格。 2、按 Ctrl H 以打开“查找和替换”对话框。 3、在“查找内容”栏中输入Ctrl J 或 Ctrl Enter 这时会出现一个闪烁的小点。如下图所示&#xff0c;然后点击全部替换即可。

【机器学习合集】参数初始化合集 ->(个人学习记录笔记)

文章目录 综述1. 全零与随机初始化2. 标准初始化(固定方差)3. Xavier初始化(方差缩放)4. He初始化5. 正交初始化6. MSRA初始化 综述 这些是不同的权重初始化方法&#xff0c;用于初始化神经网络的权重参数。它们的主要区别在于初始化权重的策略和数学原理。以下是这些初始化方法…

RTI-DDS代码分析使用介绍

DDS(Data Distribution Service数据分发服务)是对象管理组织OMG的有关分布式实时系统中数据发布的规范。 DDS规范采用了发布/订阅体系结构&#xff0c;但对实时性要求提供更好的支持。DDS是以数据为中心的发布/订阅通信模型。 以下工程基于rti_connext_dds-7.2.0 hello_world.…

Spark简单回顾

星光下的赶路人star的个人主页 大鹏一日同风起&#xff0c;扶摇直上九万里 文章目录 1、Spark1.1 Spark入门1.1.1 Spark部署模式1.1.2 常用端口 1.2 SparkCore1.2.1 RDD不可变和五大属性1.2.2 RDD的弹性1.2.3 cache和Checkpoint的区别1.2.4 算子 1.3 SparkSQL1.4 内核1.4.1提交…

在Linux上安装RStudio工具并实现本地远程访问【内网穿透】

文章目录 前言1. 安装RStudio Server2. 本地访问3. Linux 安装cpolar4. 配置RStudio server公网访问地址5. 公网远程访问RStudio6. 固定RStudio公网地址 前言 RStudio Server 使你能够在 Linux 服务器上运行你所熟悉和喜爱的 RStudio IDE&#xff0c;并通过 Web 浏览器进行访问…

音频怎么录制?让你轻松成为录音专家!

“音频可以录制吗&#xff1f;如果可以那应该怎么去操作呢&#xff1f;参加了一个配音比赛&#xff0c;需要录制自己配音的视频&#xff0c;但是我不懂怎么录制音频&#xff0c;眼看比赛就要截止了&#xff0c;真的很着急&#xff0c;大家帮帮我。” 音频录制是一项常见但强大…

【数据结构初阶】算法的时间复杂度和空间复杂度

算法的时间复杂度和空间复杂度 1.算法效率1.1 如何衡量一个算法的好坏1.2 算法的复杂度 2.时间复杂度2.1 时间复杂度的概念2.2 大O的渐进表示法2.3常见时间复杂度计算举例 3.空间复杂度4. 常见复杂度对比 1.算法效率 1.1 如何衡量一个算法的好坏 如何衡量一个算法的好坏呢&am…