golang,go,博客,开源,编程

认识SingleFlight合并请求

Published on with 0 views and 0 comments

在 Go 语言中,SingleFlightgolang.org/x/sync/singleflight 包中的一个工具,旨在避免对同一资源或任务发起重复的请求。它的主要作用是合并多个相同的并发请求,使得这些请求只会执行一次,并且共享相同的结果,从而减少系统的负载,避免重复的工作。

主要用途

SingleFlight 主要用于场景中,当多个 goroutine 发起对同一资源或任务的重复请求时,只会有一个请求被真正处理,其他请求会等待这个请求完成,并共享相同的结果。

典型应用场景

  • 缓存穿透:当多个请求访问相同的缓存键,而该键的值未命中缓存时,多个并发请求会导致重复的计算或数据库查询。SingleFlight 可以通过合并这些请求,只执行一次查询,其他请求则等待并返回相同的结果。
  • 网络请求合并:多个相同的网络请求可能会同时到达,可以合并这些请求,减少请求次数。

SingleFlight 的工作原理

  • SingleFlight 通过维护一个正在进行中的请求的集合来避免重复请求。
  • 当多个请求到达时,SingleFlight 会把它们合并到一个请求上,只有一个请求会被真正执行。
  • 其他请求会等待这个请求执行完毕,并共享相同的结果。

主要函数

  • Do(key string, fn func() (interface{}, error)) (interface{}, error):这个方法会执行给定的 fn 函数,但如果已经有一个相同 key 的请求正在执行,它会等待这个请求的结果,而不会重复执行函数。

示例代码

假设你有一个函数需要从外部服务获取数据,而多个并发请求可能会请求相同的数据。使用 SingleFlight 可以确保每个数据只请求一次,避免重复请求。

示例:

package main

import (
	"fmt"
	"log"
	"sync"
	"time"

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

// 模拟一个耗时的操作(如查询数据库、外部API请求)
func fetchDataFromServer() (interface{}, error) {
	// 模拟延时
	time.Sleep(2 * time.Second)
	return "Fetched Data", nil
}

func main() {
	var g singleflight.Group
	var wg sync.WaitGroup

	// 模拟多个请求
	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()

			// 使用 SingleFlight 合并相同的请求
			result, err, _ := g.Do("uniqueKey", func() (interface{}, error) {
				return fetchDataFromServer()
			})
			if err != nil {
				log.Printf("Error fetching data: %v", err)
				return
			}

			// 打印结果
			fmt.Printf("Goroutine %d received result: %v\n", i, result)
		}(i)
	}

	// 等待所有 goroutine 完成
	wg.Wait()
}

代码解读:

  1. 定义耗时操作 fetchDataFromServer:模拟一个耗时的操作,可能是查询数据库或调用外部 API。
  2. 使用 singleflight.Group 来合并请求:每次调用 g.Do,都传入一个唯一的 key(这里是 "uniqueKey")。对于相同的 key,如果有请求正在执行,其他请求会等待并复用该请求的结果。
  3. 并发请求:启动多个 goroutine,模拟多个并发请求。因为请求相同的数据(相同的 key),所以只有第一个请求会实际执行 fetchDataFromServer,其他请求会等待并共享该结果。
  4. 输出:尽管我们启动了 5 个并发请求,但是只有第一次请求会发起实际的计算(fetchDataFromServer),后续的请求会等待第一次请求的结果。

SingleFlight 的优势

  1. 减少重复请求:多个相同的请求只会执行一次,减少了计算或网络请求的负担。
  2. 节省资源:避免了重复的工作(比如重复的数据库查询或网络请求),节省了 CPU、内存和带宽资源。
  3. 简化并发控制:提供了一个简单的 API 来合并并发请求,无需手动管理锁或并发控制。

SingleFlight 的局限

  • 适用于请求相同的任务。如果请求的任务不同,它不能合并。
  • 如果任务本身是非常快速的或者请求非常少,使用 SingleFlight 可能会导致不必要的复杂性,反而影响性能。

总结

SingleFlight 是一个非常实用的工具,能够有效地避免对相同数据或资源的重复请求,合并多个相同的请求,使得多个并发请求可以共享一个计算或请求的结果。通过减少重复工作,它帮助提高了系统的性能,降低了负载。


标题:认识SingleFlight合并请求
作者:mooncakeee
地址:http://blog.dd95828.com/articles/2025/01/07/1736229279578.html
联系:scotttu@163.com