Sonyflake
Sonyflake 是一个分布式的唯一 ID 生成器,由索尼开源,灵感来自 Twitter 的 Snowflake。
Sonyflake专注于在许多主机/核心环境下的寿命和性能。所以它和雪花有不同的位分配。一个 Sonyflake ID 由
39 位表示时间,单位为 10 毫秒
8 位表示序列号
16 位表示机器 id因此,Sonyflake 有以下优点和缺点:
- 寿命(174年)比雪花(69年)长
- 它可以工作在更多的分布式机器上(2^16)比雪花(2^10)
- 在单台机器/线程下,它最多每 10 毫秒生成 2^8 个 id (比Snowflake慢)。
配置
若没有指定启动时间,则使用 "2023-03-23 00:00:00 +0000 UTC" 作为 StartTime,如果 StartTime 设置的比当前时间要晚,则无法创建 Sonyflake 实例。 在单个主机下部署多个容器时可以不配置 MachineID,Sonyflake 将会使用容器的内网 IP 低 16 位作为 MachineID。 多个主机下部署多个容器时需要配置,以避免 MachineID 冲突。
[sonyflake]
StartTime = 2023-03-23T00:00:00Z
MachineID = 1获取 ID
func NextID() uint64如果使用 Cosy 项目级简化,则无需手动执行 sonyflake.Init() 进行初始化。
package main
import (
"github.com/uozi-tech/cosy/sonyflake"
"log"
)
func main() {
sonyflake.Init()
log.Println(sonyflake.NextID())
}作为字符串模型主键
默认情况下,model.Model 的主键 ID 为 uint64 类型(数据库自增)。如果希望使用 Sonyflake 生成 ID,但在 API 和路由参数中都以字符串形式传递,可以启用 sonyflake_str build tag:
go build -tags sonyflake_str ./...启用后,model.Model 的 ID 字段将变为自定义的 string-like 类型 model.SonyflakeID,并在创建记录时自动将 sonyflake.NextID() 生成的 uint64 转为十进制字符串。JSON 响应和路由参数仍以字符串形式传递,数据库列则仍按数值类型存储,用于保留 Sonyflake ID 的数值排序能力。
在 MySQL 下,GORM 自动迁移会将该字段声明为 bigint unsigned;SQLite 下会使用 integer;PostgreSQL 没有 unsigned bigint,会使用 numeric(20) 作为兼容类型。
package model
type User struct {
Model // ID 为 model.SonyflakeID 类型,自动生成 Sonyflake 十进制字符串
Name string `json:"name" cosy:"add:required;update:omitempty;list:fussy"`
Email string `json:"email" cosy:"add:required;update:omitempty;list:fussy"`
}TIP
启用 sonyflake_str build tag 后,所有嵌入 model.Model 的结构体都会自动通过 GORM BeforeCreate 钩子生成 Sonyflake 字符串主键,无需额外代码。
WARNING
如果项目曾经使用 varchar(20) 保存 sonyflake_str 主键,或曾经使用 signed bigint 保存主键,需要先确认所有现有 ID 都是非负十进制数字,再手动将数据库中的 id 列迁移为数值列。MySQL 项目建议迁移为 bigint unsigned,否则按 id 排序时可能会继续使用字符串字典序,或与新版本的自动迁移类型不一致。
WARNING
sonyflake_str、cuid2、uuid build tag 互斥,不能同时启用。如果业务模型定义了自己的 BeforeCreate 方法,将覆盖嵌入的 Model.BeforeCreate,此时需要手动设置 ID。