看看 Singleflight

在看前辈的代码时,发现了一个缓存放穿透的处理,好奇就点进去看了,发现代码意外的少,于是就研究起来,为数不多我能看明白的源码T-T

源码地址:https://cs.opensource.google/go/x/sync/+/036812b2:singleflight/singleflight.go

看看 Singleflight
type call struct {
   wg sync.WaitGroup
   val interface{}
   err error
   forgotten bool
   // 统计被拦截调用fn的请求数,可以不关心
   dups  int
   // DoChan 中用的,先不关心
   chans []chan 0
}

// 调用fn()
func (g *Group) doCall(c *call, key string, fn func() (interface{}, error)) {
   normalReturn := false
   recovered := false

   defer func() {

      if !normalReturn && !recovered {
         c.err = errGoexit
      }

      c.wg.Done()
      g.mu.Lock()
      defer g.mu.Unlock()
      if !c.forgotten {
         delete(g.m, key)
      }

      if e, ok := c.err.(*panicError); ok {
         if len(c.chans) > 0 {
            go panic(e)
            select {}
         } else {
            panic(e)
         }
      } else if c.err == errGoexit {
      } else {
         for _, ch := range c.chans {
            ch  0}
         }
      }
   }()

   func() {
      defer func() {
         // 个人理解:当fn() panic的时候在这里recover,预防死锁
         if !normalReturn {
            if r := recover(); r != nil {
               c.err = newPanicError(r)
            }
         }
      }()

      c.val, c.err = fn()
      normalReturn = true
   }()

   if !normalReturn {
      recovered = true
   }
}

// 个人理解:释放这个key,使更多的请求调用请求到下游服务。当调用下游服务需要消耗大量时间时,
// 并发环境下,在调用下游服务时,只有一个请求会调用到下游服务,其他请求会被阻塞,当这个请求失败时,会严重影响效率。
// 如果启动Goroutine 定时Forget,则会释放更多的请求到下游服务,提高并发和容错。
func (g *Group) Forget(key string) {
   g.mu.Lock()
   if c, ok := g.m[key]; ok {
      c.forgotten = true
   }
   delete(g.m, key)
   g.mu.Unlock()
}

Original: https://www.cnblogs.com/weirwei/p/15404173.html
Author: weirwei
Title: 看看 Singleflight

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/591864/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 数字签名和数字证书是什么

    定义 数字签名和数字证书的区别是什么?数字证书是由权威机构CA证书授权中心发行的,能提供在Internet上进行身份验证的一种权威性电子文档。而数字签名是一种类似写在纸上的普通的物…

    数据库 2023年6月11日
    0122
  • Yapi安装配置(CentOs)

    环境要求 nodejs(7.6+)mongodb(2.6+)git 准备工作 清除yum命令缓存 sudo yum clean all 卸载低版本nodejs yum remove…

    数据库 2023年6月11日
    0114
  • 牛客SQL刷题第一趴——非技术入门基础篇

    id device_id gender age university province 1 2138 male 21 北京大学 Beijing 2 3214 male 复旦大学 S…

    数据库 2023年6月16日
    0114
  • MySQL专题1: 字段和索引

    MySQL中存在 float, double 等非标准数据类型, 也有 decimal 这种标准数据类型 其区别在于: float, double等非标准类型在DB中保存的是近似值…

    数据库 2023年5月24日
    0117
  • SQL函数-聚合函数

    聚合函数 聚合函数是对一组数据进行汇总输出的函数。 输入:一组数据集合输出:单个值 举例:返回一组数据的最大值、平均数、最小、方差等操作。 常见函数举例: 1,AVG函数:返回一组…

    数据库 2023年6月16日
    0117
  • Java处理.tif或.tiff图片

    前言 Java将图片读取到内存用的是ImageIO,默认可以处理的图片格式如下: undefined ImageIO.getWriterFileSuffixes() //此方法返回…

    数据库 2023年6月9日
    0101
  • day04-3服务器推送新闻

    多用户即时通讯系统04 4.编码实现03 4.7功能实现-服务器推送消息功能实现 4.7.1思路分析 服务器推送新闻,本质其实就是群发消息 在服务器启动一个独立线程,专门负责推送新…

    数据库 2023年6月11日
    086
  • MySQL基础入门学习教程,带你快速掌握mysql

    Original: https://www.cnblogs.com/chaichaichai/p/15243386.htmlAuthor: 牛仔码农Title: MySQL基础入门…

    数据库 2023年5月24日
    0153
  • Resilience4j 实践

    微服务设计模式 – circuit breaker circuit breaker 熔断器,在很多不同的领域都有这个定义,例如电路里面的熔断器,股票行业里面的熔断,当然…

    数据库 2023年6月11日
    0116
  • SpringBoot整合Redis和SpringBoot(SpringCache)整合Redis

    参考博客: https://blog.csdn.net/lingerlan510/article/details/121906813 https://blog.csdn.net/u…

    数据库 2023年6月14日
    0149
  • MySQL实战45讲 13

    13 | 为什么表数据删掉一半,表文件大小不变? 一个 InnoDB 表包含两部分,即: 表结构定义和 数据。 在 MySQL 8.0 版本以前, 表结构是存在以.frm 为后缀的…

    数据库 2023年6月16日
    0122
  • 5个必知的高级SQL函数

    5个必知的高级SQL函数 SQL是关系数据库管理的标准语言,用于与数据库通信。它广泛用于存储、检索和操作数据库中存储的数据。SQL不区分大小写。用户可以访问存储在关系数据库管理系统…

    数据库 2023年6月11日
    0127
  • QT槽函数获取信号发送对象

    Qt 在槽函数中获取信号发送对象 Qt中提供了一个函数 qobject_cast(QObject *object),可以通过这个函数判断信号发出对象 Qt 帮助文档的解释:Retu…

    数据库 2023年6月16日
    0170
  • 【Java代码之美】 — Java11新特性解读

    1.背景 美国时间 09 月 25 日,Oralce 正式发布了 Java 11,这是据 Java 8 以后支持的首个长期版本。非常值得大家的关注,可以通过下面的地址进行下载: h…

    数据库 2023年6月6日
    0147
  • 有趣的BUG之Stack Overflow

    今天遇到一个很有意思的bug,当程序开发完成后打包到服务器运行,总是会出现栈溢出异常,经过排查发现,问题出现在一个接口上,但这个接口逻辑并不复杂,除了几局逻辑代码外和打印语句之外也…

    数据库 2023年6月6日
    0114
  • podman基础用法

    podman的基础设置和使用 运行示例容器 列出正在运行的容器 检查正在运行的容器 测试httpd服务器 查看容器的日志 查看容器进程pid 对容器执行检查操作 还原容器 迁移容器…

    数据库 2023年6月14日
    0163
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球