Singleflight介绍

缓存击穿 对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑一个问题:缓存被“击穿”的问题,这个和缓存雪崩的区别在于这里针对某一key缓存,前者则是很多key。 缓存在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。 我在 go-redis/cache 中发现了库使用了 singleflight , 经过查阅资料,了解了 这个库的主要作用就是将一组相同的请求合并成一个请求,实际上只会去请求一次,然后对所有的请求返回相同的结果。 这样会大大降低数据库的压力。 singleflight 使用 函数签名 1 2 3 4 5 6 7 8 9 10 11 12 13 type Group struct { mu sync.Mutex // protects m m map[string]*call // lazily initialized } // Do 执行函数, 对同一个 key 多次调用的时候,在第一次调用没有执行完的时候 // 只会执行一次 fn 其他的调用会阻塞住等待这次调用返回 // v, err 是传入的 fn 的返回值 // shared 表示是否真正执行了 fn 返回的结果,还是返回的共享的结果 func (g *Group) Do(key string, fn func() (interface{}, error)) (v interface{}, err error, shared bool) // DoChan 和 Do 类似,只是 DoChan 返回一个 channel,也就是同步与异步的区别 func (g *Group) DoChan(key string, fn func() (interface{}, error)) <-chan Result // Forget 用于通知 Group 删除某个 key 这样后面继续这个 key 的调用的时候就不会在阻塞等待了 func (g *Group) Forget(key string) 示例 接下来我们来讲解一个简单的例子,我们来看看 singleflight 的使用方式,先来看一个简单的例子:...

June 18, 2022&nbsp;·&nbsp;2 min&nbsp;·&nbsp;overstarry

Go并发Sync.Once解析

在 go 语言中我们可以使用 sync.Once 对象来实现函数方法只执行一次的功能。 简单代码示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package main import ( "fmt" "sync" ) func main() { var ( o sync.Once wg sync.WaitGroup ) for i := 0; i < 10; i++ { wg.Add(1) go func(i int) { defer wg.Done() o.Do(func() { fmt.Printf("hello %d\n", i) }) }(i) } wg....

June 3, 2022&nbsp;·&nbsp;2 min&nbsp;·&nbsp;overstarry

Go截取视频某一帧图片

前言 最近遇到一个需求,需要截取视频的某一帧图片作为视频封面。我搜寻了相关资料,在 go 语言端常见的有两种做法,1)使用 opencv 的 go 绑定库,2)使用 ffmpeg 的 go 绑定库。 这里我打算使用第二种方法,使用 ffmpeg 的 go 绑定库。 ffmpeg 介绍 FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件)。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多codec都是从头开发的。 FFmpeg在Linux平台下开发,但它同样也可以在其它操作系统环境中编译运行,包括Windows、Mac OS X等。 FFmpeg项目由以下几部分组成: FFMpeg 视频文件转换命令行工具,也支持经过实时电视卡抓取和编码成视频文件。 FFServer 基于HTTP(RTSP正在开发中)用于实时广播的多媒体服务器,也支持时间平移. FFplay 用SDL和FFmpeg库开发的一个简单的媒体播放器. libavcodec 一个包含了所有FFmpeg音视频编解码器的库.为了保证最优性能和高可复用性,大多数编解码器从头开发的. libavformat 一个包含了所有的普通音视格式的解析器和产生器的库 解决 1 安装 ffmpeg 浏览器访问 https://ffbinaries.com/downloads 根据你的系统安装 ffmpeg 2 安装 ffmpeg 的 go 绑定库 这里我使用了 github.com/u2takey/ffmpeg-go 这个项目,它是一个绑定库,可以在 go 语言端使用 ffmpeg 命令行工具。 3 编写代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 package main import ( "bytes" "fmt" "github....

May 28, 2022&nbsp;·&nbsp;2 min&nbsp;·&nbsp;overstarry

Go errgroup

我们知道在 go 语言中很容易开启携程进行并发任务, 但是如何处理并发过程中的错误是非常棘手的,接下来我就来介绍 errgroup 的用法。 errgroup errgroup 包里主要是一个结构体和相应的方法,它可以让你在并发任务中处理错误。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 type Group struct { // context 的 cancel 方法 cancel func() // 复用 WaitGroup wg sync.WaitGroup sem chan token // 用来保证只会接受一次错误 errOnce sync.Once // 保存第一个返回的错误 err error } func WithContext(ctx context.Context) (*Group, context.Context) func (g *Group) done() func (g *Group) Wait() error func (g *Group) Go(f func() error) func (g *Group) TryGo(f func() error) bool func (g *Group) SetLimit(n int) 通过 WithContext 可以创建一个可以取消的 Group,当然除此之外也可以零值的 Group 也可以直接使用,但是出错之后就不会取消其他的 goroutine 了....

May 21, 2022&nbsp;·&nbsp;2 min&nbsp;·&nbsp;overstarry

Go统计代码测试覆盖率

今天来讲一讲如何统计 go 代码的测试覆盖率,主要是 cover 命令。 cover 基本用法 1 先简单写个函数和相应的测试,代码如下: 1 2 3 4 5 6 func Max(a, b int) int { if a > b { return a } return b } 这个函数就是简单的比较大小,如果 a > b,返回 a,否则返回 b。 测试代码如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package main import "testing" func TestMax(t *testing....

April 16, 2022&nbsp;·&nbsp;2 min&nbsp;·&nbsp;overstarry