基于mongodb的进程锁设计

进程锁设计逻辑:

使用时,在调用加锁函数之后,写defer释放锁函数。

/*数据库脚本

use cloudeventserver;
// ----------------------------
// Collection structure for lock
// ----------------------------
db.getCollection("lock").drop();
db.createCollection("lock");
db.getCollection("lock").createIndex({
    "lock_key": NumberInt("-1")
}, {
    name: "lock_key_",
    unique: true
});

// ----------------------------
// Documents of lock
// ----------------------------
db.getCollection("lock").insert([ {
    _id: ObjectId("60f1457b8853e3b27c1ad23a"),
    "lock_key": "cloud_event_lock",
    "is_lock": NumberInt("0"),
    "update_time": NumberLong("1626428220")
} ]);
*/

const (
	UNLOCK_STATUS  = 0 //未锁定状态
	LOCK_STATUS    = 1 //锁定状态
    MongoDocumentNotFound = "no documents in result"
)

//解锁
func unLock(ctx context.Context, key string) error {
	var (
		collection *mongo.Collection
		filter     *bson.M
		upsert     = false
		err        error
	)
	filter = &bson.M{"lock_key": key}
	collection = config.Pool.Database("cloudeventserver").Collection("lock")
	update := &bson.M{"$set": &bson.M{"is_lock": UNLOCK_STATUS, "update_time": time.Now().Unix()}}
	err = collection.FindOneAndUpdate(ctx, filter, update, &options.FindOneAndUpdateOptions{
		Upsert: &upsert}).Err()
	if err != nil && !strings.Contains(err.Error(), MongoDocumentNotFound) {
		uclog.Error("unLock failed error:%s", err)
		return err
	}
	return nil
}

//加锁
func lock(ctx context.Context, key string) error {
	var (
		collection *mongo.Collection
		filter     *bson.M
		upsert     = false
		err        error
	)
	now := time.Now().Unix()

	//对已经释放的锁执行加锁操作
	filter = &bson.M{"lock_key": key, "is_lock": UNLOCK_STATUS}
	collection = config.Pool.Database("cloudeventserver").Collection("lock")
	update := &bson.M{"$set": &bson.M{"is_lock": LOCK_STATUS, "update_time": now}}
	opts := &options.FindOneAndUpdateOptions{
		Upsert: &upsert}

	err = collection.FindOneAndUpdate(ctx, filter, update, opts).Err()
	if err != nil {
		//只要加锁失败,则返回错误,结束本次任务
		//如果执行加锁失败,有可能是因为锁没有释放成功,则尝试着对已经过期未释放的锁进行解锁
		expireTime := now - beego.AppConfig.DefaultInt64("LockExpireTime", 5)*60
		filter = &bson.M{"lock_key": key, "is_lock": LOCK_STATUS, "update_time": &bson.M{"$lt": expireTime}}
		update := &bson.M{"$set": &bson.M{"is_lock": UNLOCK_STATUS, "update_time": now}}
		collection.FindOneAndUpdate(ctx, filter, update, opts).Err()

		uclog.Error("lock failed:%+s", err.Error())
		return err
	}
	return nil
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值