不做大哥好多年 不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核

逍遥子

不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核
  • GO基础

  • 面向对象

  • 并发编程

  • 常用库

  • 数据库操作

  • Beego框架

  • Beego商城

  • GIN框架

  • GIN论坛

    • 01.gin源码
    • 02.go内置sql模块
    • 03.sqlx库
    • 04.sqlx-In函数
    • 05.gin中使用zap日志
    • 06.gin优雅地关机
    • 07.大型WEB项目CLD分层
    • 08.web脚手架
    • 09.validator校验器
    • 10.雪花算法用户ID
      • 01.分布式ID成器
        • 1.1 分布式ID的特点
        • 1.2 分布式ID应用场景
      • 02.雪花算法介绍
        • 2.1 snowflake算法
        • 2.2 四个站位说明
      • 03.snowflake的Go实现
      • 04.gin中使用snowflake
        • 1.1 pkg/snowflake/snowflake.go
        • 1.2 conf/config.yaml
        • 1.3 settings/settings.go
        • 1.4 main.go
    • 11.返回格式封装
    • 12.注册模块
    • 13.JWT
    • 14.登录模块
    • 15.社区接口开发
    • 16.认证中间件
    • 100.docker部署
    • 101.nginx部署
  • 微服务

  • 设计模式

  • Go
  • GIN论坛
xiaonaiqiang
2021-06-13
目录

10.雪花算法用户ID

# 01.分布式ID成器

# 1.1 分布式ID的特点

  • 全局唯⼀性:不能出现有重复的ID标识,这是基本要求。

  • 递增性:确保⽣成ID对于⽤户或业务是递增的。

  • ⾼可⽤性:确保任何时候都能⽣成正确的ID。

  • ⾼性能性:在⾼并发的环境下依然表现良好。

# 1.2 分布式ID应用场景

  • 不仅仅是⽤于⽤户ID,实际互联⽹中有很多场景需要能够⽣成类似MySQL⾃增ID这样不断增⼤,同时⼜不会重复的id。
  • 以⽀持业务中的⾼并发场景。
    • ⽐较典型的场景有:电商促销时短时间内会有⼤量的订单涌⼊到系统,⽐如每秒10w+;
    • 明星出轨时微博短时间内会产⽣⼤量的相关微博转发和评论消息
  • 在这些业务场景下将数据插⼊数据库之前,我们需要给这些订单和消息先分配⼀个唯⼀ID,然后再保存到数据库中。
  • 对这个id的要求是希望其中能带有⼀些时间信息
  • 这样即使我们后端的系统对消息进⾏了分库分表,也能够以时间顺序对这些消息进⾏排序。

# 02.雪花算法介绍

# 2.1 snowflake算法

  • 雪花算法,它是Twitter开源的由64位整数组成分布式ID,性能较⾼,并且在单机上递增

# 2.2 四个站位说明

  • 1.第一位 占1 bit,其值始终是0,没有实际作用。

  • 2.时间戳 占41 bit,单位为毫秒,总共可以容纳约69年的时间。

    • 当然,我们的时间毫秒计数不会真的从1970年开始记
    • 那样我们的系统跑到 2039/9/7 23:47:35 就不能了,
    • 所以这里的时间戳只是相对于某个时间的增量,比如我们的系统上线是2020-07-01,
  • 3.工作机器id 占10 bit,其中高位5bit是数据中心ID,低位5bit是工作节点ID最多可以容纳1024个节点。

  • 4.序列号 占12 bit,用来记录同毫秒内产⽣的不同id。

    • 每个节点每毫秒0开始不断累加,最多可以累加到4095,同一毫秒一共可以产生4096个ID。
    • SnowFlake算法在同一毫秒内最多可以生成多少个全局唯一ID呢?
    • 同一毫秒的ID数量 = 1024 X 4096 = 4194304

# 03.snowflake的Go实现

package main

import (
	"fmt"
	"github.com/bwmarrin/snowflake"
	"time"
)

var node *snowflake.Node
func Init(startTime string, machineID int64) (err error) {
	var st time.Time
	st, err = time.Parse("2006-01-02", startTime)
	if err != nil {
		return
	}
	snowflake.Epoch = st.UnixNano() / 1000000
	node, err = snowflake.NewNode(machineID)
	return
}
func GenID() int64 {
	return node.Generate().Int64()
}
func main() {
	if err := Init("2020-07-01", 1); err != nil {
		fmt.Printf("init failed, err:%v\n", err)
		return
	}
	id := GenID()
	fmt.Println(id)  // 125946957477711872
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 04.gin中使用snowflake

# 1.1 pkg/snowflake/snowflake.go

package snowflake

import (
	sf "github.com/bwmarrin/snowflake"
	"time"
)

var node *sf.Node

func Init(startTime string, machineID int64) (err error) {
	var st time.Time
	st, err = time.Parse("2006-01-02", startTime)
	if err != nil {
		return
	}
	sf.Epoch = st.UnixNano() / 1000000
	node, err = sf.NewNode(machineID)
	return
}

func GenID() int64 {
	return node.Generate().Int64()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 1.2 conf/config.yaml

start_time: "2020-07-01"
machine_id: 1
1
2

# 1.3 settings/settings.go

type AppConfig struct {
	Name         string `mapstructure:"name"`
	Mode         string `mapstructure:"mode"`
	Version      string `mapstructure:"version"`
	Port         int    `mapstructure:"port"`
    
    
	StartTime    string `mapstructure:"start_time"`
	MachineID    int64  `mapstructure:"machine_id"`
    
    
	*LogConfig   `mapstructure:"log"`
	*MySQLConfig `mapstructure:"mysql"`
	*RedisConfig `mapstructure:"redis"`
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 1.4 main.go

func main() {
	// 初始化,雪花算法
	if err := snowflake.Init(settings.Conf.StartTime, settings.Conf.MachineID); err != nil {
		fmt.Printf("init snowflake failed, err:%v\n", err)
		return
	}
	// fmt.Println("使用雪花算法获取用户ID:", snowflake.GenID())
}
1
2
3
4
5
6
7
8
上次更新: 2024/3/13 15:35:10
09.validator校验器
11.返回格式封装

← 09.validator校验器 11.返回格式封装→

最近更新
01
04.数组双指针排序_子数组
03-25
02
08.动态规划
03-25
03
06.回溯算法
03-25
更多文章>
Theme by Vdoing | Copyright © 2019-2025 逍遥子 技术博客 京ICP备2021005373号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式