首页 > 其他分享 >大厂分布式ID方案之美团Leaf

大厂分布式ID方案之美团Leaf

时间:2024-08-29 14:27:53浏览次数:12  
标签:Leaf 段长度 DB 之美团 snowflake 号段 ID

分布式ID必须保证以下特性:

  • 全局唯一

  • 有序性:便于索引

  • 高并发可用

  • 不依赖中心认证

  • 安全性

目前大厂的分布式ID方案基本都是基于号段式,号段模式可以理解成从数据库批量获取 ID,然后将 ID 缓存在本地,以此来提高业务获取 ID 的效率。例如,每次从数据库获取 ID 时,获取一个号段,如(1,1000],这个范围表示 1000 个 ID,业务应用在请求获取 ID 时,只需要在本地从 1 开始自增并返回,而不用每次去请求数据库,一直到本地自增到 1000 时,才去数据库重新获取新的号段,后续流程循环往复。

美团-Leaf-基于数据库自增ID的优化

Leaf-V1.0

在DB之上挂N个Server,每个Server启动时,都会去DB拿固定长度的ID List。这样就做到了完全基于分布式的架构,同时因为ID是由内存分发,所以也可以做到很高效。接下来是数据持久化问题,Leaf每次去DB拿固定长度的ID List,然后把最大的ID持久化下来,也就是并非每个ID都做持久化,仅仅持久化一批ID中最大的那一个。

上线之后发现的问题:

  • 耗时尖刺,发现系统最大耗时取决于更新号段的时间,造成性能波动

  • 更新号段时DB宕机造成整个服务不可用

  • 可以估计发号数量,估计订单数量,数据细腻系泄漏

Leaf-V2.0-异步更新双Buffer

整体思路其实就是不等消费完毕就去更新号段,预更新的思路。使用缓存解决了耗时尖刺和DB宕机的问题,DB宕机时也预留了一段的重启时间。

  • 每个biz-tag都有消费速度监控,通常推荐segment长度设置为服务高峰期发号QPS的600倍(10分钟),这样即使DB宕机,Leaf仍能持续发号10-20分钟不受影响。

  • 每次请求来临时都会判断下个号段的状态,从而更新此号段,所以偶尔的网络抖动不会影响下个号段的更新。

上线之后发现的问题:号段长度Step不好控制,短了流量激增频繁获取,长了ID跨度很大。

  • 号段长度始终是固定的,假如Leaf本来能在DB不可用的情况下,维持10分钟正常工作,那么如果流量增加10倍就只能维持1分钟正常工作了。

  • 号段长度设置的过长,导致缓存中的号段迟迟消耗不完,进而导致更新DB的新号段与前一次下发的号段ID跨度过大。

Leaf-V2.5-动态调整Step

假设服务QPS为Q,号段长度为L,号段更新周期为T,那么Q * T = L。最开始L长度是固定的,导致随着Q的增长,T会越来越小。但是Leaf本质的需求是希望T是固定的。那么如果L可以和Q正相关的话,T就可以趋近一个定值了。所以Leaf每次更新号段的时候,根据上一次更新号段的周期T和号段长度step,来决定下一次的号段长度nextStep:

  • T < 15min,nextStep = step * 2
  • 15min < T < 30min,nextStep = step
  • T > 30min,nextStep = step / 2

至此,满足了号段消耗稳定趋于某个时间区间的需求。当然,面对瞬时流量几十、几百倍的暴增,该种方案仍不能满足可以容忍数据库在一段时间不可用、系统仍能稳定运行的需求。因为本质上来讲,Leaf虽然在DB层做了些容错方案,但是号段方式的ID下发,最终还是需要强依赖DB。Leaf采用一主二从半同步复制的方案,在极端情况下会超时退化成异步复制,造成ID重复。但是概率非常小

  • 异步复制:性能最高,延迟最低,但数据一致性较弱,适合对延迟敏感且容忍一定数据不一致的场景。
  • 半同步复制:在性能和一致性之间取得平衡,适合希望提高数据安全性但又不能承受完全同步带来的性能损失的场景。
  • 同步复制:提供最强的数据一致性,但对性能有较大影响,通常只在对数据一致性要求极高的情况下使用,但在 MySQL 中不常用。

Leaf-snowflake方案

在之前版本中,可以通过在0点下单和24点下单的ID号推算出美团一天的订单量,这是不能忍受的,于是每天结合雪花算法做出了Leaf-snowflake方案。

Leaf-snowflake方案完全沿用snowflake方案的bit位设计,即是“1+41+10+12”的方式组装ID号。对于workerID的分配,当服务集群数量较小的情况下,完全可以手动配置。Leaf服务规模较大,动手配置成本太高。所以使用Zookeeper持久顺序节点的特性自动对snowflake节点配置wokerID。

也就是说:美团的Leaf-snowflake方案在雪花算法的基础上使用zookeeper解决了自动配置workerID的问题,同时在本地缓存workerID,使之成为弱依赖zookeeper。

在时钟回拨问题上,Leaf-snowflake会上报当前生成ID的最大时间戳到zookeeper(间隔周期3秒),上报时,如果发现当前时间戳少于最后一次上报的时间戳,那么会放弃上报。之所以这么做的原因是,防止在leaf实例重启过程中,由于时钟回拨导致可能产生重复ID的问题。本质就是用zookeeper判断是否发生时钟回拨,所以运行期间还是依赖zookeeper的,zookeeper可以短时间宕机,但是长时间宕机会导致时钟回拨问题无法检测

Leaf并不是全局有序,因为是并发获取,只是单节点有序。

时钟回拨解决的代码:

    //发生了回拨,此刻时间小于上次发号时间
    if (timestamp < lastTimestamp) {
    long offset = lastTimestamp - timestamp;
    if (offset &lt;= 5) {
        try {
            //时间偏差大小小于5ms,则等待两倍时间
            wait(offset &lt;&lt; 1);//wait
            timestamp = timeGen();
            if (timestamp &lt; lastTimestamp) {
               //还是小于,抛异常并上报
                throwClockBackwardsEx(timestamp);
              }    
        } catch (InterruptedException e) {  
           throw  e;
        }
    } else {
        //throw
        throwClockBackwardsEx(timestamp);
    }
}
//分配ID</code></pre>

标签:Leaf,段长度,DB,之美团,snowflake,号段,ID
From: https://www.cnblogs.com/lilizzyy/p/18386592

相关文章

  • Android开发 - “序列化”与“反序列化”解析
    简介序列化和反序列化是计算机科学中两个非常常用的概念。简单来说,它们是将数据转换成不同形式的过程序列化(Serialization)序列化是将对象(比如一个Java对象或一个Python字典)转换成一种可以保存或传输的格式的过程。这种格式通常是字节流或字符串。通过序列化,你可以将一个......
  • OpenCV(cv::idft())
    目录1.函数2.示例3.应用场景4.注意事项5.总结cv::idft()是OpenCV中用于计算逆离散傅里叶变换(IDFT)的函数,它将频域的数据转换回时域。它常与cv::dft()配合使用,例如在进行频域滤波后,需要使用cv::idft()将处理后的数据转换回图像的空间域。1.函数voidcv::idft(......
  • css grid布局实现一个复杂表格
    产品设计了这样一个表格,如下图:当然表格内容格式是固定的,本来想用elementui的,但是思考了一下,用el-table好像嵌套的比较麻烦,还要合并单元格,所以采用了grid布局。废话不多说,直接上代码:<template><divclass="table"><!--表头1--><divclass="th">类型名称<......
  • Android App启动流程
    1.通过Launcher启动应用时,点击应用图标后,Launcher调用startActivity启动应用。 2.LauncherActivity最终调用Instrumentation的execStartActivity来启动应用。 3.Instrumentation调用ActivityManagerProxy(ActivityManagerService在应用进程的一个代理对象)......
  • 结构开发笔记(六):solidworks软件(五):绘制M2x3.0mm螺丝
    前言  绘制36x36方块摄像头模型中的方块摄像头,用到了2个M2x3.0mm螺丝。  本篇描述其详细绘制方法。 绘制螺丝步骤一:绘制螺纹柱  先把螺纹柱体绘制出来,绘制草图    圆直径2mm,高度3.0mm,用螺纹住满足M2x3.0mm。      添加螺纹:    ......
  • Java毕业设计作品:福建厦门城市文化展示系统设计与实现(基于thymeleaf前后端分离 )
      博主介绍:黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。所有项目都配有从入门到精通的基础知识视频课程,学习后应对毕业设计答辩。项目配有对应开发文档、开题报告、任务书......
  • AMD在新的MLPerf基准测试中缩小了与Nvidia的差距
    AMD、UntetherAI、Google、Intel和Nvidia的新基准测试结果显示,AI硅片性能竞争日趋激烈。然而,系统设计、网络和软件使AI大放异彩,而这正是Nvidia的强项。终于,我可以停止抱怨AMD缺乏公开的AI基准测试了。AMD发布了其MI300GPU的优秀MLPerf推理结果,虽然只在一个基准测试上与Nvidi......
  • AI变现之Midjourney头像定制
    前言Midjourney|头像定制1.项目介绍个性化头像在如今的社交媒体时代变得越来越重要。传统头像照片有时显得普通,而AI绘画头像则能为自己的社交账号增加独特性和吸引力。通过AI绘画工具制作头像,可以获得一个充满创意和个性的头像,让自己在社交平台上脱颖而出。2.项目......
  • Android开发 - Parcel 类打包对象数据进行传递解析
    Parcel是什么Parcel是用于对象序列化和反序列化的一个类。通俗地说,它是一种轻量级的容器,常用于打包对象的数据(如基本类型和其他Parcelable对象),使它们能够在不同的组件(如Activity、Service等)之间传递Parcel的主要作用不同的组件(如Activity、Service)之间需要传递数据。......
  • pyspider的安装
    pyspider挺好用,原来用过,最近想用,发现尽管原来的东西还在,可是却安装不起来,最大的原因,是和python版本、各个库的版本的冲突相关。我把我跑通了的相关信息记录一下。1.python 用3.62.pyspider 0.3.83.pycurl 7.43.0.14.flask1.05.wsgidav2.4.1至于async的问题,按照网上教程,对......