首页 > 其他分享 >【Go - 超实用,3行代码实现个自增器】

【Go - 超实用,3行代码实现个自增器】

时间:2024-09-15 13:20:08浏览次数:13  
标签:实用 mongo err MONGODB 增器 go key Go bson

场景

自增器的作用是生成一个唯一的递增序列号。这在一些需要生成自增id的场景十分有用,比如自增的订单号,任务号,序列号。

要点

  • 全局统一:在整个服务体系下,多个服务或者进程,都统一调用这个自增器,来获取自增ID。
  • 严格自增:避免竞争,写冲突造成写覆盖等,导致不严格自增

实现

根据上面要点,需要跨服务进程可以访问,且保障严格自增。综上考虑, 依赖MonogoDB来实现这个自增器,以下是代码实现,

代码

mongodb-conn.go

package main

import (
	"context"
	"os"
	"sync"

	mongo "go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

var (
	singletonMongoClient *mongo.Client
	once                 sync.Once
)

var MONGODB_URI = os.Getenv("MONGODB_URI")
var MONGODB_DATABASE = os.Getenv("MONGODB_DATABASE")

func getSingletonMongoClient() *mongo.Client {

	once.Do(func() {
		// 创建连接到 MongoDB 的客户端
		uri := MONGODB_URI
		client, err := mongo.Connect(context.TODO(), options.Client().
			ApplyURI(uri))

		if err != nil {
			panic(err)
		}
		singletonMongoClient = client
	})
	return singletonMongoClient
}
func GetMongoConn() *mongo.Database {
	return getSingletonMongoClient().Database(MONGODB_DATABASE)
}

main.go

package main

import (
	"context"

	bson "go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo/options"
)

type UniqSeq struct {
	Key string `bson:"key"`
	Seq int64  `bson:"seq"`
}

func GetNextSeq(key string) (int64, error) {
	conn := GetMongoConn()
	var collectionName = "uniqseqz"
	collection := conn.Collection(collectionName)
	filter := bson.M{"key": key}
	update := bson.M{"$inc": bson.M{"seq": 1}}
	opts := options.FindOneAndUpdate().SetUpsert(true).SetReturnDocument(options.After)

	var result UniqSeq
	err := collection.FindOneAndUpdate(context.Background(), filter, update, opts).Decode(&result)

	if err != nil {
		return 0, err
	}
	return result.Seq, nil
}

func main() {
	// Test
	key := "T"
	seq, err := GetNextSeq(key)
	if err != nil {
		panic(err)
	}
	println(seq)
}

这里的核心就在下面三行

// 这里是借助了MongoDB $inc 和 upsert特性
// 先按key过滤,找出对应的document,然后upsert,没有就插入一条,有就加一。
// 以此来完成了自增
filter := bson.M{"key": key}
update := bson.M{"$inc": bson.M{"seq": 1}}
opts := options.FindOneAndUpdate().SetUpsert(true).SetReturnDocument(options.After)

关于竞争,

// 这个操作调用的时候,MongoDB Server端会加锁执行,保障操作的原子性,
// 对于调用方可以看以下一行是原子性的,不用担心写冲突或者写覆盖。
var result UniqSeq
	err := collection.FindOneAndUpdate(context.Background(), filter, update, opts).Decode(&result)

运行

最后可以带入运行一下,

MONGODB_URI="${YOUR_MONGODB_URL}" MONGODB_DATABASE="${YOUR_MONGODB_DATABASE}" go run mongodb-conn.go main.go

标签:实用,mongo,err,MONGODB,增器,go,key,Go,bson
From: https://blog.csdn.net/qq_38428433/article/details/142283171

相关文章

  • 【开题报告】基于django+vue旅游管理系统(论文+源码) 计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着旅游业的蓬勃发展,旅游市场的竞争日益激烈,传统的旅游管理方式已难以满足游客多元化、个性化的需求。在这个数字化时代,构建一个高效、便......
  • 硬件实用技巧:螺丝M标准、螺丝长度以及螺帽M直径
    若该文为原创文章,转载请注明原文出处本文章博客地址:https://hpzwl.blog.csdn.net/article/details/142205318长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…硬件相关开发......
  • 【开题报告】基于django+vue基于Web的电影推荐与点评系统(论文+源码) 计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展,在线娱乐已成为人们日常生活中不可或缺的一部分,其中网络电影观看尤为普及。然而,面对海量的电影资源,用户往往难以......
  • 【Go语言】quic-go实现0-RTT传输
    核心思路:在客户端的tls文件中缓存第一次连接留下来的会话票据,在第二次连接中就可以实现0-RTT。为此,重要的是实现tls.Config.ClientSessionCache这个接口的具体结构体文件目录tlscfg.go代码:这个模块主要用于实现客户端和服务器的tls配置packagetlscfgimport( "crypto......
  • Django 聚合查询
    文章目录一、聚合查询二、使用步骤1.准备工作2.具体使用3.分组查询(annotate)1.定义2.使用3.具体案例4.F()查询1.定义2.使用5.Q()查询1.定义2.查询一、聚合查询使用聚合查询前要先从django.db.models引入Avg、Max、Min、Count、Sum(首字母大写)聚合查询返回值......
  • Study Plan For Algorithms - Part32
    1.不同路径II一个机器人位于一个mxn网格的左上角(起始点在下图中标记为“Start”)。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?网格中的障碍物......
  • Study Plan For Algorithms - Part30
    1.螺旋矩阵II给定一个正整数n,生成一个包含1到n2所有元素,且元素按顺时针顺序螺旋排列的nxn正方形矩阵matrix。classSolution:defgenerateMatrix(self,n:int)->List[List[int]]:matrix=[[0]*nfor_inrange(n)]num=1......
  • Study Plan For Algorithms - Part31
    1.旋转链表给定一个链表的头节点head,旋转链表,将链表每个节点向右移动k个位置。classListNode:def__init__(self,val=0,next=None):self.val=valself.next=nextclassSolution:defrotateRight(self,head:Optional[ListNode],k:int)->O......
  • 【开题报告】基于django+vue外卖订餐管理系统(论文+程序)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着互联网的飞速发展和生活节奏的加快,外卖订餐服务已成为现代都市生活中不可或缺的一部分。它不仅极大地便利了消费者的日常生活,也为餐饮......
  • django实现分页的模块(导入即可用)
    `fromdjango.utils.safestringimportmark_safeimportcopyclassPagerPlay(object):definit(self,request,customer_list):self.customer_list=customer_listself.request_GET=copy.deepcopy(request.GET)self.request_GET._mutable=Trueself.page=request......