网易云课堂-分布式订单号生成策略

订单号要求

  • 全局唯一
  • 长度固定
  • 趋势递增
  • 高并发
  • 高效率(整型、不能太长)

策略一:UUID

  • 缺点:无序、效率低、字符串、过长(占用空间)、可读性差

策略二:数据库自增

  • 自增参数设置
    show varivables like 'auto_inc';
    -- 起始
    set @@auto_increment_offset=2
    -- 步长
    set @@auto_increment_increment=5
    
  • 可通过设置不同数据库自增参数来并发获取订单号
  • 缺点
    • 不利于数据库服务器伸缩(步长限制)
    • 不利于数据迁移

策略三:雪花算法

  • SnowFlake:最原始的版本来源于Twitter,是用Scala实现的。地址为 https://github.com/twitter-archive/snowflake。

  • SnowFlake:是一个64bit的整数分别由四部分组成: 1(最高位固定为0表示整数)+41(时间戳以毫秒为单位)+10(机器编号用来区分不同服务器)+12(序列号,同一毫秒同一机器可支持4095个序列号)。

  • 根据源码可知最后的结果是由时间戳,机器码,工作码,序列数位或运算(|)得到的结果。

    • 时间戳:时间戳等于当前时间戳减去开始计算时间然后左位移偏移量。偏移量等于12+5+5。
    • 机器码:-1L^(-1L <<5L),首先-1左移5位得到的结果再和-1异或计算,得到的结果是31,也就是5位能表达出的最大正整数。然后随机机器码再向左偏移12+5得到机器码。
    • 工作码:工作码和机器码类似,只是最后向左偏移量是5。
    • 序列码:序列是从0开始的自增序列,他是12位的最大整数 4095,从源码可以看出如果是同一毫秒,序列号要自增,如果是新的毫秒序列号要从0开始重新计算。sequence=(sequence+1)&sequenceMask可以保证不管sequence传入多少都能保证最后的结果小于4095,这样可以达到防溢出的效果。
  • 缺点:依赖服务器时间,id递增规律,可能因此泄漏商业机密(根据订单ID猜出订单量);长度长且固定,不容易加入自定义变量

策略四:基于redis自增

  • 思路:利用增长计数API,结合其他信息组成唯一ID
  • Redis的 incr(key) API
  • 缺点:
    • 引入第三方依赖
    • 增加网络开销
    • 服务器成本、维护开销(redis高可用、集群)

总结

  • 没有银弹,根据场景和需求选择合适的,满足KISS原则即可
posted @ 2020-04-26 20:01  杨海星  阅读(598)  评论(0编辑  收藏  举报