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

Once is an object that will perform exactly one action

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

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

缓存击穿

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

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

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

就像这样,

图片来源:见附录1

singleflight

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

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

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

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

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

代码并不复杂。

自定义singleflight

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

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

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

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

总结

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

附录

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

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

给网管个星标,第一时间吸我的知识 

原来sync.Once还能这么用相关推荐

  1. golang sync.Map和map+mutex性能比较

    目录 测试环境 测试代码 运行指令 测试结果 结论 测试环境 goos: linux goarch: amd64 go version go1.14 linux/amd64 Run on (8 X 2 ...

  2. cin.clear、cin.sync()与cin.ignore()

    一.cin.clear().cin.sync() cin.clear()是用来更改cin的状态标示符的. cin.sync()是用来清除缓存区的数据流的. 如果标示符没有改变那么即使清除了数据流也无法 ...

  3. iOS progressive Web App (PWA) 技术

    随着 iOS 11.3 的发布,iOS + PWA 的时代终于来了!本文对 iOS 中 PWA 的能力进行了分析,并将其与 iOS 上的 Native App.Android 上的 PWA 进行了深度 ...

  4. 33张图剖析ReentrantReadWriteLock源码

    本文大纲如下 纵观全局 我的英文名叫ReentrantReadWriteLock(后面简称RRW),大家喜欢叫我读写锁,因为我常年混迹在读多写少的场景. 读写锁规范 作为合格的读写锁,先要有读锁与写锁 ...

  5. Java 动态代理机制分析及扩展--转

    http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/#icomments http://www.ibm.com/developerworks/c ...

  6. imessage_如何在所有Apple设备上同步您的iMessage

    imessage Messages in iCloud lets you sync your iMessages across all of your Apple devices using your ...

  7. 几款效率神器助你走上人生巅峰

    一.背景 在我的工作和生活中,我一直都很注重效率工具的使用,这么些年下来也积累好几款很不错,但是又不为大多数人所熟知的软件工具,我用起来得心应手,很不错.那我就像在此给大家做个分享,希望你们都能多多提 ...

  8. 锐界机器人_2019款锐界智能家居远程控制使用介绍

    2019款 经过场地的绕圈测试,传祺GA6的制动系统依旧保持良好的响应速度,而且制动力输出没有虚位,从踩上制动踏板初段就能得到明显的制动力反馈. 车头重量给前脸极大的压力,不过在极限过弯的情况下,悬架 ...

  9. LED显示驱动(三):显示驱动底层学习小结

    一.DE硬件架构 显示系统可划分为三个层面,驱动层,框架层及底层. 底层与图形硬件相接,将上层配置的功能参数转换成硬件需要的参数,配置相应寄存器. 显示框架层对底层进行抽象封装成功能模块. 驱动层对外 ...

最新文章

  1. Java Remote Debug(远程调试)
  2. 企业分布式微服务云SpringCloud SpringBoot mybatis (二)Spring Boot属性配置文件详解...
  3. 排错经历:openstack搭建dashboard进入输入帐号密码登录后报错
  4. Linux的Find使用
  5. RISC与CISC比较
  6. 利用python爬虫(part9)--Xpath与谓词の爱
  7. Effective Java~43. 方法引用优于Lambda
  8. 项目微管理17 - 双赢
  9. linux简单命令3---帮助命令
  10. vs2005下使用ASPNetPage分页的例子1
  11. Tomcat使用Tomcat Native和APR
  12. CStdioFile UNICODE编译 读取中文汉字乱码 .
  13. 小白学VUE——实现抖音时钟(NPM方式)
  14. Win10更改用户账户、appdata和ProgramData的默认存储路径
  15. ThreadPoolExecutor线程池 —————— 开开开山怪
  16. MySQL | 自定义函数
  17. ajax传递数组到后台时为空,ajax传递数组,后台接收为null解决方法
  18. Q3c「最大可以支持多大容量的硬盘?」AirDisk
  19. 盒子科技笔试Java_丰巢科技 Java高级笔试面试题 PDF 下载
  20. 法兰(工具零件)与法兰圈_百度百科

热门文章

  1. centos7 改虚拟网卡名称
  2. 当快递员也学会了“跑路”,消费者如何捍卫自己的权益?
  3. centos7新机器需要安装的。。。。。。
  4. JAVA入门到精通-第6讲-成员属性-成员方法
  5. 十大面试问题解惑,秒杀一切HR、技术面试。iOS程序员必读!
  6. 三十六、【减小apk包的体积】
  7. 有关 input默认宽度
  8. [转]Java Web基础——Action+Service +Dao三层的功能划分
  9. 如何在while和for中使用ssh
  10. Dubbo的Javassist代理