分布式 id 生成策略选型

我们一般对分布式id会有什么诉求,一个好的分布式id生成策略,应该具备哪些要素?其实还是由业务决定的(废话,啥不是由业务决定- -!),但一些通用的诉求大致可以总结为以下几点吧:

  1. 全局唯一性:这是最基本的要求。
  2. 信息安全:说到id,我们总会不自觉地想到mysql自增id ,这其实很不安全,一看id就能大致猜测出来我们系统每天的业务量,也容易被暴力穷举。
  3. 高 QPS : 如果因为 id 生成而成为业务的瓶颈,是不是有点尴尬?
  4. 趋势递增:在 MySQL InnoDB 引擎中使用的是聚集索引,用 B-tree 的数据结构来存储索引数据,在主键的选择上面我们应该尽量使用有序的主键保证写入性能。
  5. 高可用 : 如今这年代,高可用是一个永远逃不开的命题,我们应该能在任何时候,都能保证id能被生成出来,局部挂了,不能影响整体服务。
  6. id 生成要尽量少的依赖其他组件:依赖的组件越多,理论上越没法保证高可用(如果依赖组建挂了),也可能意味着你的业务方接入代价会比较高,出错了,排错代价也会比较高

目前市场上流行的方案

UUID

  • 优点:本地生成,没有高可用风险,性能好
  • 缺点:长度过长,存储冗余,且无序不可读,查询效率低

使用MySQL 的 auto_increment

  • 优点:数据库生成的 ID 绝对有序,高可用实现方式简单(使用两台数据库分别设置不同步长,生成不重复 ID 的策略来实现高可用)
  • 缺点:需要独立部署数据库实例,成本高,有性能瓶颈,上面也说过,绝对有序会造成信息安全问题,我们的业务量可猜测,穷举

利用数据库分段批量生成 ID

在上一个方案的基础上,改为利用 proxy server 批量获取,每次获取一个 segment(step 决定大小) 号段的值。用完之后再去数据库获取新的号段,可以大大的减轻数据库的压力

  • 优点:基本同上一个方案,在上一个方案基础上有巨大的性能提升
  • 缺点:也基本上同上一个方案,DB 宕机仍然会造成整个系统不可用。

Redis 生成 ID

Redis 的所有命令操作都是单线程的,本身提供像 incr 和 increby 这样的自增原子命令,所以能保证生成的 ID 肯定是唯一有序的。

  • 优点:数字 ID 天然排序,redis性能也比较好。
  • 缺点:ID 号码不够随机,仍然有安全问题,类似DB方案,仍然强依赖了三方组件 ,如果redis不可用,会影响服务

Twitter 的雪花算法(snowflake)【推荐】

如果大家百度下雪花算法,介绍一大堆。这里仍然作下简要介绍。雪花算法大致来说是一种以划分命名空间来生成 ID 的一种算法,这种方案把 64-bit 分别划分成多段,分开来标示机器、时间等。snowflake 中的 64-bit 分别表示如下图所示:


image.png

41-bit 的时间可以表示(1L<<41)/(1000L360024*365)=69 年的时间,10-bit 机器可以分别表示 1024 台机器。如果我们对 IDC 划分有需求,还可以将 10-bit 分 5-bit 给 IDC,分 5-bit 给工作机器。这样就可以表示 32 个 IDC,每个 IDC 下可以有 32 台机器,可以根据自身需求定义。12 个自增序列号可以表示 2^12 = 4096 个 ID,理论上 snowflake 方案的 QPS 约为 409.6w/s,这种分配方式可以保证在任何一个 IDC 的任何一台机器在任意毫秒内生成的 ID 都是不同的。

  • 优点:基本符合了我们上面提出的各个要求
  1. 毫秒数在高位,自增序列在低位,整个 ID 都是趋势递增的。
  2. 不依赖数据库等第三方系统,生成 ID 的性能也是非常高的。
  3. 可以根据自身业务特性分配 bit 位,非常灵活。
  • 缺点:
  1. 强依赖机器时钟,如果机器上时钟回拨,会导致发号重复或者服务会处于不可用状态。
  2. 分布式情况下,我们需要确定机器的编号,机器量小的情况下,完全可以手工编号,但是有新机器加入,就需要新编号,带来额外工作量,机器多的情况下,手工和配置都是不小的维护量

总结

再回顾开头对分布式id的需求分析,雪花算法综合来说是一个比较优的方案。代码实现也是百度一下一大把,这里贴一个美团点评的实现。核心实现类https://github.com/Meituan-Dianping/Leaf/blob/master/leaf-core/src/main/java/com/sankuai/inf/leaf/snowflake/SnowflakeIDGenImpl.java
对于上面雪花算法的缺点,比如时钟回拨,机器编号等,一些三方优化过的实现版本,都有相应优化,美团也是。比如

  1. 通过弱依赖 zookeeper 解决机器编号问题(启动依赖,得到自己的机器编号后,会缓存。后续 zookeeper 可挂,不影响)
  2. 时钟回拨:通过RPC请求获得集群中各节点的机器时间,取平均值,来判断本节点时钟是否正常,从而做时钟回拨的补偿方案。仔细阅读美团 github 开源的代码,貌似并没有发现类似实现,开源的有阉割?应该是吧。下图大致描述了服务启动流程图


    image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351

推荐阅读更多精彩内容