go如何利用orm简单实现接口分布式锁

作者:zx 时间:2023-06-17 16:55:04 

在开发中有些敏感接口,例如用户余额提现接口,需要考虑在并 * 况下接口是否会发生问题。如果用户将自己的多条提现请求同时发送到服务器,代码能否扛得住呢?一旦没做锁,那么就真的会给用户多次提现,给公司带来损失。我来简单介绍一下在这种接口开发过程中,我的做法。

第一阶段:

我们使用的orm为xorm,提现表对应的结构体如下


type Participating struct {
ID   uint     `xorm:"autoincr id" json:"id,omitempty"`
Openid string    `xorm:"openid" json:"openid"`
Hit   uint     `xorm:"hit" json:"hit"`
Orderid string    `xorm:"order_id" json:"order_id"`
Redpack uint     `xorm:"redpack" json:"redpack"`
Status uint     `xorm:"status" json:"status"`
Ctime  tool.JsonTime `xorm:"ctime" json:"ctime,omitempty"`
Utime  tool.JsonTime `xorm:"utime" json:"utime,omitempty"`
PayTime tool.JsonTime `xorm:"pay_time" json:"pay_time,omitempty"`
}

在Participating表中,是以Openid去重的,当一个Openid对应的Hit为1时,可以按照Redpack的数额提现,成功后将Status改为1,简单来说这就是提现接口的业务逻辑。

起初我并没有太在意并发的问题,我在MySQL的提现表中设置一个字段status来记录提现状态,我只是在提现时将状态修改为2(体现中),提现完成后将status修改为1(已提现)。然后事实证明,我太天真了,用ab做了测试1s发送了1000个请求到服务器,结果。。。成功提现了6次。部分代码如下


p_info := &Participating{}
// 查找具体提现数额
has, _ := db.Dalmore.Where("openid = ? and hit = 1 and status = 0", openid).Get(p_info)
if !has {
resp.Error(errcode.NO_REDPACK_FOUND, nil, nil)
return
}

// 改status为提现中
p_info.Status = 2
db.Dalmore.Cols("status").Where("openid = ? and hit = 1 and status = 0", openid).Update(p_info)

// 提现p_info.Redpack

第二阶段:

既然出现了并发问题,那第一反应肯定的加锁啊,代码如下:


type Set struct {
m map[string]bool
sync.RWMutex
}

func New() *Set {
return &Set{
m: map[string]bool{},
}
}

var nodelock = set.New()

// 加锁
nodelock.Lock()

p_info := &Participating{}
// 查找具体提现数额
has, _ := db.Dalmore.Where("openid = ? and hit = 1 and status = 0", openid).Get(p_info)
if !has {
resp.Error(errcode.NO_REDPACK_FOUND, nil, nil)
return
}

// 改status为提现中
p_info.Status = 2
db.Dalmore.Cols("status").Where("openid = ? and hit = 1 and status = 0", openid).Update(p_info)

// 释放锁
nodelock.Unlock()

// 提现p_info.Redpack

加了锁以后。。。emem,允许多次提现的问题解决了,但是这个锁限制的范围太多了,直接让这段加锁代码变成串行,这大大降低了接口性能。而且,一旦部署多个服务端,这个锁又会出现多次提现的问题,因为他只能拦住这一个服务的并发。看来得搞一个不影响性能的分布式才是王道啊。

第三阶段:

利用redis,设置一个key为openid的分布式锁,并设置一个过期时间可以解决当前的这个问题。但是难道就没别的办法了吗?当然是有的,golang的xorm中Update函数其实是有返回值的:num,err,我就是利用num做了个分布式锁。


//记录update修改条数
num, err := db.Dalmore.Cols("status").Where("openid = ? and status = 0 and hit = 1", openid).Update(p_update)
if err != nil {
logger.Runtime().Debug(map[string]interface{}{"error": err.Error()}, "error while updating")
resp.Error(errcode.INTERNAL_ERROR, nil, nil)
return
}

// 查看update操作到底修改了多少条数据,起到了分布式锁的作用
if num != 1 {
resp.Error(errcode.NO_REDPACK_FOUND, nil, nil)
return
}

p_info := &Participating{}
_, err := db.Dalmore.Where("openid = ? and status = 2", openid).Get(p_info)
if err != nil {
logger.Runtime().Debug(map[string]interface{}{"error": err.Error()}, "error while selecting")
resp.Error(errcode.INTERNAL_ERROR, nil, nil)
return
}

// 提现p_info.Redpack

其实有点投机取巧的意思,利用xorm的Update函数,我们将核对并发处理请求下数据准确性的问题抛给了MySQL,毕竟MySQL是经过千锤百炼的。再用ab测试,嗯,锁成功了只有,只提现了一次,大功告成~

来源:http://www.cnblogs.com/baiyb/p/9352018.html

标签:go,orm,接口,分布式锁
0
投稿

猜你喜欢

  • MYSQL不能从远程连接的一个解决方法(s not allowed to connect to this MySQL server)

    2024-01-19 02:57:34
  • 软件测试实现Finddler的手机抓包过程

    2023-12-27 03:36:40
  • Sql Server表死锁的解决方法分享

    2011-09-01 19:08:00
  • 对setInterval在火狐和chrome切换标签产生奇怪的效果之探索,与解决方案!

    2024-04-28 09:43:23
  • 基于webstorm卡顿问题的2种解决方法

    2023-02-23 09:03:17
  • python+django快速实现文件上传

    2021-03-12 19:07:38
  • Python 一篇文章看懂时间日期对象

    2022-12-23 04:29:14
  • golang中select语句的简单实例

    2023-09-03 03:01:28
  • 学习 YUI3 中的沙箱机制

    2010-04-12 12:52:00
  • C#访问PostGreSQL数据库的方法

    2024-01-23 01:00:13
  • Python列表和集合的效率大比拼

    2021-09-04 14:10:16
  • TensorFlow中关于tf.app.flags命令行参数解析模块

    2021-10-17 03:40:40
  • mysql语句实现简单的增、删、改、查操作示例

    2024-01-24 23:04:04
  • SQL Server 监控磁盘IO错误,msdb.dbo.suspect_pages

    2024-01-22 09:26:44
  • 详解非极大值抑制算法之Python实现

    2021-02-24 06:41:32
  • pandas之分组groupby()的使用整理与总结

    2022-04-23 17:24:42
  • python自动发邮件库yagmail的示例代码

    2022-01-15 14:23:26
  • golang 中strings包的Replace的使用说明

    2024-02-09 16:02:04
  • 浅析Python编写函数装饰器

    2023-06-07 12:20:05
  • 在Python的框架中为MySQL实现restful接口的教程

    2024-01-13 08:09:54
  • asp之家 网络编程 m.aspxhome.com