1
0
mirror of https://github.com/chai2010/advanced-go-programming-book.git synced 2025-05-24 04:22:22 +00:00
This commit is contained in:
Xargin 2018-12-23 18:55:21 +08:00
parent 59f26a0144
commit 903b12bf20
4 changed files with 25 additions and 54 deletions

View File

@ -6,32 +6,11 @@
Twitter的snowflake算法是这种场景下的一个典型解法。先来看看snowflake是怎么一回事 Twitter的snowflake算法是这种场景下的一个典型解法。先来看看snowflake是怎么一回事
``` ![snowflake](../images/ch6-snowflake.png)
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)。 首先确定我们的数值是64 位int64类型被划分为四部分不含开头的第一个bit因为这个bit是符号位。用41位来表示收到请求时的时间戳单位为毫秒然后五位来表示数据中心的id然后再五位来表示机器的实例id最后是12位的循环自增id(到达 1111 1111 1111 后会归 0)。
这样的机制可以支持我们在同一台机器上,同一毫秒内产生 2 ^ 12 = 4096 条消息。一秒共 409.6w 条消息。从值域上来讲完全够用了。 这样的机制可以支持我们在同一台机器上,同一毫秒内产生`2 ^ 12 = 4096`条消息。一秒共409.6万条消息。从值域上来讲完全够用了。
数据中心 + 实例id共有10位可以支持我们每数据中心部署32台机器所有数据中心共1024台实例。 数据中心 + 实例id共有10位可以支持我们每数据中心部署32台机器所有数据中心共1024台实例。
@ -68,11 +47,7 @@ mysql> select last_insert_id();
`github.com/bwmarrin/snowflake` 是一个相当轻量化的snowflake的Go实现。其文档指出 `github.com/bwmarrin/snowflake` 是一个相当轻量化的snowflake的Go实现。其文档指出
``` ![ch6-snowflake-easy](../images/ch6-snowflake-easy.png)
+--------------------------------------------------------------------------+
| 1 Bit Unused | 41 Bit Timestamp | 10 Bit NodeID | 12 Bit Sequence ID |
+--------------------------------------------------------------------------+
```
和标准的snowflake完全一致。使用上比较简单 和标准的snowflake完全一致。使用上比较简单
@ -128,15 +103,11 @@ Epoch 就是本节开头讲的起始时间NodeBits 指的是机器编号的
sonyflake是Sony公司的一个开源项目基本思路和snowflake差不多不过位分配上稍有不同 sonyflake是Sony公司的一个开源项目基本思路和snowflake差不多不过位分配上稍有不同
``` ![sonyflake](../images/ch6-snoyflake.png)
+-----------------------------------------------------------------------------+
| 1 Bit Unused | 39 Bit Timestamp | 8 Bit Sequence ID | 16 Bit Machine ID |
+-----------------------------------------------------------------------------+
```
这里的时间只用了39个bit但时间的单位变成了10ms所以理论上比41位表示的时间还要久(174 years)。 这里的时间只用了39个bit但时间的单位变成了10ms所以理论上比41位表示的时间还要久(174 years)。
Sequence ID 和之前的定义一致Machine ID 其实就是节点 id。sonyflake 与众不同的地方在于其在启动阶段的 setting 配置 `Sequence ID`和之前的定义一致,`Machine ID`其实就是节点id。`sonyflake`与众不同的地方在于其在启动阶段的配置参数:
```go ```go
func NewSonyflake(st Settings) *Sonyflake func NewSonyflake(st Settings) *Sonyflake
@ -154,7 +125,7 @@ type Settings struct {
StartTime选项和我们之前的Epoch差不多如果不设置的话默认是从`2014-09-01 00:00:00 +0000 UTC`开始。 StartTime选项和我们之前的Epoch差不多如果不设置的话默认是从`2014-09-01 00:00:00 +0000 UTC`开始。
MachineID 可以由用户自定义的函数,如果用户不定义的话,会默认将本机 ip 的低 16 位作为 machine id MachineID可以由用户自定义的函数如果用户不定义的话会默认将本机IP的低16位作为`machine id`
CheckMachineID是由用户提供的检查MachineID是否冲突的函数。这里的设计还是比较巧妙的如果有另外的中心化存储并支持检查重复的存储那我们就可以按照自己的想法随意定制这个检查MachineID是否冲突的逻辑。如果公司有现成的Redis集群那么我们可以很轻松地用Redis的set来检查冲突。 CheckMachineID是由用户提供的检查MachineID是否冲突的函数。这里的设计还是比较巧妙的如果有另外的中心化存储并支持检查重复的存储那我们就可以按照自己的想法随意定制这个检查MachineID是否冲突的逻辑。如果公司有现成的Redis集群那么我们可以很轻松地用Redis的set来检查冲突。

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

BIN
images/ch6-snowflake.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
images/ch6-snoyflake.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB