13

发号器实践,企业发号器实例--snowflake系列

 4 years ago
source link: https://studygolang.com/articles/28032
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

美团发号器Leaf-snowflake方案

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

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

b500890f770b87ea9a9fa53545b9da4c.png

弱依赖ZooKeeper

除了每次会去ZK拿数据以外,也会在本机文件系统上缓存一个workerID文件。当ZooKeeper出现问题,恰好机器出现问题需要重启时,能保证服务能够正常启动。这样做到了对三方组件的弱依赖。一定程度上提高了SLA

解决时钟问题

因为这种方案依赖时间,如果机器的时钟发生了回拨,那么就会有可能生成重复的ID号,需要解决时钟回退的问题。

UnIRNvB.png!web

参见上图整个启动流程图,服务启动时首先检查自己是否写过ZooKeeper leaf_forever节点:

  1. 若写过,则用自身系统时间与leaf_forever/${self}节点记录时间做比较,若小于leaf\_forever/${self}时间则认为机器时间发生了大步长回拨,服务启动失败并报警。
  2. 若未写过,证明是新服务节点,直接创建持久节点leaf_forever/${self}并写入自身系统时间,接下来综合对比其余Leaf节点的系统时间来判断自身系统时间是否准确,具体做法是取leaf_temporary下的所有临时节点(所有运行中的Leaf-snowflake节点)的服务IP:Port,然后通过RPC请求得到所有节点的系统时间,计算sum(time)/nodeSize。
  3. 若abs( 系统时间-sum(time)/nodeSize ) < 阈值,认为当前系统时间准确,正常启动服务,同时写临时节点leaf_temporary/${self} 维持租约。
  4. 否则认为本机系统时间发生大步长偏移,启动失败并报警。
  5. 每隔一段时间(3s)上报自身系统时间写入leaf_forever/${self}。

由于强依赖时钟,对时间的要求比较敏感,在机器工作时NTP同步也会造成秒级别的回退,建议可以直接关闭NTP同步。要么在时钟回拨的时候直接不提供服务直接返回ERROR_CODE,等时钟追上即可。或者做一层重试,然后上报报警系统,更或者是发现有时钟回拨之后自动摘除本身节点并报警

京东到家发号器方案

EVr6bib.jpg!web

百度发号器方案

UidGenerator是Java实现的, 基于 Snowflake 算法的唯一ID生成器。UidGenerator以组件形式工作在应用项目中, 支持自定义workerId位数和初始化策略, 从而适用于 docker 等虚拟化环境下实例自动重启、漂移等场景。 在实现上, UidGenerator通过借用未来时间来解决sequence天然存在的并发限制; 采用RingBuffer来缓存已生成的UID, 并行化UID的生产和消费, 同时对CacheLine补齐,避免了由RingBuffer带来的硬件级「伪共享」问题. 最终单机QPS可达600万。

vMVr2aV.png!web

RingBuffer环形数组,数组每个元素成为一个slot。RingBuffer容量,默认为Snowflake算法中sequence最大值,且为2^N。可通过 boostPower 配置进行扩容,以提高RingBuffer 读写吞吐量。

Tail指针、Cursor指针用于环形数组上读写slot:

  • Tail指针
    表示Producer生产的最大序号(此序号从0开始,持续递增)。Tail不能超过Cursor,即生产者不能覆盖未消费的slot。当Tail已赶上curosr,此时可通过 rejectedPutBufferHandler 指定PutRejectPolicy
  • Cursor指针
    表示Consumer消费到的最小序号(序号序列与Producer序列相同)。Cursor不能超过Tail,即不能消费未生产的slot。当Cursor已赶上tail,此时可通过 rejectedTakeBufferHandler 指定TakeRejectPolicy

CachedUidGenerator采用了双RingBuffer,Uid-RingBuffer用于存储Uid、Flag-RingBuffer用于存储Uid状态(是否可填充、是否可消费)

由于数组元素在内存中是连续分配的,可最大程度利用CPU cache以提升性能。但同时会带来「伪共享」FalseSharing问题,为此在Tail、Cursor指针、Flag-RingBuffer中采用了CacheLine 补齐方式。

BBVJVnJ.png!web

RingBuffer填充时机

  • 初始化预填充
    RingBuffer初始化时,预先填充满整个RingBuffer.
  • 即时填充
    Take消费时,即时检查剩余可用slot量( tail - cursor ),如小于设定阈值,则补全空闲slots。阈值可通过 paddingFactor 来进行配置,请参考Quick Start中CachedUidGenerator配置
  • 周期填充
    通过Schedule线程,定时补全空闲slots。可通过 scheduleInterval 配置,以应用定时填充功能,并指定Schedule时间间隔

欢迎关注我们的微信公众号,每天学习Go知识

FveQFjN.jpg!web

Recommend

  • 35

    部署环境yuminstall-yncurses-devellibaio-develcmakegccgcc-c++openssl-devellrzszwgetmakeperlautoconfautomakezliblibxmllibgcryptlibtoolbisonmkdir/applicationmkdir-p/home/Ricky/toolsMySQL服务启动用户useradd-s/sbin/

  • 43

  • 23
    • 微信 mp.weixin.qq.com 4 years ago
    • Cache

    发号器:分布式 ID 生成系统

    相关文章:

  • 15

    Dockerfile概述 Dockerfile是docker中镜像文件的的描述文件,说的直白点就是镜像文件到底是由什么东西一步步构成的。 例如:你在淘宝上买了一个衣架,但是卖家并没有给你发一个完整的衣架,而是一些组件和一张图纸,你按照这个图纸一步一步将衣架组装起来,就成了...

  • 3
    • blogread.cn 3 years ago
    • Cache

    用MySQL实现发号器

    您现在的位置:首页 --> MySQL --> 用MySQL实现发号器 用MySQL实现发号器 ...

  • 3
    • segmentfault.com 2 years ago
    • Cache

    Android Flutter 多实例实践

    Android Flutter 多实例实践Flutter CLI 工具支持将 Flutter Module 打包成 Android AAR 包以供外部依赖使用,即 Flutter AAR。在一个没有使用 Flutter 技术栈的 Android 工程中集成 Flutt...

  • 1
    • www.cnblogs.com 2 years ago
    • Cache

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

    分布式 ID 需要满足的条件: 全局唯一:这是最基本的要求,必须保证 ID 是全局唯一的。 高性能...

  • 8

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

  • 3

    使用 Promethues 实现应用监控的一些实践在这篇文章中我们介绍了如何利用 Prometheus 监控应用。在后续的工作中随着监控的深入,我们结合自己的经验和官方文档总结了一些 Metrics 的实践。希望这些实践能给大家提供参考。确定监控...

  • 2

    业务下滑只是一个开始,而不是终点。 这也给了你一个新的机会,重新学习如何运营企业,准备好东山再起。 如果你仔细观察,你会发现,在企业倒闭前几个月,往往会出现一些相关的迹象,包括增长停滞、现金流管理不善、品牌差异化缩小,或明显缺乏创新能...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK