go语言后端开发学习(六) ——基于雪花算法生成用户ID

简介: 本文介绍了分布式ID生成中的Snowflake(雪花)算法。为解决用户ID安全性与唯一性问题,Snowflake算法生成的ID具备全局唯一性、递增性、高可用性和高性能性等特点。64位ID由符号位(固定为0)、41位时间戳、10位标识位(含数据中心与机器ID)及12位序列号组成。面对ID重复风险,可通过预分配、动态或统一分配标识位解决。Go语言实现示例展示了如何使用第三方包`sonyflake`生成ID,确保不同节点产生的ID始终唯一。

前言

在我们日常进行开发的时候,不可避免的会出现对用户表的操作,而为了保证每一个用户的唯一性,这就需要我们创建一个唯一性的id,但是现在有一个问题,如果我们仅仅像通过自增这样方式来创建唯一的id,这无疑是非常不合适的,他人可以通过自己新创建账号的id进而大致推算出当前网站大致的用户量,这样会对网站的安全造成极大的威胁,那我们可以如何去避免这种情况呢?这就是我们今天所要介绍的内容:分布式ID生成。

分布式ID的特点及其应用

分布式ID主要具有以下特点:

  • 全局唯一性:不能出现有重复的ID标识
  • 递增性:确保生成ID对于用户/业务是递增的
  • 高可用性:确保如何情况下生成的id都正常
  • 高性能性:在高并发的环境下依旧表现良好

而今天我们所要介绍的分布式ID生成方案是业内比较推荐的方法—— Snowflake(雪花算法)

它的优点有以下几个:

  • 生成时不依赖于数据库,完全在内存中生成(高性能高可用)
  • 每秒钟能生成数百万的自增 ID(高吞吐)
  • 存入数据库中,索引效率高

缺点也比较明显:

  • 依赖服务器时间,服务器时间回拨时可能会生成重复 id。

雪花算法的实现机理

一.雪花算法的组成

在雪花算法中会生成64bit的long型数值,它可以分为如下四个部分:
image.png

  • 固定值(符号位,0-正 1-负)
  • 时间戳:41bit,存储毫秒级时间戳(41 位的长度可以使用 69 年)
  • 标识位:12bit,用于表示在同一毫秒内生成的多个ID的序号。如果在同一毫秒内生成的ID超过了4096个(2的12次方),则需要等到下一毫秒再生成ID。

拓展: 虽然默认生成的位数是64位,但是这个我们可以手动调节

二.对于雪花算法部分问题的分析

1.生成ID重复问题

场景:一个订单微服务,通过雪花算法生成 ID,共部署三个节点,标识位一致。此时有 200 并发,均匀散布三个节点,三个节点同一毫秒同一序列号下生成 ID,那么就会产生重复 ID

由此我们可以知道该问题出现的前置条件如下:

  • 服务通过集群的方式部署,其中部分机器标识位一致;
  • 业务存在一定的并发量,没有并发量无法触发重复问题;
  • 生成 ID 的时机:同一毫秒下的序列号一致。

解决方案:

  • 预分配:应用上线前,统计当前服务的节点数,人工去申请标识位.(适用于服务节点固定或者项目较少)
  • 动态分配:将标识位存放在 Redis、Zookeeper、MySQL 等中间件,在服务启动的时候去请求标识位,请求后标识位更新为下一个可用的
  • 统一分配:将标识位存放在 Redis、Zookeeper、MySQL 等中间件,在服务启动的时候去请求标识位,请求后标识位更新为下一个可用的

2.标识位的使用方式

标识位一共10 bit,如果全部表示机器,那么可以表示1024台机器,如果拆分,5 bit 表示机房,5bit表示机房里面的机器,那么可以有32个机房,每个机房可以用32台机器。

雪花算法的实现

这里我们选择使用第三方包sonyflake

 go get github.com/sony/sonyflake
package snoyflake

import (
    "fmt"
    "github.com/sony/sonyflake"
    "time"
)

var (
    sonyFlake     *sonyflake.Sonyflake
    sonyMachineId uint16
)

func getMachineId() (id uint16, err error) {
   
   
    return sonyMachineId, nil
}
func Init(starttime string, machineId uint16) (err error) {
   
   
    sonyMachineId = machineId
    t, _ := time.Parse("2006-01-02", starttime) // 设置开始时间
    setting := sonyflake.Settings{
   
   
        StartTime: t,
        MachineID: getMachineId,
    }
    sonyFlake = sonyflake.NewSonyflake(setting) //用配置生成sonyflake节点
    return
}

// GetID 返回生成的id
func GetID() (id uint64, err error) {
   
   
    if sonyFlake == nil {
   
   
        err = fmt.Errorf("sonyflake not init")
        return
    }
    return sonyFlake.NextID()
}

最后我们尝试来生成一下:

image.png

也是看到成功的生成了id,再运行一次:
image.png

可以看到生成的id并不相同,说明我们的雪花算法已经成功实现了。

结语

在原理方面参考了下面的文章,在此鸣谢大佬的分享:
一文读懂“Snowflake(雪花)”算法

相关文章
|
24天前
|
JSON 中间件 Go
Go 网络编程:HTTP服务与客户端开发
Go 语言的 `net/http` 包功能强大,可快速构建高并发 HTTP 服务。本文从创建简单 HTTP 服务入手,逐步讲解请求与响应对象、URL 参数处理、自定义路由、JSON 接口、静态文件服务、中间件编写及 HTTPS 配置等内容。通过示例代码展示如何使用 `http.HandleFunc`、`http.ServeMux`、`http.Client` 等工具实现常见功能,帮助开发者掌握构建高效 Web 应用的核心技能。
157 61
|
4月前
|
存储 负载均衡 算法
基于 C++ 语言的迪杰斯特拉算法在局域网计算机管理中的应用剖析
在局域网计算机管理中,迪杰斯特拉算法用于优化网络路径、分配资源和定位故障节点,确保高效稳定的网络环境。该算法通过计算最短路径,提升数据传输速率与稳定性,实现负载均衡并快速排除故障。C++代码示例展示了其在网络模拟中的应用,为企业信息化建设提供有力支持。
117 15
|
4月前
|
监控 算法 安全
基于 PHP 语言深度优先搜索算法的局域网网络监控软件研究
在当下数字化时代,局域网作为企业与机构内部信息交互的核心载体,其稳定性与安全性备受关注。局域网网络监控软件随之兴起,成为保障网络正常运转的关键工具。此类软件的高效运行依托于多种数据结构与算法,本文将聚焦深度优先搜索(DFS)算法,探究其在局域网网络监控软件中的应用,并借助 PHP 语言代码示例予以详细阐释。
81 1
|
5月前
|
运维 监控 算法
监控局域网其他电脑:Go 语言迪杰斯特拉算法的高效应用
在信息化时代,监控局域网成为网络管理与安全防护的关键需求。本文探讨了迪杰斯特拉(Dijkstra)算法在监控局域网中的应用,通过计算最短路径优化数据传输和故障检测。文中提供了使用Go语言实现的代码例程,展示了如何高效地进行网络监控,确保局域网的稳定运行和数据安全。迪杰斯特拉算法能减少传输延迟和带宽消耗,及时发现并处理网络故障,适用于复杂网络环境下的管理和维护。
|
2月前
|
人工智能 缓存 安全
Go开发遇见的一次Data Race
本文通过一段 Go 语言代码示例,分析了并发编程中的数据竞争(Data Race)问题。代码实现了一个带缓存的内存存储系统,包含 `LRUCache` 和 `MemoryCache` 两个核心组件。尽管在 `MemoryCache` 的 `Set` 方法中加了锁保护,但由于直接调用 `LRUCache` 的 `GetLength` 方法时未加锁,导致底层数据结构在多 goroutine 环境下被同时读写,从而触发 Data Race。文章详细解析了问题根源,并提出了解决方案:为 `LRUCache` 的 `Add` 方法添加锁保护,确保并发安全。
|
4月前
|
存储 算法 安全
企业员工数据泄露防范策略:基于 C++ 语言的布隆过滤器算法剖析[如何防止员工泄密]
企业运营过程中,防范员工泄密是信息安全领域的核心议题。员工泄密可能致使企业核心数据、商业机密等关键资产的流失,进而给企业造成严重损失。为应对这一挑战,借助恰当的数据结构与算法成为强化信息防护的有效路径。本文专注于 C++ 语言中的布隆过滤器算法,深入探究其在防范员工泄密场景中的应用。
77 8
|
3月前
|
Go API 定位技术
MCP 实战:用 Go 语言开发一个查询 IP 信息的 MCP 服务器
随着 MCP 的快速普及和广泛应用,MCP 服务器也层出不穷。大多数开发者使用的 MCP 服务器开发库是官方提供的 typescript-sdk,而作为 Go 开发者,我们也可以借助优秀的第三方库去开发 MCP 服务器,例如 ThinkInAIXYZ/go-mcp。 本文将详细介绍如何在 Go 语言中使用 go-mcp 库来开发一个查询 IP 信息的 MCP 服务器。
192 0
|
4月前
|
存储 监控 算法
基于 PHP 语言的滑动窗口频率统计算法在公司局域网监控电脑日志分析中的应用研究
在当代企业网络架构中,公司局域网监控电脑系统需实时处理海量终端设备产生的连接日志。每台设备平均每分钟生成 3 至 5 条网络请求记录,这对监控系统的数据处理能力提出了极高要求。传统关系型数据库在应对这种高频写入场景时,性能往往难以令人满意。故而,引入特定的内存数据结构与优化算法成为必然选择。
95 3
|
5月前
|
算法 安全 Go
公司局域网管理系统里的 Go 语言 Bloom Filter 算法,太值得深挖了
本文探讨了如何利用 Go 语言中的 Bloom Filter 算法提升公司局域网管理系统的性能。Bloom Filter 是一种高效的空间节省型数据结构,适用于快速判断元素是否存在于集合中。文中通过具体代码示例展示了如何在 Go 中实现 Bloom Filter,并应用于局域网的 IP 访问控制,显著提高系统响应速度和安全性。随着网络规模扩大和技术进步,持续优化算法和结合其他安全技术将是企业维持网络竞争力的关键。
106 2
公司局域网管理系统里的 Go 语言 Bloom Filter 算法,太值得深挖了
|
5月前
|
存储 缓存 监控
企业监控软件中 Go 语言哈希表算法的应用研究与分析
在数字化时代,企业监控软件对企业的稳定运营至关重要。哈希表(散列表)作为高效的数据结构,广泛应用于企业监控中,如设备状态管理、数据分类和缓存机制。Go 语言中的 map 实现了哈希表,能快速处理海量监控数据,确保实时准确反映设备状态,提升系统性能,助力企业实现智能化管理。
80 3

热门文章

最新文章