东东's Blog

东东's Blog

马上订阅 东东's Blog RSS 更新: https://blog.yasking.org/atom.xml

Golang Singleflight 防缓存击穿验证示例

2024年8月30日 21:00

Singleflight 示例一:基础用法

多次请求共享一次请求的结果

package main

import (
    "fmt"
    "time"

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

func main() {
    var group singleflight.Group

    // A function that simulates an expensive operation
    expensiveOperation := func(key string) (interface{}, error) {
        time.Sleep(2 * time.Second) // Simulate delay
        return fmt.Sprintf("Result for %s", key), nil
    }

    key := "unique-key"

    // Start multiple goroutines that call the expensive operation through singleflight
    for i := 0; i < 3; i++ {
        go func(id int) {
            result, err, shared := group.Do(key, func() (interface{}, error) {
                return expensiveOperation(key)
            })

            if err != nil {
                fmt.Printf("Goroutine %d received error: %v\n", id, err)
            } else {
                fmt.Printf("Goroutine %d received result: %v (shared: %v)\n", id, result, shared)
            }
        }(i)
    }

    // Wait for goroutines to finish
    time.Sleep(3 * time.Second)
}

输出

Goroutine 0 received result: Result for unique-key (shared: true)
Goroutine 2 received result: Result for unique-key (shared: true)
Goroutine 1 received result: Result for unique-key (shared: true)

Singleflight 示例二:解决缓存击穿

这个示例集成了数据库、缓存和 HTTP API,有以下几个关键点:

  1. 提供了 [GET] /gold/prcie[POST] /gold 两个接口模拟黄金价格的更新与查询
  2. 缓存由更新接口在更新数据后设置失效,由查询接口负责构建
  3. 高并发查询场景,缓存失效的一瞬间,面临多个请求会同时访问数据库,即缓存击穿
  4. 高并发查询场景,使用 Singleflight 避免缓存击穿
  5. 查看访问数据库的次数,看到 Singleflight 在这个场景中的重要作用

创建表作为数据源

-- 创建表
CREATE TABLE gold_realtime_prices (
    id SERIAL PRIMARY KEY,
    price NUMERIC NOT NULL,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 插入一条模拟数据
INSERT INTO gold_realtime_prices (price) VALUES (575.25);

代码示例

通关环境变量设置...

剩余内容已隐藏

查看完整文章以阅读更多