原来sync.Once还能这么用

介绍

sync.Once估计大家都不陌生,官方介绍中,

Once is an object that will perform exactly one action

正是因为这个特性,Once常常被用于单例对象的初始化场景。

也正是因为这个特性,其实它还能做一些其他的事情。


缓存击穿

日常背诵八股文,我相信你们对缓存击穿这个词特别熟悉。

缓存击穿一般代指热点key缓存失效(到期|删了),同一时刻大量对热点key的并发请求。缓存找不到数据,所有请求都打入到DB层。此时,身为开发的你,明天和意外就不知道哪个先到了。

为了防止这种情况发生,针对相同key的请求,只需要一个请求(A)到达DB层取数据,其他请求等待A通知就行了。

就像这样,

2fa1d742ae56c2d807e7ffbb7d630b5c.png

                                图片来源:[1]

singleflight

Go里有很多防缓存击穿的工具,比如singleflight库。

f8ea4f4c309c1fd2cef5dcf6a3d5c56c.png

8982ffb2784bd922deb88b5d0b5f09bd.png

通过上面简单的代码大概能看出,其实就是对key做了缓存。

把一个key对应call结构存储在map中。保证只有一个key真正执行fn()服务 ,其他请求则通过sync.waitGroupwait等待结果。

至于g.docall(c,key,fn)

3681df5ce2ab04d4aad9b0ead2544672.png

当带着全村人希望的那个请求,获取到数据,给对应keycall赋值,最终执行done,通知等待这个key全村的村民获取数据。

代码并不复杂。

自定义singleflight

我们也可以实现一个简易版本的。

8b6387b936a59759c22acdf8a8a876bc.png

代码整体不难,主要的点在于我们是通过通道来实现通知自家兄弟取数据。

最后,让我们使用Once来达到同样的效果,不然标题不白起了嘛。

05bc7b6e691506d0e9dc1e5c83b886f1.png

上面核心代码都写出来了,实际开发中需要对请求资源做一些超时控制等操作。


总结

平常对Once的使用只停留在初始化工作上,而弱化了它的使用场景。对于其他工具也是一个道理,这就需要去积累和挖掘了。

附录

[1]https://medium.com/codex/caching-system-stability-766bf5fff69f

https://blog.chuie.io/posts/synconce/

推荐阅读:

sync.Once化作一道光让我顿悟

资料下载

点击下方卡片关注公众号,发送特定关键字获取对应精品资料!

  • 回复「电子书」,获取入门、进阶 Go 语言必看书籍。

  • 回复「视频」,获取价值 5000 大洋的视频资料,内含实战项目(不外传)!

  • 回复「路线」,获取最新版 Go 知识图谱及学习、成长路线图。

  • 回复「面试题」,获取四哥精编的 Go 语言面试题,含解析。

  • 回复「后台」,获取后台开发必看 10 本书籍。

对了,看完文章,记得点击下方的卡片。关注我哦~ 👇👇👇

如果您的朋友也在学习 Go 语言,相信这篇文章对 TA 有帮助,欢迎转发分享给 TA,非常感谢!52368a399a4fe8b4ccae9fbd38b45f18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值