最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

go如何利用orm簡單實現(xiàn)接口分布式鎖

 更新時間:2018年07月23日 09:36:06   投稿:zx  
本篇文章主要介紹了go如何利用orm簡單實現(xiàn)接口分布式鎖,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

在開發(fā)中有些敏感接口,例如用戶余額提現(xiàn)接口,需要考慮在并發(fā)情況下接口是否會發(fā)生問題。如果用戶將自己的多條提現(xiàn)請求同時發(fā)送到服務(wù)器,代碼能否扛得住呢?一旦沒做鎖,那么就真的會給用戶多次提現(xiàn),給公司帶來損失。我來簡單介紹一下在這種接口開發(fā)過程中,我的做法。

第一階段:

我們使用的orm為xorm,提現(xiàn)表對應(yīng)的結(jié)構(gòu)體如下

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表中,是以O(shè)penid去重的,當(dāng)一個Openid對應(yīng)的Hit為1時,可以按照Redpack的數(shù)額提現(xiàn),成功后將Status改為1,簡單來說這就是提現(xiàn)接口的業(yè)務(wù)邏輯。

起初我并沒有太在意并發(fā)的問題,我在MySQL的提現(xiàn)表中設(shè)置一個字段status來記錄提現(xiàn)狀態(tài),我只是在提現(xiàn)時將狀態(tài)修改為2(體現(xiàn)中),提現(xiàn)完成后將status修改為1(已提現(xiàn))。然后事實證明,我太天真了,用ab做了測試1s發(fā)送了1000個請求到服務(wù)器,結(jié)果。。。成功提現(xiàn)了6次。部分代碼如下

p_info := &Participating{}
// 查找具體提現(xiàn)數(shù)額
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為提現(xiàn)中
p_info.Status = 2
db.Dalmore.Cols("status").Where("openid = ? and hit = 1 and status = 0", openid).Update(p_info)

// 提現(xiàn)p_info.Redpack

第二階段:

既然出現(xiàn)了并發(fā)問題,那第一反應(yīng)肯定的加鎖啊,代碼如下:

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{}
// 查找具體提現(xiàn)數(shù)額
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為提現(xiàn)中
p_info.Status = 2
db.Dalmore.Cols("status").Where("openid = ? and hit = 1 and status = 0", openid).Update(p_info)

// 釋放鎖
nodelock.Unlock()

// 提現(xiàn)p_info.Redpack

加了鎖以后。。。emem,允許多次提現(xiàn)的問題解決了,但是這個鎖限制的范圍太多了,直接讓這段加鎖代碼變成串行,這大大降低了接口性能。而且,一旦部署多個服務(wù)端,這個鎖又會出現(xiàn)多次提現(xiàn)的問題,因為他只能攔住這一個服務(wù)的并發(fā)??磥淼酶阋粋€不影響性能的分布式才是王道啊。

第三階段:

利用redis,設(shè)置一個key為openid的分布式鎖,并設(shè)置一個過期時間可以解決當(dāng)前的這個問題。但是難道就沒別的辦法了嗎?當(dāng)然是有的,golang的xorm中Update函數(shù)其實是有返回值的:num,err,我就是利用num做了個分布式鎖。

//記錄update修改條數(shù)
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操作到底修改了多少條數(shù)據(jù),起到了分布式鎖的作用
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
}

// 提現(xiàn)p_info.Redpack

其實有點投機取巧的意思,利用xorm的Update函數(shù),我們將核對并發(fā)處理請求下數(shù)據(jù)準(zhǔn)確性的問題拋給了MySQL,畢竟MySQL是經(jīng)過千錘百煉的。再用ab測試,嗯,鎖成功了只有,只提現(xiàn)了一次,大功告成~

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Golang并發(fā)編程深入分析

    Golang并發(fā)編程深入分析

    golang中的并發(fā),是函數(shù)相互獨立運行的能力,goroutines是并發(fā)運行的函數(shù)。golang提供了goroutines作為并發(fā)處理的一種方式
    2022-11-11
  • go語言中json處理方式詳解

    go語言中json處理方式詳解

    這篇文章主要介紹了go語言中json處理方式,文中通過實例代碼講解的非常詳細,對大家的學(xué)習(xí)或工作有一定的幫助,感興趣的小伙伴跟著小編一起來看看吧
    2024-05-05
  • Golang?HTTP服務(wù)超時控制實現(xiàn)原理分析

    Golang?HTTP服務(wù)超時控制實現(xiàn)原理分析

    這篇文章主要介紹了Golang?HTTP服務(wù)超時控制實現(xiàn)原理,HTTP服務(wù)的超時控制是保障服務(wù)高可用性的重要措施之一,由于HTTP服務(wù)可能會遇到網(wǎng)絡(luò)延遲,資源瓶頸等問題,因此需要對請求進行超時控制,以避免服務(wù)雪崩等問題,需要的朋友可以參考下
    2023-05-05
  • Go語言時間處理必備技巧全解析

    Go語言時間處理必備技巧全解析

    Golang 的時間處理是 Golang 編程中的一個重要方面,它涉及到了時間類型、時間格式化、時間計算、時區(qū)處理以及定時器和超時機制等多個方面。在本文中,我們將從更深入的角度來探討 Golang 的時間處理
    2023-04-04
  • go+redis實現(xiàn)消息隊列發(fā)布與訂閱的詳細過程

    go+redis實現(xiàn)消息隊列發(fā)布與訂閱的詳細過程

    這篇文章主要介紹了go+redis實現(xiàn)消息隊列發(fā)布與訂閱,redis做消息隊列的缺點:沒有持久化,一旦消息沒有人消費,積累到一定程度后就會丟失,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-09-09
  • golang通過http訪問外部網(wǎng)址的操作方法

    golang通過http訪問外部網(wǎng)址的操作方法

    這篇文章主要介紹了golang通過http訪問外部網(wǎng)址的操作方法,分為?get方式訪問外部的接口,Post方式請求外部接口,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2024-02-02
  • golang 后臺進程的啟動和停止操作

    golang 后臺進程的啟動和停止操作

    這篇文章主要介紹了golang 后臺進程的啟動和停止操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • 解讀rand.Seed(time.Now().UnixNano())的作用及說明

    解讀rand.Seed(time.Now().UnixNano())的作用及說明

    這篇文章主要介紹了關(guān)于rand.Seed(time.Now().UnixNano())的作用及說明,具有很好的參考價值,希望對大家有所幫助。
    2023-03-03
  • Go timer如何調(diào)度

    Go timer如何調(diào)度

    本篇文章剖析下 Go 定時器的相關(guān)內(nèi)容。定時器不管是業(yè)務(wù)開發(fā),還是基礎(chǔ)架構(gòu)開發(fā),都是繞不過去的存在,由此可見定時器的重要程度,感興趣的可以了解一下
    2021-06-06
  • 10個現(xiàn)代網(wǎng)站開發(fā)必備的Go軟件包工具盤點

    10個現(xiàn)代網(wǎng)站開發(fā)必備的Go軟件包工具盤點

    這篇文章主要為大家介紹了10個現(xiàn)代網(wǎng)站開發(fā)必備的Go軟件包,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10

最新評論

德州市| 西充县| 延寿县| 额济纳旗| 鸡泽县| 赣州市| 临城县| 香河县| 板桥市| 浪卡子县| 安新县| 会泽县| 巨鹿县| 巴中市| 哈巴河县| 凤庆县| 湘西| 太仓市| 太仓市| 云阳县| 崇明县| 拜城县| 安仁县| 柏乡县| 开化县| 涪陵区| 辽宁省| 石景山区| 丹巴县| 尉犁县| 美姑县| 紫金县| 永新县| 嘉禾县| 横峰县| 稻城县| 平顶山市| 都昌县| 临邑县| 牟定县| 红河县|