细聊Go高级并发用法-singleflight

44 阅读3分钟

**欢迎关注我的wechat公众号:程序员技术成长之路 **

什么是singleflight

Singleflight是Google开源的一个Go语言库,主要用于控制对共享资源的重复请求,防止服务器被同时高并发访问所引发的"雪崩"问题。具体来说,当多个相同的请求(例如访问同一个数据或地址)在同一时间发生时,Singleflight会将这些请求合并为一个。实际上,只有一个请求会被执行,然后这个请求的结果将被所有其他的请求共享。

这个库的主要应用场景是缓存系统。例如,当有大量用户同时请求同一资源时,如果没有Singleflight,服务器可能需要执行大量的数据库查询或其他高负荷操作。但有了Singleflight,服务器只需执行一次查询或操作,然后将结果返回给所有请求。这大大减轻了服务器的负载。

未命名文件.jpg 主要作用

     Singleflight 的主要作用是防止对共享资源的多次重复请求,特别是在高并发的场景中。这样可以避免不必要的重复工作,减轻服务器负载,提高系统的性能和效率。    当有多个相同的请求同时发生时,Singleflight 会把这些请求合并为一个,只执行一次请求操作(如数据库查询,HTTP 请求等),然后把这个结果共享给所有的请求。这就避免了相同的请求被重复执行多次,提高了系统的性能。        此外,Singleflight 还可以帮助抑制雪崩效应,当系统中某一部分因过载而出现问题时,不会影响到整个系统的运行。

Go如何使用

var g singleflight.Group

func someExpensiveOperation() (interface{}, error) {
   time.Sleep(1 * time.Second)
   return "foo", nil
}
func main() {
   for i := 0; i < 5; i++ {
      go func() {
         v, err, _ := g.Do("some_key", someExpensiveOperation)
         if err != nil {
            fmt.Printf("error: %v\n", err)
            return
         }
         fmt.Printf("got: %v\n", v)
      }()
   }
   time.Sleep(2 * time.Second)
}

在这个例子中,someExpensiveOperation 代表一项消耗很大的操作,比如一个复杂的数据库查询或者一个网络请求。当这个函数被并发调用多次时,singleflight 会保证这个函数只执行一次,然后各个并发的调用者将获得相同的返回结果。

        注意"some_key"这个参数,singleflight 使用这个 key 去区分不同的请求,只有在相同的 key 的访问中,才会合并请求。

源码解释

Group是Singleflight的主要结构,它有一个锁和一个map,用于存储所有的请求(call)。锁保证了对同一资源的访问在同一时间只能由一个进程进行。

   Do方法是实现请求合并的核心,它首先会检查当前的请求(key表示的请求)是否正在被处理,如果是则等待处理结束,然后返回结果,如果不是则执行请求(fn),并将结果存储在call结构中,供之后的请求使用。