美团分布式 ID 框架 Leaf 介绍和使用
一、Leaf
在当今日益数字化的世界里,软件系统的开发已经成为了几乎所有行业的核心。然而,随着应用程序的规模不断扩大,以及对性能和可扩展性的需求不断增加,传统的软件架构和设计模式也在不断地面临挑战。其中一个主要挑战就是如何有效地处理分布式环境中的唯一标识问题。这正是分布式ID
的重要性所在。
分布式ID
的实现方式有多种多样,常见的包括 UUID
、Snowflake
算法、Twitter
的 Snowflake
算法、基于数据库的自增长ID
等。每种方式都有其适用的场景和优缺点。
比如常见的 UUID
, 标准型式包含32
个16
进制数字,以连字号分为五段,形式为8-4-4-4-12
的36
个字符,优点是性能非常高,本地生成,没有网络消耗,但缺点也显而易见,首先不易于存储,UUID
太长,16
字节128
位,通常以36
长度的字符串表示,很多场景不适用。其次信息不安全,基于MAC
地址生成UUID
的算法可能会造成MAC
地址泄露,这个漏洞曾被用于寻找梅丽莎病毒的制作者位置。也不适合作为DB
的主键。MySQL
官方有明确的建议主键要尽量越短越好。
基于数据库的自增长ID
的方式,实现起来非常简单,并且ID是单向自增顺序的,但缺点也很明显,过度依赖于 DB 数据库,在并发量高的情况下数据库成为了性能瓶颈。
基于Snowflake
算法的方式,可以解决上述提到的问题,并且稳定性和灵活性都非常高,但强依赖于机器时钟,如果机器上时钟回拨,会导致发号重复或者服务会处于不可用状态。
既然如此,那下面我们来认识更强大的分布式ID
生成器 Leaf
,它是美团开源的分布式 ID
生成器,旨在解决分布式系统中的唯一标识生成问题,确保在分布式环境下生成的 ID
具有全局唯一性、顺序性和高性能。
Leaf
实现了Leaf-segment
和Leaf-snowflake
两种方案。
Leaf-segment
是一种基于数据库的分布式 ID
生成方案,原始基于数据库的自增长ID
方案,每次获取ID
都得读写一次数据库,造成数据库压力大,该方案利用proxy server
批量获取,每次获取一个segment
(step
决定大小)号段的值。用完之后再去数据库获取新的号段,可以大大的减轻数据库的压力。各个业务不同的发号需求用biz_tag
字段来区分,每个biz-tag
的ID
获取相互隔离,互不影响。如果以后有性能需求需要对数据库扩容,不需要上述描述的复杂的扩容操作,只需要对biz_tag
分库分表就行。
Leaf-snowflake
方案完全沿用snowflake
方案的bit
位设计,对于workerID
的分配,使用Zookeeper
持久顺序节点的特性自动对snowflake
节点配置wokerID
,对于时钟回拨问题,解决方案如下:
更多介绍可以参考官方信息:
官方介绍地址:https://tech.meituan.com/2017/04/21/mt-leaf.html
github:https://github.com/Meituan-Dianping/Leaf.git
下面一起来实践下Leaf
的使用。
首先拉取 Leaf
SpringBoot
封装依赖源码:
git clone -b feature/spring-boot-starter https://github.com/Meituan-Dianping/Leaf.git
cd leaf
使用 Maven
将 Leaf
打到本地仓库中
mvn clean install -Dmaven.test.skip=true
打包成功后,可以创建一个 SpringBoot
项目,在 pom
中加入下面依赖:
<dependency><artifactId>leaf-boot-starter</artifactId><groupId>com.sankuai.inf.leaf</groupId><version>1.0.1-RELEASE</version><exclusions><exclusion><groupId>com.alibaba</groupId><artifactId>druid</artifactId></exclusion><exclusion><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></exclusion></exclusions></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.6</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency>
二、Leaf-segment 方式使用
首先创建leaf
使用的数据库:
CREATE DATABASE leaf
创建ID
规则表:
CREATE TABLE `leaf_alloc` (`biz_tag` varchar(128) NOT NULL DEFAULT '',`max_id` bigint(20) NOT NULL DEFAULT '1',`step` int(11) NOT NULL,`description` varchar(256) DEFAULT NULL,`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`biz_tag`)
) ENGINE=InnoDB;
写入两个 biz_tag
:
insert into leaf_alloc(biz_tag, max_id, step, description) values('test1', 1, 2000, '测试1');
insert into leaf_alloc(biz_tag, max_id, step, description) values('test2', 1, 2000, '测试2');
项目中加入leaf
和数据库配置:
leaf:name: test1segment:enable: trueurl: jdbc:mysql://localhost:3306/leaf?useUnicode=true&characterEncoding=utf8&serverTimezone=GMTusername: rootpassword: root
生成ID
测试:
@Slf4j
@SpringBootTest
class LeafIdApplicationTests {@Resourceprivate SegmentService segmentService;@Testvoid contextLoads() {// 生成 1000 个IDStopWatch sw = new StopWatch();sw.start();for (int i = 0; i < 1000; i++) {long id1 = segmentService.getId("test1").getId();long id2 = segmentService.getId("test2").getId();log.info("id1: {}, id2: {}", id1, id2);}sw.stop();log.info(sw.prettyPrint());}}
可以看到在约 0.178
秒的时间,为两个业务场景生成了 1000
个ID
。
三、Leaf-snowflake 方式使用
这种模式依赖于 Zookeeper
,所以在实验前你需要有一个运行中的 Zookeeper
服务。
这种模式操作ZK
使用 curator
,因此需要引入 curator
的依赖:
<dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>2.12.0</version>
</dependency>
在配置文件中开启Leaf-snowflake
模式:
leaf:name: test1segment:enable: trueurl: jdbc:mysql://localhost:3306/leaf?useUnicode=true&characterEncoding=utf8&serverTimezone=GMTusername: rootpassword: rootsnowflake:enable: trueaddress: 127.0.0.1port: 2181
生成ID
测试:
@Slf4j
@SpringBootTest
class LeafIdApplicationTests {@Resourceprivate SegmentService segmentService;@Resourceprivate SnowflakeService snowflakeService;@Testvoid contextLoads() {// 生成 1000 个IDStopWatch sw = new StopWatch();sw.start();for (int i = 0; i < 1000; i++) {long id1 = snowflakeService.getId("test1").getId();long id2 = snowflakeService.getId("test2").getId();log.info("id1: {}, id2: {}", id1, id2);}sw.stop();log.info(sw.prettyPrint());}}
可以看到相比于上面数据库模式,仅需要约 0.0234105
秒,性能更高,而且做到ID
不是顺序+1
式增长。
相关文章:

美团分布式 ID 框架 Leaf 介绍和使用
一、Leaf 在当今日益数字化的世界里,软件系统的开发已经成为了几乎所有行业的核心。然而,随着应用程序的规模不断扩大,以及对性能和可扩展性的需求不断增加,传统的软件架构和设计模式也在不断地面临挑战。其中一个主要挑战就是如…...

Ubuntu20.04: UE4.27 中 Source Code 的编辑器下拉框没有 Rider选项
问题描述 最近想用 Rider 作为 UE4 开发的 IDE,但安装好 Rider 后,发现编辑器下拉框中没有 Rider 的选项,我检查了 UE4 的插件,发现 Rider Integration 插件已经安装且启用的。 环境:Ubuntu 20.04 UE4.27 Rider2023…...

【论文阅读-PRIVGUARD】Day4:3节
3 PRIVANALYZER:强制执行隐私政策的静态分析 本节介绍PRIVANALYZER,这是一个用于强制执行由PRIVGUARD追踪的隐私政策的静态分析器**。我们首先回顾LEGALEASE政策语言,我们使用它来正式编码政策,然后描述如何静态地强制执行它们**…...

新一代电话机器人开源PHP源代码
使用easyswoole 框架开发的 新一代电话机器人开源PHP源码 项目地址:https://gitee.com/ddrjcode/robotphp 代理商页面演示地址 http://119.23.229.15:8080 用户名:c0508 密码:123456 包含 AI外呼管理,话术管理,CR…...
dockerdocker-copose_限制容器cpu和内存
本文目录 docker的限制方式限制CPU占用限制内存占用 docker-compose docker的限制方式 限制CPU占用 Docker使用--cpus参数来限制容器的CPU资源。该参数指定了分配给容器的CPU核心数量或百分比。 例子:限制CPU使用个数 docker run --cpus2 <imageName>以上…...

【leetcode】圆圈中最后剩下的数字
目录 1. 问题 2. 思路 3. 代码 4. 运行 1. 问题 本题即为典型的约瑟夫问题,通过递推公式倒推出问题的解。原始问题是从n个人中每隔m个数踢出一个人,原始问题变成从n-1个人中每隔m个数踢出一个人…… 示例 1: 输入: n 5, m 3 输出: 3…...
利用python批量将.shp文件转换坐标生成.geojson文件,再将.geojson转换成.csv文件,最后将csv文件插入数据库表
第一步:.shp批量转.geojson # author: JMY # 创建时间: 2024/2/26 17:12 # 批量将.shp文件生成geojson文件并转换坐标为3857import os import geopandas as gpd# 定义输入和输出文件夹路径 input_folder shp文件 output_folder geojson文件# 定义输入和输出坐标系…...

远程服务器Ubuntu 18.04安装VNC远程桌面
一、安装vnc 1.安装图形化界面工具 # 安装过程中会弹窗让选择配置,选lightdm sudo apt install ubuntu-desktop sudo apt-get install gnome-panel gnome-settings-daemon metacity nautilus gnome-terminal 2.安装vnc sudo apt-get install x11vnc3.安装LightD…...
30天自制操作系统(第23天)
23.1 编写malloc 参考第22天的内容,在绘制窗口前先分配了150*50个字节大小的内存,所以导致该文件经编译后有7.6k左右,能否在其中使用指针呢?当需要开辟空间时,移动指针即可。在之前的章节中也有函数memman_alloc函数可…...
基于Rust语言,和WebAssembly技术,与JavaScript结合,的具体应用场景
基于Rust语言与WebAssembly(Wasm)技术并与JavaScript结合,可以应用于多个场景,特别是在需要高性能和/或低级系统访问的情况下。下面是一些具体的应用场景: 性能密集型任务: Rust加上Wasm适合执行计算密集型任务&#x…...

【MATLAB源码-第154期】基于matlab的OFDM系统多径信道下块状和梳妆两种导频插入方式误码率对比仿真。
操作环境: MATLAB 2022a 1、算法描述 OFDM(Orthogonal Frequency Division Multiplexing,正交频分复用)是一种高效的无线信号传输技术,广泛应用于现代通信系统,如Wi-Fi、LTE和5G。OFDM通过将宽带信道划分…...
Linux 下 socket 编程介绍及 TCP 客户端与服务端创建示例
目录 socket 编程接口TCP 服务端TCP 客户端更多内容 本文介绍了 Linux 下的 socket 编程,及总结了使用 socket 接口实现 TCP 服务端和客户端的示例代码。 socket 编程接口 socket() 函数:用于创建一个新的 socket 描述符: int socket(int …...

JetBrains Gateway Github Copilot 客户端插件和主机插件
JetBrains Gateway可以通过插件支持Github Copilot(需另行注册)。 需要安装插件 客户端,而非插件 主机,如图所示: 大概是因为代码显示在客户端(运行在本地的IDE)?...

【web APIs】3、(学习笔记)有案例!
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、概念其他事件页面加载事件元素滚动事件页面尺寸事件 元素尺寸与位置 二、案例举例电梯导航 前言 掌握阻止事件冒泡的方法理解事件委托的实现原理 一、概念…...
使用css reset 还是使用Normalize.css
文章目录 使用css reset 还是使用Normalize.cssCSS Reset:Normalize.css:总结Normalize.css 的使用(例如Vue 3.0 和 Vue CLI 4.x 项目)1.安装2.main.js 中导入3.测试引用是否成功。 使用css reset 还是使用Normalize.css 使用 CSS Reset 还是 Normalize…...
英语中的提问方式(问法)(bug提问、bug描述)
文章目录 英语提问方式一、单词、短语、句子的意思1.1 提问单词的意思1.2 提问短语的意思1.3 提问句子的意思 二、在编程中提问2.1 提问bug2.2 请求代码帮助 如何提出反问句1. 构建反问句的基本结构2. 提问反问句的方法3. 理解反问句的意图 在口语中提问:确保清晰度…...

xss.haozi.me靶机练习
目录 第零关: 第一关: 第二关: 第三关: 第四关: 第五关: 第六关: 第七关: 第八关: 第九关: 第十关: 第十一关: 第十二关…...

2.1 mov、add和sub加减指令实操体验
汇编语言 1. mov操作 1.1 mov移动值 mov指令把右边的值移动到左边 mount c d:masm c: debug r ax 0034 r 073f:0100 mov ax,7t1.2 mov移动寄存器的值 把右边寄存器的值赋值给左边的寄存器 a 073f:0105 mov bx,axt1.3 mov高八位(high)和低八位&am…...

计算机设计大赛 深度学习机器视觉车道线识别与检测 -自动驾驶
文章目录 1 前言2 先上成果3 车道线4 问题抽象(建立模型)5 帧掩码(Frame Mask)6 车道检测的图像预处理7 图像阈值化8 霍夫线变换9 实现车道检测9.1 帧掩码创建9.2 图像预处理9.2.1 图像阈值化9.2.2 霍夫线变换 最后 1 前言 🔥 优质竞赛项目系列,今天要分…...
中间件安全(概述)有中间件的各类链接和官网信息和漏洞库以及配置问题和开源工具
分类主要包括Apache、IIS、Tomcat、weblogic、websphere、Jboss等相关的技术知识和实践。 以Apache为例讲一讲如何保证中间件安全 中间件安全是指保护中间件软件和服务的安全性,防止被恶意攻击或者滥用。中间件软件是指在操作系统和应用程序之间提供通信和集成功能…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...

visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...