成人性生交大片免费看视频r_亚洲综合极品香蕉久久网_在线视频免费观看一区_亚洲精品亚洲人成人网在线播放_国产精品毛片av_久久久久国产精品www_亚洲国产一区二区三区在线播_日韩一区二区三区四区区区_亚洲精品国产无套在线观_国产免费www

主頁 > 知識庫 > 使用Golang的singleflight防止緩存擊穿的方法

使用Golang的singleflight防止緩存擊穿的方法

熱門標簽:智能電銷機器人營銷 澳門防封電銷卡 福州鐵通自動外呼系統(tǒng) 長沙ai機器人電銷 地圖標注測試 賺地圖標注的錢犯法嗎 烏魯木齊人工電銷機器人系統(tǒng) 廣東語音外呼系統(tǒng)供應商 濮陽自動外呼系統(tǒng)代理

在使用緩存時,容易發(fā)生緩存擊穿。

緩存擊穿:一個存在的key,在緩存過期的瞬間,同時有大量的請求過來,造成所有請求都去讀dB,這些請求都會擊穿到DB,造成瞬時DB請求量大、壓力驟增。

singleflight

介紹

import "golang.org/x/sync/singleflight"

singleflight類的使用方法就新建一個singleflight.Group,使用其方法Do或者DoChan來包裝方法,被包裝的方法在對于同一個key,只會有一個協(xié)程執(zhí)行,其他協(xié)程等待那個協(xié)程執(zhí)行結(jié)束后,拿到同樣的結(jié)果。

Group結(jié)構(gòu)體

代表一類工作,同一個group中,同樣的key同時只能被執(zhí)行一次。

Do方法

func (g *Group) Do(key string, fn func() (interface{}, error)) (v interface{}, err error, shared bool)

key:同一個key,同時只有一個協(xié)程執(zhí)行。

fn:被包裝的函數(shù)。

v:返回值,即執(zhí)行的結(jié)果。其他等待的協(xié)程都會拿到。

shared:表示是否有其他協(xié)程得到了這個結(jié)果v。

DoChan方法

func (g *Group) DoChan(key string, fn func() (interface{}, error)) -chan Result

與Do方法一樣,只是返回的是一個channel,執(zhí)行結(jié)果會發(fā)送到channel中,其他等待的協(xié)程都可以從channel中拿到結(jié)果。

ref:https://godoc.org/golang.org/x/sync/singleflight

示例

使用Do方法來模擬,解決緩存擊穿的問題

func main() {

  var singleSetCache singleflight.Group

  getAndSetCache:=func (requestID int,cacheKey string) (string, error) {

  log.Printf("request %v start to get and set cache...",requestID)

  value,_, _ :=singleSetCache.Do(cacheKey, func() (ret interface{}, err error) {//do的入?yún)ey,可以直接使用緩存的key,這樣同一個緩存,只有一個協(xié)程會去讀DB

    log.Printf("request %v is setting cache...",requestID)

     time.Sleep(3*time._Second_)

     log.Printf("request %v set cache success!",requestID)

    return "VALUE",nil

   })

  return value.(string),nil

  }

  cacheKey:="cacheKey"

  for i:=1;i10;i++{//模擬多個協(xié)程同時請求

  go func(requestID int) {

     value,_:=getAndSetCache(requestID,cacheKey)

     log.Printf("request %v get value: %v",requestID,value)

   }(i)

  }

  time.Sleep(20*time._Second_)
}

輸出:

2020/04/12 18:18:40 request 4 start  to  get  and  set cache...

2020/04/12 18:18:40 request 4 is setting cache...

2020/04/12 18:18:40 request 2 start  to  get  and  set cache...

2020/04/12 18:18:40 request 7 start  to  get  and  set cache...

2020/04/12 18:18:40 request 5 start  to  get  and  set cache...

2020/04/12 18:18:40 request 1 start  to  get  and  set cache...

2020/04/12 18:18:40 request 6 start  to  get  and  set cache...

2020/04/12 18:18:40 request 3 start  to  get  and  set cache...

2020/04/12 18:18:40 request 8 start  to  get  and  set cache...

2020/04/12 18:18:40 request 9 start  to  get  and  set cache...

2020/04/12 18:18:43 request 4 set  cache  success!

2020/04/12 18:18:43 request 4 get value: VALUE

2020/04/12 18:18:43 request 9 get value: VALUE

2020/04/12 18:18:43 request 6 get value: VALUE

2020/04/12 18:18:43 request 3 get value: VALUE

2020/04/12 18:18:43 request 8 get value: VALUE

2020/04/12 18:18:43 request 1 get value: VALUE

2020/04/12 18:18:43 request 5 get value: VALUE

2020/04/12 18:18:43 request 2 get value: VALUE

2020/04/12 18:18:43 request 7 get value: VALUE`

可以看到確實只有一個協(xié)程執(zhí)行了被包裝的函數(shù),并且其他協(xié)程都拿到了結(jié)果。

源碼分析

看一下這個Do方法是怎么實現(xiàn)的。

首先看一下Group的結(jié)構(gòu):

type Group struct {

  mu sync.Mutex   

  m map[string]*call //保存key對應的函數(shù)執(zhí)行過程和結(jié)果的變量。

}

Group的結(jié)構(gòu)非常簡單,一個鎖來保證并發(fā)安全,另一個map用來保存key對應的函數(shù)執(zhí)行過程和結(jié)果的變量。

看下call的結(jié)構(gòu):

type call struct {

  wg sync.WaitGroup //用WaitGroup實現(xiàn)只有一個協(xié)程執(zhí)行函數(shù)

  val interface{} //函數(shù)執(zhí)行結(jié)果

  err error

  forgotten bool

  dups int //含義是duplications,即同時執(zhí)行同一個key的協(xié)程數(shù)量

  chans []chan- Result
}

看下Do方法

func (g *Group) Do(key string, fn func() (interface{}, error)) (v interface{}, err error, shared bool) {

  g.mu.Lock()//寫Group的m字段時,加鎖保證寫安全。

  if g.m == nil {

  g.m = make(map[string]*call)

  }

if c, ok := g.m[key]; ok {//如果key已經(jīng)存在,說明已經(jīng)有協(xié)程在執(zhí)行,則dups++,并等待其執(zhí)行完畢后,返回其執(zhí)行結(jié)果,執(zhí)行結(jié)果保存在對應的call的val字段里

   c.dups++

   g.mu.Unlock()

   c.wg.Wait()

 return c.val, c.err, true

  }

//如果key不存在,則新建一個call,并使用WaitGroup來阻塞其他協(xié)程,同時在m字段里寫入key和對應的call

c := new(call)

  c.wg.Add(1)

  g.m[key] = c

  g.mu.Unlock()

  g.doCall(c, key, fn)//第一個進來的協(xié)程來執(zhí)行這個函數(shù)

return c.val, c.err, c.dups > 0

}

繼續(xù)看下g.doCall里具體干了什么

func (g *Group) doCall(c *call, key string, fn func() (interface{}, error)) {

  c.val, c.err = fn()//執(zhí)行被包裝的函數(shù)

  c.wg.Done()//執(zhí)行完畢后,就可以通知其他協(xié)程可以拿結(jié)果了

  g.mu.Lock()

if !c.forgotten {//其實這里是為了保證執(zhí)行完畢之后,對應的key被刪除,Group有一個方法Forget(key string),可以用來主動刪除key,這里是判斷那個方法是否被調(diào)用過,被調(diào)用過則字段forgotten會置為true,如果沒有被調(diào)用過,則在這里把key刪除。

  delete(g.m, key)

  }

  for _, ch := range c.chans {//將執(zhí)行結(jié)果發(fā)送到channel里,這里是給DoChan方法使用的

  ch - Result{c.val, c.err, c.dups > 0}

  }

  g.mu.Unlock()

}

由此看來,其實現(xiàn)是非常簡單的。不得不贊嘆一百來行代碼就實現(xiàn)了功能。

其他

順便附上DoChan方法的使用示例:

func main() {

  var singleSetCache singleflight.Group

  getAndSetCache:=func (requestID int,cacheKey string) (string, error) {

  log.Printf("request %v start to get and set cache...",requestID)

  retChan:=singleSetCache.DoChan(cacheKey, func() (ret interface{}, err error) {

    log.Printf("request %v is setting cache...",requestID)

    time.Sleep(3*time._Second_)

    log.Printf("request %v set cache success!",requestID)

    return "VALUE",nil

   })

  var ret singleflight.Result

  timeout := time.After(5 * time._Second_)

  select {//加入了超時機制

    case -timeout:

      log.Printf("time out!")

      return "",errors.New("time out")

    case ret =- retChan://從chan中取出結(jié)果

      return ret.Val.(string),ret.Err

   }

  return "",nil

  }

  cacheKey:="cacheKey"
  
  for i:=1;i10;i++{

  go func(requestID int) {

     value,_:=getAndSetCache(requestID,cacheKey)

     log.Printf("request %v get value: %v",requestID,value)

   }(i)

  }

  time.Sleep(20*time._Second_)

}

看下DoChan的源碼

func (g *Group) DoChan(key string, fn func() (interface{}, error)) -chan Result {

  ch := make(chan Result, 1)

  g.mu.Lock()

  if g.m == nil {

  g.m = make(map[string]*call)

  }

  if c, ok := g.m[key]; ok {

   c.dups++

c.chans = append(c.chans, ch)//可以看到,每個等待的協(xié)程,都有一個結(jié)果channel。從之前的g.doCall里也可以看到,每個channel都給塞了結(jié)果。為什么不所有協(xié)程共用一個channel?因為那樣就得在channel里塞至少與協(xié)程數(shù)量一樣的結(jié)果數(shù)量,但是你卻無法保證用戶一個協(xié)程只讀取一次。

   g.mu.Unlock()

   return ch

  }

  c := call{chans: []chan- Result{ch}}

  c.wg.Add(1)

  g.m[key] = c

  g.mu.Unlock()

  go g.doCall(c, key, fn)

  return ch
}

到此這篇關(guān)于使用Golang的singleflight防止緩存擊穿的方法的文章就介紹到這了,更多相關(guān)Golang singleflight防止緩存擊穿內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

您可能感興趣的文章:
  • 一篇文章帶你輕松了解C# Lock關(guān)鍵字
  • C#筆試題之同線程Lock語句遞歸不會死鎖
  • C#使用Interlocked實現(xiàn)線程同步
  • C#中使用Interlocked進行原子操作的技巧
  • C#中實現(xiàn)線程同步lock關(guān)鍵字的用法詳解
  • 如何使用C#讀寫鎖ReaderWriterLockSlim
  • C#中的lock、Monitor、Mutex學習筆記
  • C#中l(wèi)ock用法詳解
  • C#中l(wèi)ock死鎖實例教程
  • c#多線程中Lock()關(guān)鍵字的用法小結(jié)
  • c# 如何用lock解決緩存擊穿

標簽:太原 慶陽 西雙版納 貴陽 阿克蘇 調(diào)研邀請 德州 廣西

巨人網(wǎng)絡(luò)通訊聲明:本文標題《使用Golang的singleflight防止緩存擊穿的方法》,本文關(guān)鍵詞  使用,Golang,的,singleflight,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《使用Golang的singleflight防止緩存擊穿的方法》相關(guān)的同類信息!
  • 本頁收集關(guān)于使用Golang的singleflight防止緩存擊穿的方法的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    日韩片之四级片| 综合av第一页| 欧美另类变人与禽xxxxx| 欧美一级网站| 中文字幕亚洲精品在线| 日本精品一区二区三区四区| 久久久久久久久久久久久久免费看| 国产农村妇女毛片精品久久莱园子| 一本加勒比波多野结衣| av在线免费播放网址| 99999精品| 国产成人精品免费看在线播放| 99porn视频在线| 91高跟黑色丝袜呻吟在线观看| 无圣光视频在线观看| 国产美女在线一区二区三区| 国产精品电影一区| 色爱av综合网| 国产69精品久久久久999小说| 亚洲自拍偷拍色片视频| 日韩一级特黄毛片| 成人免费视屏| 久久99久久久| 欧美第一精品| 欧美激情网站在线观看| 狂野欧美激情性xxxx欧美| 国产伦精品一区二区免费| www.天堂av.com| 欧美日韩在线一区二区三区| 久久综合九色综合欧美98| 国产九九在线观看| 最新中文字幕日本| 黑人精品一区| 九一国产在线观看| 天天操天天操天天色天天要| 性欧美hd调教| 国产在线观看a| 亚洲国产精彩中文乱码av| 欧美一级特黄视频| 国产一级片在线播放| 国产91在线免费| 爱福利一区二区| 日本精品久久久久影院| 日韩av网址大全| 成人激情动漫在线观看| 国产精品扒开腿做爽爽爽视频软件| yw193.com尤物在线| 九九精品视频免费| 国产成人精品一区二区三区免费| 成人亚洲精品| 亚洲码欧美码一区二区三区| 成人午夜一级二级三级| 久久精品成人欧美大片古装| 激情综合在线观看| 亚洲美女黄色片| 亚洲精品天堂在线| 日韩夫妻性生活xx| 欧美不卡视频| 日韩欧美精品一区二区三区经典| 成人动漫视频在线观看免费| 色屁屁草草影院ccyy.com| 国产成人亚洲综合91精品| 亚洲在线播放| 国产精品久久久久久久小唯西川| 在线看视频不卡| 在线观看欧美日韩电影| 91国内揄拍国内精品对白| 99色这里只有精品| 激情小视频在线| 天堂在线中文资源| 五月天av在线播放| 日韩美女视频在线观看| aa日韩免费精品视频一| 欧美一级色片| 性欧美极品另类| 狠狠色2019综合网| aaa大片在线观看| 亚洲综合123| 国产激情偷乱视频一区二区三区| 蜜桃视频网站在线| 欧美男生操女生| 天天激情综合| 亚洲免费人成在线视频观看| 欧美日韩国产123区| 亚洲欧美综合国产精品一区| 开心快乐六月丁香婷婷| 国产亚洲成av人片在线观黄桃| 亚洲高清影视| 亚洲国产精品专区久久| 成人午夜免费视频| 日韩三区在线| 亚洲视频在线播放免费| 不卡视频观看| 在线观看亚洲国产| 亚洲 欧美 激情 另类| 亚洲欧美另类综合偷拍| 国产毛片毛片毛片| 国产理论片免费观看| 日韩av在线第一页| 日韩电影一区二区三区四区| 91精品美女在线| 精品视频一区二区在线观看| 国产一区在线免费观看| av在线电影网| 中文字幕av免费观看| 亚洲视频在线视频| 无罩大乳的熟妇正在播放| 国产伦精品一区二区三区免费视频| 在线观看免费p片视频网站地址| 在线观看亚洲免费视频| 日韩一区在线播放| www.麻豆| 欧美精品一卡| 欧美日韩一区二区视频在线| 五月六月丁香婷婷| 免费在线看污| 亚洲成年电人电影网站| 欧美hdsex| 青青草97国产精品麻豆| 欧美精品一二三四| 精品福利av导航| 亚洲最大成人av| xxxx成人| 中文字幕66页| 成人看片人aa| 日韩在线一卡二卡| 国产一级一片免费播放放a| 亚洲国产天堂久久国产91| 国产永久免费高清在线观看| 午夜精品三级久久久有码| 国产91精品入口17c| 国产福利电影在线观看| 日韩精品一卡| 伊人精品视频| 在线黄色网页| 日韩av手机在线播放| 久草成人在线视频| 国产精品日本精品| 久久av秘一区二区三区| 三上悠亚在线资源| 日本韩国欧美超级黄在线观看| 中文字幕伦av一区二区邻居| 深夜福利视频一区| 激情久久久久久久久久久久久久久久| 91成人国产综合久久精品| 亚洲1卡2卡3卡4卡乱码精品| 欧美亚洲在线播放| 成人黄页在线观看| 两个人看的无遮挡免费视频| 国产中文字幕一区| 国产一级做a爰片久久| 亚洲视频 中文字幕| 男女男精品视频网站| 先锋影音日韩| 欧美极度另类| 一区一区视频| 狠狠干夜夜操| 91麻豆精品国产91久久久资源速度| 欧美伦理片在线观看| 国产综合色精品一区二区三区| 国产精品视频一区二区三区四蜜臂| 91国内精品在线视频| 欧美日韩国产高清一区| 国产精品久久久久久久久久齐齐| 国产视频每日更新| www.天天射.com| 欧美调教网站| 少妇性色午夜淫片aaa播放| 国产免费无遮挡吸奶头视频| 91国偷自产一区二区三区观看| www.成人在线观看| 国产欧美日韩精品丝袜高跟鞋| 欧美日韩在线播放一区二区| 一级在线观看视频| 久草精品在线播放| 美女网站视频一区| 五月婷婷六月丁香| 久久a级毛片毛片免费观看| 成人性a激情免费视频| 91短视频版在线观看www免费| 亚洲欧洲日韩一区二区三区| 欧美日韩国产在线观看| a级毛片免费观看在线| 中文字幕视频二区| 国产精品久久久久久久小唯西川| 欧美成人激情视频免费观看| 久久久久久激情| 99在线精品视频| 久久中文字幕免费| 亚洲成人av高清| 久久久www免费人成黑人精品| 一区av在线播放| 日本一区二区三区久久| 精品成人自拍视频| 中文字幕2022永久在线| 91麻豆成人精品国产免费网站| 欧美在线日韩在线| 久久久www免费人成精品| 久久久久se| 韩日中文字幕| 久久国产视频精品| 免费无码毛片一区二三区| 久久久99精品免费观看| 久热在线中文字幕色999舞| 91视频欧美| www.91在线| 一本大道av一区二区在线播放| 97在线国产视频| 亚洲一区二区三区精品动漫| 精品网站在线| 久久国产精品精品国产色婷婷| 亚洲线精品一区二区三区| 在线精品一区| 欧美成人精品一区二区男人看| 国语对白做受xxxxx在线中国| 亚洲男人的天堂在线视频| 国精产品一区二区三区| 在线综合欧美| 香蕉视频网站在线播放| 日韩在线观看a| 亚洲制服丝袜在线播放| 国产福利小视频在线观看| 亚洲精品蜜桃久久久久久| 亚洲成人激情综合网| 欧美 日韩 激情| 69xx绿帽三人行| 中文在线永久免费观看| 亚洲午夜精品一区二区三区他趣| 精品人妻一区二区三区三区四区| 美女网站色精品尤物极品姐弟| 特级西西444www| 欧美一区二区在线视频| 日本在线视频观看| 内衣办公室在线| 蜜臀久久99精品久久久画质超高清| 美乳视频一区二区| 深夜福利av| 久久亚洲精品国产精品紫薇| 久久综合九色综合欧美就去吻| 乱码第一页成人| 中文字幕av片| 亚洲免费观看高清在线观看| 91在线公开视频| 蜜桃久久av一区| 国产免费裸体视频| 亚洲不卡1卡2卡三卡2021麻豆| 伊人伊人av电影| 国产精品色哟哟网站| 青草视频.com| 国产精品免费观看高清| 中文字幕xxxx| 亚洲国产91色在线| 少妇人妻好深好紧精品无码| av影片免费在线观看| 亚洲国产成人久久| 国产精品国产三级欧美二区| 国产精品夜间视频香蕉| 国产午夜三区视频在线| 伦理天堂电影| 夜夜添无码一区二区三区| 亚洲精品国产综合久久| 日韩天堂在线观看| 在线不卡免费欧美| 一卡二卡三卡在线观看| 激情视频在线观看一区二区三区| 中文字幕av观看| 国产精品99| 黄色片在线免费观看| 你懂的视频在线播放| 视频一区中文| 日本免费www| 无码av免费精品一区二区三区| 精品亚洲成a人片在线观看| 免费成人美女女在线观看| 国产精品嫩草影院俄罗斯| 91看片在线| 9久草视频在线视频精品| 日本不卡的三区四区五区| 亚洲高清电影| 日本一区二区三区视频在线看| 成人爱爱网址| 欧美特黄aaaaaa| 欧美日韩精品一区二区三区蜜桃| 欧美xxxxxx| 亚洲精品大片| 国产一级精品在线| 亚洲免费精品视频| 久久免费看毛片| 国产一区二区色| 亚洲依依成人| 最近免费观看高清韩国日本大全| 亚洲男人天堂2023| 小说区图片区图片区另类灬| 韩国毛片一区二区三区| 91亚洲精品视频在线观看| 欧美在线精品一区| 大黑人交xxx极品hd| 欧美人与牲动交xxxxbbbb| 成人疯狂猛交xxx| 久久久精品电影| 一本色道久久88| 国产又粗又长又爽| 先锋影音av中文字幕| 亚洲黄色在线播放| 黄色短视频在线观看| 亚洲色图偷窥| 欧美一区二区三区成人片在线| 久久综合狠狠综合久久激情| 国产精品观看在线亚洲人成网| 久久久久久久久久久久久久久国产| 天海翼中文字幕| 中文字幕这里只有精品| 亚洲成人精品影院| zzjj国产精品一区二区| 中文在线最新版地址| 蜜臀久久久久久999| 黄网站在线观看永久免费| 91影院在线播放| 精品9999| 精品一区二区三区免费观看| 久久国产毛片| 免费看的av| 欧美永久精品| 日韩免费电影一区| 精品推荐国产麻豆剧传媒| av在线网址导航| 亚洲福利av在线| 999精品久久久|