关于分布式系统:探究分布式全局唯一Id生成器

2次阅读

共计 1903 个字符,预计需要花费 5 分钟才能阅读完成。

原文首发于我的博客:https://kaolengmian7.com/post…

PC 端拜访我的博客能够取得最优质的浏览体验同时也能够翻阅我的其余博文。

分布式全局惟一 Id 生成器有啥用?

首先咱们有一个共识,那就是咱们的业务零碎大量用到惟一 Id,比方电商零碎的订单、内容社区的帖子等等。在大部分传统场景中,咱们依赖 Mysql 存储数据,并依附 Mysql 的自增 Id 来取得一个惟一 Id。

如果某个场景咱们无奈依赖 Mysql 的自增 Id(比方分库分表),亦或者应用 Mysql 很节约性能(应用 Mysql 不是为了存储数据,仅仅是为了取得一个惟一 Id),那么此时应用分布式全局惟一 Id 生成器是一个适合的计划。

有哪些分布式全局惟一 Id 生成形式?

UUID

UUID 全称:Universally Unique Identifier。规范型式蕴含 32 个 16 进制数字,以连字号分为五段,模式为 8-4-4-4-12 的 36 个字符,示例:9628f6e9-70ca-45aa-9f7c-77afe0d26e05。

长处:

  1. 代码实现简略。
  2. 本机生成,简直没有性能问题。

毛病:

  1. 无奈保障递增。
  2. UUID 是字符串,存储和查问相比于整形更麻烦(须要的存储空间大、不好索引等)。

拓展:基于 MAC 地址生成 UUID 的算法可能会造成 MAC 地址泄露,这个破绽曾被用于寻找梅丽莎病毒的制作者地位。

不过咱们这里仅探讨 UUID 作为惟一 Id 的场景,所以不能算作毛病。

利用场景:

  1. 生成 token 令牌的场景。
  2. 链路追踪场景。
  3. 不实用要求 Id 趋势递增的场景。
  4. 不适宜作为高性能需要的场景下的数据库主键。

Mysql && Redis

Mysql 与 Redis 的原理相似,都是利用数字自增来实现。

长处:

  1. 整型,且从 0 开始。
  2. 枯燥递增(区别趋势递增)。
  3. 查问效率高。
  4. 可读性好。

毛病:

  1. 存在单点问题,重大依赖 Mysql or Redis。
  2. 数据库压力大,高并发抗不住。
  3. 主从 Redis 存在同步提早。(这一点求教了公司团队的大佬)
  4. 即使应用集群 Redis,仍无奈防止 Redis 单点。(这一点求教了公司团队的大佬)

SnowFlake

SnowFlake 是 twitter 开源的分布式 ID 生成算法,也叫雪花算法,基于工夫戳来实现。

这是 Id 的格局,一共 64 位(对应 Go 的 int64 类型、Java 的 long 类型)。

+--------------------------------------------------------------------------+
| 1 Bit Unused | 41 Bit Timestamp |  10 Bit NodeID  |   12 Bit Sequence ID |
+--------------------------------------------------------------------------+

每次生成 ID 时:

  • 第 1 位废除不必。
  • 应用 41 位 ID 存储毫秒精度的工夫戳。
  • 而后增加 10 位 NodeID。
  • 最初增加 12 位序列号,从 0 开始,并为在同一毫秒内生成的每个 ID 递增。如果在同一毫秒内生成足够多的 ID 以使序列翻转或溢出,则生成函数将暂停到下一毫秒。

业界有很多轮子,比方 https://github.com/bwmarrin/s… 应用 Golang 实现了雪花算法。

这是应用该库的例子:能够看到,咱们须要在 NewNode 填入一个整数(因为 NodeID 有 10 位,所以该整数应该 < 1024)

func main() {

    // Create a new Node with a Node number of 1
    node, err := snowflake.NewNode(1)
    if err != nil {fmt.Println(err)
        return
    }

    // Generate a snowflake ID.
    id := node.Generate()}

长处:

  1. 整型。
  2. 趋势递增。
  3. 查问效率高。
  4. 本地生成 Id,简直没有性能问题。

毛病:

  1. 尽管是整型,然而生成的 Id 位 int64 类型(不能从 0 开始自增),须要思考与现有业务的兼容性。
  2. 无奈枯燥递增。
  3. 基于工夫戳实现,须要思考“工夫回拨”问题。

工夫回拨:雪花算法生成 Id 时,依赖机器工夫,如果机器工夫呈现大范畴回撤,那么生成的 Id 会反复。

总结

分布式全局惟一 Id 生成器作为微服务零碎的根底组件,高性能高可用是他最根本的要求。

首先,UUID 生成的 Id 是字符串,无奈代替传统的 Mysql 自增 Id,应用场景无限。

而无论是 Mysql、Redis 还是雪花算法,它们都存在各自的问题,前面我会联合国内几个比拟有名的开源实现(百度 UId – Generator、美团 Leaf、滴滴 TinyId),聊聊业界大厂是如何晋升 Mysql 发号器的性能的,是如何防止雪花算法“工夫回拨”的。

正文完
 0