分布式 ID

在庞大复杂的分布式系统中,通常需要对海量数据进行唯一标识,随着数据日渐增长,对数据分库分表以后需要有一个唯一 ID 来标识一条数据,而数据库的自增 ID 显然不能满足需求,此时就需要有一个能够生成全局唯一 ID 的系统,需要满足以下条件:

  • 全局唯一性:最基本的要求就是不能出现重复的 ID。
  • 递增:保证下一个 ID 一定大于上一个 ID。
  • 信息安全:如果 ID 是连续的,用户就可以按照顺序进行恶意爬取数据,所以 ID 生成无规则。

上述的 2 和 3 点需求是互斥的,无法使用同一个方案满足。

解决方案

数据库生成

以 MySQL 为例,利用给字段设置 auto_increment_incrementauto_increment_offset 来实现 ID 自增。每次业务可以使用下列 SQL 进行读写得到 ID:

begin;
REPLACE INTO Tickets64 (stub) VALUES ('a');
SELECT LAST_INSERT_ID();
commit;
  • 优点:使用非常简单,ID 单调递增。
  • 缺点:非常依赖数据库,当数据库异常时则整个系统不可用。

UUID

  • 优点:本地生成,没有网络消耗,性能高。
  • 缺点:过长不易于存储;造成信息不安全,基于 MAC 地址生成可能会造成 MAC 地址泄露。

Snowflake

Snowflake(雪花算法)是由 Twitter 发布的分布式 ID 生成算法,它能够保证不同进程主键的不重复性,以及相同进程主键的有序性。它是通过时间位实现单调递增,且各个服务器如果都做了时间同步,那么生成的 ID 可以认为是总体有序的。

Leaf

Leaf 最早期需求是各个业务线的订单 ID 生成需求。在美团早期,有的业务直接通过数据库自增的方式生成 ID,有的业务通过 Redis 缓存来生成 ID,也有的业务直接用 UUID 这种方式来生成 ID。以上的方式各自有各自的问题,因此决定实现一套分布式 ID 生成服务来满足需求。

Leaf-segment

Leaf-segment 数据库方案,在使用数据库的方案上,做了以下改变:

  • 原方案每次获取 ID 都得读写一次数据库,造成数据库压力大。改为利用 proxy server 批量获取一个 segment 号段,用完之后再去数据库获取新的号段,大大减轻数据库的压力。
  • 各个业务不同的发号需求用 biz_tag 字段来区分,每个 big_tag 的 ID 获取相互隔离互不影响。

优点:

  • Leaf 服务可以很方便的线性扩展,性能完全能够支撑大多数业务场景。
  • ID 是趋势递增的 8 字节的 64 位数字,满足数据库存储的主键要求。
  • 容灾性高:Leaf 服务内部有号段缓存,即使数据库宕机,短时间内仍能可以正常对外提供服务。
  • 可以自定义 max_id 大小。

缺点:

  • ID 不够随机,能够泄露发号数量的信息,不安全。
  • 数据库宕机可能会造成整个系统不可用。
Leaf-snowflake

该方案完全沿用 snowflake 方案设计。对于 workerID 的分配,当服务器集群数量较小的情况下,完全可以手动配置。服务规模较大时,动手配置成本太高,所以使用 Zookeeper 持久顺序节点的特性自动对 snowflake 节点配置。

启动步骤如下:

  1. 启动 Leaf-snowflake 服务,连接 Zookeeper,在 leaf_forever 父节点下检查自己是否已经注册过。
  2. 如果有注册过直接取回自己的 workerID,启动服务。
  3. 如果没有注册过,就在该父节点下面创建一个持久顺序节点,创建成功后取回顺序号当做自己的 workerID 号。

使用 Docker Compose 部署 Leaf

克隆项目

$ git clone https://github.com/antoniopeng/leaf.git
$ cd leaf
$ mvn clean install -DskipTests

构建

$ cd leaf-docker
$ chmod +x build.sh
$ ./build.sh

启动

$ docker-compose up -d

测试

生成地址:http://localhost:8080/api/snowflake/get/test

$ curl http://localhost:8080/api/snowflake/get/test

分布式 ID 解决方案之美团 Leaf的更多相关文章

  1. spring cloud微服务快速教程之(十二) 分布式ID解决方案(mybatis-plus篇)

    0-前言 分布式系统中,分布式ID是个必须解决的问题点: 雪花算法是个好方式,不过不能直接使用,因为如果直接使用的话,需要配置每个实例workerId和datacenterId,在微服务中,实例一般动 ...

  2. 最常用的分布式ID解决方案,你知道几个

    一.分布式ID概念 说起ID,特性就是唯一,在人的世界里,ID就是身份证,是每个人的唯一的身份标识.在复杂的分布式系统中,往往也需要对大量的数据和消息进行唯一标识.举个例子,数据库的ID字段在单体的情 ...

  3. 分布式ID解决方案

    开发十年,就只剩下这套Java开发体系了 >>>   在游戏开发中,我们使用分布式ID.有很多优点 便于合服 便于ID管理 等等 一.单服各自ID系统的弊端 1. 列如合服 在游戏上 ...

  4. 9种分布式ID生成之 美团(Leaf)实战

    整理了一些Java方面的架构.面试资料(微服务.集群.分布式.中间件等),有需要的小伙伴可以关注公众号[程序员内点事],无套路自行领取 更多优选 一口气说出 9种 分布式ID生成方式,面试官有点懵了 ...

  5. 就这?分布式 ID 发号器实战

    分布式 ID 需要满足的条件: 全局唯一:这是最基本的要求,必须保证 ID 是全局唯一的. 高性能:低延时,不能因为一个小小的 ID 生成,影响整个业务响应速度. 高可用:无限接近于100%的可用性. ...

  6. 如何设计一个分布式 ID 发号器?

    大家好,我是树哥. 在复杂的分布式系统中,往往需要对大量的数据和消息进行唯一标识,例如:分库分表的 ID 主键.分布式追踪的请求 ID 等等.于是,设计「分布式 ID 发号器」就成为了一个非常常见的系 ...

  7. 面试总被问分布式ID怎么办? 滴滴(Tinyid)甩给他

    整理了一些Java方面的架构.面试资料(微服务.集群.分布式.中间件等),有需要的小伙伴可以关注公众号[程序员内点事],无套路自行领取 一口气说出 9种 分布式ID生成方式,面试官有点懵了 面试总被问 ...

  8. 分布式ID生成策略之ZK

    import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFra ...

  9. 美团分布式ID生成框架Leaf源码分析及优化改进

    本文主要是对美团的分布式ID框架Leaf的原理进行介绍,针对Leaf原项目中的一些issue,对Leaf项目进行功能增强,问题修复及优化改进,改进后的项目地址在这里: Leaf项目改进计划 https ...

随机推荐

  1. ThinkPHP6 上传图片代码demo

    本文展示了ThinkPHP6 上传图片代码demo, 代码亲测可用. HTML部分代码 <tr> <th class="font-size-sm" style=& ...

  2. 1、struct2第一个项目登陆流程

    这些jar包的作用:第一个日志记录 第二个 使用freemarker制作页面,freemarker和jsp一样都是页面操作的 ognl是struct2提供的向el标签设置的包 struct2-core ...

  3. Socket连接和Http连接

    Socket连接与HTTP连接我们在传输数据时,可以只使用(传输层)TCP/IP协议,但是那样的话,如果没有应用层,便无法识别数据内容,如果想要使传输的数据有意义,则必须使用到应用层协议,应用层协议有 ...

  4. 都在讲DevOps,但你知道它的发展趋势吗?

    根据最近的一项集体研究,DevOps的市场在2017年创造了约29亿美元的产值,预计到2022年,这个数字将达到约66亿美元.人工智能的融入和安全性的融入,加上向自动化的巨大转变,可合理预测,在202 ...

  5. 实战:IDEA运行速度调优

    序言 可能大家觉得系统调优一般都是针对服务端应用而言的,普通Java开发人员很少有机会实践.今天就通用一个Java开发人员日常工作中经常使用的开发工具开做一次调优实战. 我在日常工作中的主要IDE工具 ...

  6. 入门大数据---Python基础

    前言 由于AI的发展,包括Python集成了很多计算库,所以淡入了人们的视野,成为一个极力追捧的语言. 首先概括下Python中文含义是蟒蛇,它是一个胶水语言和一个脚本语言,胶水的意思是能和多种语言集 ...

  7. DOM-BOM-EVENT(7)

    7.事件深入 7.1.事件捕获 事件流分为事件冒泡和事件捕获两种,事件冒泡指事件从里往外传播,而事件捕获刚好相反,指事件从外向內传播 <!DOCTYPE html> <html la ...

  8. 分享一个与jQuery相关的TypeError: $ is not a function问题解决过程

    最近碰到一个比较奇葩的问题,估计很多人也遇到过,就是jQuery可能会遇到的‘$ is not a function’,不过我碰到的这个问题比较怪异,解决该问题也颇费了一番周折,现在给大家分享一下. ...

  9. Netty 源码解析(六): Channel 的 register 操作

    原创申明:本文由公众号[猿灯塔]原创,转载请说明出处标注 今天是猿灯塔“365篇原创计划”第六篇. 接下来的时间灯塔君持续更新Netty系列一共九篇   Netty 源码解析(一 ):开始 Netty ...

  10. 面向对象之继承以及抽象(Java实现)

    回顾封装 关于面向对象三大特性,我们可以很自信的回答:封装.继承.多态 之前学习的封装,可以很直观的理解为了保护数据,我们在idea中可以用alt+insert进行一个选择 constructer构造 ...