原来sync.Once还能这么用

简介: 原来sync.Once还能这么用

介绍


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

Once is an object that will perform exactly one action

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

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


缓存击穿


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

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

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

就像这样


1668507893683.jpg


图片来源:[1]


singleflight


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


1668507912686.jpg


1668507920859.jpg


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

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

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


1668507947074.jpg


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

代码并不复杂


自定义singleflight


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

1668507994363.jpg

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

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

1668508007556.jpg

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


总结


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


附录


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

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

相关文章
|
安全 Java 调度
多线程锁sync+lock使用,@Async使用
多线程锁sync+lock使用,@Async使用
多线程锁sync+lock使用,@Async使用
|
11月前
|
SQL 关系型数据库 MySQL
|
JavaScript
彻底理解sync的用法
彻底理解sync的用法
133 0
|
程序员 Go
你真的了解 sync.Once 吗
你真的了解 sync.Once 吗
148 0
|
存储 JSON 安全
​sync.Pool 使用
​sync.Pool 使用
134 0
|
存储 缓存 数据处理
完全揭秘log file sync等待事件
什么是log file sync等待事件呢?在一个提交(commit)十分频繁的数据库中,一般会出现log file sync等待事件,当这个等待事件出现在top5中,这个时侯我们需要针对log file sync等待事件进行优化,一定要尽快分析并解决问题,否则当log file sync等待时间从几毫秒直接到20几毫秒可能导致系统性能急剧下降,甚至会导致短暂的挂起。
完全揭秘log file sync等待事件
|
安全 Java Go
sync
sync包有以下几个内容: (1)sync.Pool 临时对象池 (2)sync.Mutex 互斥锁 (3)sync.RWMutex 读写互斥锁 (4)sync.WaitGroup 组等待 (5)sync.Cond 条件等待 (6)sync.Once 单次执行 一、临时对象池 Pool可以用来存储临时对象,其实原理就是这个对象池指向对象变量,以防没有变量指向对象时,被GC所回收。
1329 0