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

news2024/11/14 5:32:58

前言

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

分布式ID的特点及其应用

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

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

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

它的优点有以下几个:

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

缺点也比较明显:

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

雪花算法的实现机理

一.雪花算法的组成

在雪花算法中会生成64bit的long型数值,它可以分为如下四个部分:
在这里插入图片描述

  • 固定值(符号位,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()
}

最后我们尝试来生成一下:
在这里插入图片描述
也是看到成功的生成了id,再运行一次:
在这里插入图片描述
可以看到生成的id并不相同,说明我们的雪花算法已经成功实现了。

结语

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2039018.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第N5周:Pytorch文本分类入门

本文为365天深度学习训练营 中的学习记录博客原作者:K同学啊 任务: ●1. 了解文本分类的基本流程 ●2. 学习常用数据清洗方法 ●3. 学习如何使用jieba实现英文分词 ●4. 学习如何构建文本向量 一、前期准备 环境安装 这是一个使用PyTorch实现的简单文…

超详细教程:贴片电阻要怎么焊接?

在电子硬件中,焊接是必不可少的一个技能。 但是在实际的学习或者工作过程中,往往会碰上各种各样的焊接条件,焊接环境,如果是对于直插式的元件,比如说焊接一个直插式LED灯或者直插式电解电容,可能很容易焊接…

15个网络工程师必须记住的专业术语和概念

网络工程师在日常工作中确实需要掌握大量的专业术语和概念,这些术语和概念是理解和应用网络技术的基础。以下是一些网络工程师必知的重要术语及其应用场景: 1. IP地址(IP Address) 定义:互联网协议地址,用…

Elasticsearch 8 RAG 技术分享

作者:来自 Elastic 中国区首席架构师 Jerry 本文由 Elastic 中国区首席架构师 Jerry Zhu 在【AI 搜索 TechDay】上的分享整理而成。【AI 搜索 TechDay】 是 Elastic 和阿里云联合主办的 AI 技术 Meetup 系列,聚焦企业级 AI 搜索应用和开发者动手实践&am…

framebuffer总结

FrameBuffer,可以译作"帧缓冲",有时简称为 fbdrv。 这是一种独立于硬件的抽象图形设备。 是Linux为显示设备提供的一个接口,把显存抽象后的一种设备, 允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作 什么是…

QT 网络聊天室简易版

视频:qt开发网络聊天w室软件3.4界面开发_哔哩哔哩_bilibili 目录 UI部分 设计稿图 放置控件 界面美化 拖动窗体 设置界面 网络部分 配置对话框 多项目结果和服务器端设计 客户端框架开发 UI部分 设计稿图 放置控件 界面美化 现在我们把窗体自带的标题栏给去了,用我们自…

软件设计之MySQL(1)

软件设计之MySQL(1) 此篇应在JavaSE之后进行学习: 路线图推荐: 【Java学习路线-极速版】【Java架构师技术图谱】 Navicat可以在软件管家下载 使用navicat连接mysql数据库创建数据库、表、转储sql文件,导入sql数据 学习内容: 数据库概述表、…

6.IIC

理论 参考51单片机IIC理论:链接 在起始信号后必须发送一个7位从机地址 1位方向位,用“0”表示主机发送数据,“1”表示主机接收数据 代码编写 IIC三个模式配置 IIC(阻塞模式)配置 主要方式 IIC(中断模式)配置 IIC(DMA模式)配置 阻塞模式 mi…

智源研究院举办第一期数据与行业应用Workshop

近日,北京智源人工智能研究院联合中国互联网协会人工智能工委会、中国AIIA联盟数据委员会、CSDN举办了以“行业革新,数据先行”为主题的第一期数据与行业应用Workshop。来自智源研究院、中国信息通信研究院、航天信息技术有限公司、北京市科学技术研究院…

学习记录第二十七天

进程 wait函数 功能 等待子进程结束:父进程调用wait函数后,会暂停执行,直到它的某个子进程结束。收集子进程状态:当子进程结束时,wait函数会返回子进程的终止状态,包括是正常终止还是被信号终止等信息。…

单链表leetcode刷题/中(C语言版)

目录 题目1:合并两个有序链表 题目2:分割链表 题目3:随机链表的复制 “单链表leetcode刷题/上”的链接:https://blog.csdn.net/2302_80297338/article/details/140409360?spm1001.2014.3001.5501 题目1:合并两个有…

Ecovadis认证评估的四个方面 Ecovadis评估结果呈现形式

Ecovadis的认证过程严谨,基于国际公认的标准和准则进行评估。获得Ecovadis认证的企业,在社会责任、环境保护、商业道德和可持续采购等方面的表现得到了专业认可,这有助于提升企业的信誉度和透明度,增强利益相关者的信任。 Ecovad…

【CTF | WEB】003、攻防世界WEB题目之xff_referer

文章目录 xff_referer题目描述:解题思路:XFF与Referer基本了解1. XFF(X-Forwarded-For):2. Referer:简单总结: 解题实操: xff_referer 题目描述: X老师告诉小宁其实xff和referer是可以伪造的。…

在 Linux 系统中下载 Python 并配置环境

哈喽,大家好,木易巷来啦! 在 Linux 系统中下载 Python 并配置环境,主要包含以下几个核心步骤: ▍1、安装 Python 多数 Linux 发行版已预装 Python,但您可能需要安装不同版本或更新现有版本。 打开终端。 …

SpringBoot(Ⅰ)——HelloWorld和基本打包部署+Pom依赖概述+@SpringBootApplication注解+自动装配原理+约定大于配置

前言 如果SSM学的比较好,那么SpringBoot说白了就两件事:约定大于配置和自动装配 SpringBoot不会提供任何的功能拓展,完全依赖我们手动添加 所以SpringBoot的本质是一个依赖脚手架,可以快速集成配置各种依赖 1.1 SpringBoot相关依赖 创建…

失败:Windows--WSL2--Ubuntuon--Docker

编写目的: 在Windows上安装Docker,用Docker安装Gitlab、Jenkins等软件。 文章记录一下Windows上安装Docker的过程。 参考文档: 旧版 WSL 的手动安装步骤 | Microsoft Learn 下面用"参考文档"代替 目录 第一步:启…

学习计算机网络(三)——IP地址

一、IP协议(IPV4、IPV6) 表示形式(两种): 点分十进制、二进制 地址被点分为4个部分,每个部分8位,总共32位。 A、B、C类地址都是单播地址(一对一通信),D类…

谷粒商城实战笔记-175~177-商城业务-检索服务-检索查询接口开发

文章目录 一,175-商城业务-检索服务-检索查询参数模型分析抽取二,176-商城业务-检索服务-检索返回结果模型分析抽取三,177-商城业务-检索服务-检索DSL测试-查询部分四,178-商城业务-检索服务-检索DSL测试-聚合部分问题记录解决方案…

redis散列若干记录

字典 redis本身使用字典结构管理数据 redis使用hash表实现字典结构 使用了什么hash算法 使用SipHash算法,该算法能有效防止Hash表碰撞,并有不错的性能 hash冲突怎么解决 使用链表法解决hash冲突 hash表如何扩容 渐进式扩容,不会引起线程长期阻…