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

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);@Autowiredprivate SegmentService segmentService;@Overridepublic ServerResponseEntity<Long> getSegmentId(String key) {//通过不同服务的key获取分布式idreturn 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) {// 如果找到了缓存中的SegmentBufferif (buffer.isInitOk()) {// 检查SegmentBuffer是否已成功初始化synchronized (buffer) {// 同步块,确保线程安全if (buffer.isInitOk()) {// 再次检查SegmentBuffer是否已成功初始化try {// 尝试从数据库中更新SegmentBufferupdateSegmentFromDb(key, buffer.getCurrent());logger.info("Init buffer. Update leafkey {} {} from db", key, buffer.getCurrent());// 更新成功后,将SegmentBuffer的初始化标志设置为truebuffer.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.mzph.cn/news/116382.shtml

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

相关文章

Node学习笔记之path模块

path 模块提供了 操作路径 的功能&#xff0c;我们将介绍如下几个较为常用的几个 API&#xff1a; API 说明 path.resolve 拼接规范的绝对路径常用 path.sep 获取操作系统的路径分隔符 path.parse 解析路径并返回对象 path.basename 获取路径的基础名称 path.dirname…

【深度学习】数据集最常见的问题及其解决方案

简介 如果您还没有听过&#xff0c;请告诉您一个事实&#xff0c;作为一名数据科学家&#xff0c;您应该始终站在一个角落跟你说&#xff1a;“你的结果与你的数据一样好。” 尝试通过提高模型能力来弥补糟糕的数据是许多人会犯的错误。这相当于你因为原来的汽车使用了劣质汽…

SL8541 android系统环境+编译

1.Ubuntu系统的安装 最好使用ubuntu18.0.4 2.工具环境包的安装 // 安装Android8.1源码编译环境 sudo apt-get install openjdk-8-jdk --------------ok sudo apt-get install libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-dev g-multilib --------------ok sudo…

nrf52832 PWM配置

PWM使用时sdk_config.h文件中配置如下:#define PWM_ENABLED 1 sdk_config.h 文件中添加下列配置 // <e> NRFX_PWM_ENABLED - nrfx_pwm - PWM peripheral driver // #ifndef NRFX_PWM_ENABLED #define NRFX_PWM_ENABLED 0 #endif // <q> NRFX_PWM0_ENABLED - Enab…

USGS MODIS 蒸散量数据集

USGS MODIS 蒸散量 这里提供的蒸散量 (ET) 数据集是遥感技术的结果&#xff0c;主要利用 MODIS 热图像和全球天气数据集。该数据集对应于 Climate Engine 使用的全球 ET 产品的第 5 版。它为 2003 年至 2023 年期间的 ET 时空动态提供了宝贵的见解。该数据集的基石是可操作的简…

【自动化测试入门】用Airtest - Selenium对Firefox进行自动化测试(0基础也能学会)

1. 前言 本文将详细介绍如何使用AirtestIDE驱动Firefox测试&#xff0c;以及脱离AirtestIDE怎么驱动Firefox&#xff08;VScode为例&#xff09;。看完本文零基础小白也能学会Firefox浏览器自动化测试&#xff01;&#xff01;&#xff01; 2. 如何使用AirtestIDE驱动Firefox…

五个步骤轻松搞定软件开发流程

互联网在当今社会非常普遍&#xff0c;日常生活中很多东西都离不开互联网&#xff0c;应用软件是互联网必不可少的载体和终端。因此&#xff0c;软件是互联网中不可缺少的关键因素。软件开发已经成为许多企业和企业家非常重要的布局。在软件开发之前&#xff0c;我们应该了解软…

Kafka3.x安装以及使用

一、Kafka下载 下载地址&#xff1a;https://kafka.apache.org/downloads 二、Kafka安装 因为选择下载的是 .zip 文件&#xff0c;直接跳过安装&#xff0c;一步到位。 选择在任一磁盘创建空文件夹&#xff08;不要使用中文路径&#xff09;&#xff0c;解压之后把文件夹内容剪…

如何在 Azure 容器应用程序上部署具有 Elastic Observability 的 Hello World Web 应用程序

作者&#xff1a;Jonathan Simon Elastic Observability 是提供对正在运行的 Web 应用程序的可见性的最佳工具。 Microsoft Azure 容器应用程序是一个完全托管的环境&#xff0c;使你能够在无服务器平台上运行容器化应用程序&#xff0c;以便你的应用程序可以扩展和缩减。 这使…

ImportError: DLL load failed while importing MPI: 找不到指定的模块

在运行下面这行python代码时会报错 from mpi4py import MPI 原因就是缺少MPI模块 解决方法如下&#xff1a; 1.在MPI官网下载msmpisetup.exe和msmpisdk.msi两个文件&#xff0c;并且安装到默认路径下 2.添加环境变量 进入“控制面板——>高级系统设置——>环境变量”…

设计模式:抽象工厂模式(C#、JAVA、JavaScript、C++、Python、Go、PHP)

上一篇《工厂方法模式》 下一篇《单例模式》 简介&#xff1a; 抽象工厂模式&#xff0c;它是所有形态的工厂模式中最为抽象和最具一般性的一种形态。它用于处理当有多个抽象角色时的情况。抽象工厂模式可以向…

Linux备份Docker的mysql数据并传输到其他服务器保证数据级容灾

目录 简介什么是容灾 &#xff1f;容灾的分类容灾和备份有什么连系 &#xff1f; 数据级容灾备份步骤1、scp命令&#xff1a;用于Linux之间复制文件和目录2、编写备份数据库脚本3、crontab定时任务执行脚本4、测试 应用级容灾业务级容灾 简介 为了防止客户系统的数据丢失&…

【Python爬虫】安装requests库解决报错问题

requests 确保pip的安装命令行下安装出现的问题以及解决办法换镜像源安装验证安装为什么使用requests库呢 废话不多说了&#xff0c;直接进入正题 确保pip的安装 首先要想安装requests库&#xff0c;第一点就是要确保pip已经安装。这个pip在Python高级版本中已经默认安装了。…

基于蝗虫算法的无人机航迹规划-附代码

基于蝗虫算法的无人机航迹规划 文章目录 基于蝗虫算法的无人机航迹规划1.蝗虫搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用蝗虫算法来优化无人机航迹规划。 1.蝗虫搜索算法 …

进阶JAVA篇-深入了解 List 系列集合

目录 1.0 List 类的说明 1.1 List 类的常用方法 1.2 List 集合的遍历方式 2.0 ArrayList 集合的底层原理 2.1 从 ArrayList 集合的底层原理来了解具有该特性的原因&#xff1a; 2.2 ArrayList 集合的优缺点 3.0 LinkedList 集合的底层原理 3.1 从 LinkedList 集合的底层原理来了…

中心胖AP(AD9430DN)+远端管理单元RU(R240D)+出口网关,实现组网

适用于&#xff1a;V200R008至V200R019C00版本的万兆中心胖AP&#xff08;AD9431DN-24X&#xff09;。 组网规划 RU管理&#xff1a;VLAN 100&#xff0c;网段为192.168.100.0/24。 无线业务&#xff1a;VLAN 3&#xff0c;SSID为“wlan-net”&#xff0c;密码为“88888888”…

怎么下载微信视频号视频?

你是否曾经在浏览视频号时看到了一些精彩的视频号&#xff0c;希望能够保存下来&#xff0c;但却不知道如何下载&#xff1f;别担心&#xff01;本篇文章将为你介绍一个方便易用的视频号下载工具&#xff0c;让你轻松保存喜欢的视频号视频&#xff01;犀牛下载是一款专门为微信…

05 | 类型匹配:怎么切除臃肿的强制转换

Java 的模式匹配是一个新型的、而且还在持续快速演进的领域。类型匹配是模式匹配的一个规范。类型匹配这个特性&#xff0c;首先在 JDK 14 中以预览版的形式发布。在 JDK 15 中&#xff0c;改进的类型匹配再次以预览版的形式发布。最后&#xff0c;类型匹配在 JDK 16 正式发布。…

电子画册如何制作,教你几分钟简单上手制作?

电子画册不同于纸质画册&#xff0c;它可以不受时间、空间及地域的限制&#xff0c;以更直观、新颖的形式展示在读者面前&#xff0c;还能快速传播效益。所以&#xff0c;当下&#xff0c;越来越多人想要用电子画册来传递内容信息。 如何制作电子画册&#xff1f;其实只要使用…

Python 框架学习 Django篇 (五) Session与Token认证

我们前面经过数据库的学习已经基本了解了怎么接受前端发过来的请求&#xff0c;并处理后返回数据实现了一个基本的登录登出效果&#xff0c;但是存在一个问题&#xff0c;我们是将所有的请求都直接处理了&#xff0c;并没有去检查是否为已经登录的管理员发送的&#xff0c;如果…