1
0
mirror of https://github.com/chai2010/advanced-go-programming-book.git synced 2025-05-29 16:22:21 +00:00
2018-07-08 23:27:50 +08:00

48 lines
4.4 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 6.7. 分布式 id 生成器
有时我们需要能够生成类似 MySQL 自增 ID 这样不断增大,同时又不会重复的 id。以支持业务中的高并发场景。比较典型的电商促销时短时间内会有大量的订单涌入到系统比如每秒 10w+。明星出轨时,会有大量热情的粉丝发微薄以表心意,同样产生短时间大量的消息。
在插入数据库之前,我们需要给这些消息/订单先打上一个 ID然后再插入到我们的数据库。对这个 id 的要求是希望其中能带有一些时间信息,这样即使我们后端的系统对消息进行了分库分表,也能够以时间顺序对这些消息进行排序。
Twitter 的 snowflake 算法是这种场景下的一个典型解法。先来看看 snowflake 是怎么一回事:
```
datacenter_id sequence_id
unused
│ │
│ │ │
│ │ │
│ │ │ │ │
│ │ │ │ │
▼ │◀────────────────── 41 bits ────────────────────▶│ ▼ ▼
┌─────┼──────────────────────────────────────────────────────┼────────┬────────┬────────────────┐
│ 0 │ 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0 │ 00000 │ 00000 │ 0000 0000 0000 │
└─────┴──────────────────────────────────────────────────────┴────────┴────────┴────────────────┘
▲ ▲
│ │
│ │
│ │
│ │
│ │
│ │
time in milliseconds worker_id
```
首先确定我们的数值是 64 位int64 类型,被划分为四部分,不含开头的第一个 bit因为这个 bit 是符号位。用 41 位来表示收到请求时的时间戳,单位为毫秒,然后五位来表示数据中心的 id然后再五位来表示机器的实例 id最后是 12 位的循环自增 id(到达 1111 1111 1111 后会归 0)。
这样的机制可以支持我们在同一台机器上,同一毫秒内产生 2 ^ 12 = 4096 条消息。一秒共 409.6w 条消息。从值域上来讲完全够用了。
数据中心 + 实例 id 共有 10 位,可以支持我们每数据中心部署 32 台机器,所有数据中心共 1024 台实例。
表示 timestamp 的 41 位,可以支持我们将时间推进到 `2039/9/7 23:47:35`,暂时也够用了。如果不够用,我们就从数据中心 id 中接一位出来,可以用到遥不可及的未来了。
## worker id 分配
## 开源实例
gosnowflake
sonyflake