登录
首页 >  Golang >  Go教程

## Singleflight并发获取数据时,如何避免访问穿透问题?

时间:2024-10-25 14:10:15 217浏览 收藏

一分耕耘,一分收获!既然打开了这篇文章《## Singleflight并发获取数据时,如何避免访问穿透问题?》,就坚持看下去吧!文中内容包含等等知识点...希望你能在阅读本文后,能真真实实学到知识或者帮你解决心中的疑惑,也欢迎大佬或者新人朋友们多留言评论,多给建议!谢谢!

## Singleflight并发获取数据时,如何避免访问穿透问题?

并发获取数据的singleflight使用问题

在使用singleflight并发获取数据时,多个请求同时访问数据库的问题。

问题代码:

package main

import (
    "errors"
    "log"
    "sync"
    "golang.org/x/sync/singleflight"
)

var errornotexist = errors.new("not exist")
var g singleflight.group

func main() {
    var wg sync.waitgroup
    cpu_amount := 4
    wg.add(cpu_amount)

    for i := 0; i < cpu_amount; i++ {
        go func() {
            defer wg.done()
            data, err := getdata("key")
            if err != nil {
                log.print(err)
                return
            }
            log.println(data)
        }()
    }
    wg.wait()
}

func getdata(key string) (string, error) {
    data, err := getdatafromcache(key)
    if err == errornotexist {
        v, err, _ := g.do(key, func() (interface{}, error) {
            return getdatafromdb(key)
        })
        if err != nil {
            log.println(err)
            return "", err
        }
        data = v.(string)
    } else if err != nil {
        return "", err
    }
    return data, nil
}

func getdatafromcache(key string) (string, error) {
    return "", errornotexist
}

func getdatafromdb(key string) (string, error) {
    log.printf("get %s from database", key)
    return "data", nil
}

问题原因:

singleflight仅避免大量并发的访问,即在多个协程同时运行的情况下才满足“同时”的条件。

在给定代码中,getdatafromdb函数在输出信息后就结束了,这意味着如果前面三个协程都已执行完毕,第四个协程来执行时,就不能满足“同时”性,因此不会进入singleflight的do函数,从而导致访问穿透。

解决方案:

为了解决此问题,可以修改getdatafromdb函数,在返回数据之前引入延迟,以确保所有协程同时运行。例如:

func getDataFromDB(key string) (string, error) {
    log.Printf("get %s from database", key)
    time.Sleep(time.Millisecond * 500) // 引入延迟
    return "data", nil
}

到这里,我们也就讲完了《## Singleflight并发获取数据时,如何避免访问穿透问题?》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

相关阅读
更多>
最新阅读
更多>
课程推荐
更多>