当前位置: 首页 > news >正文

吴忠住房和城乡建设局网站百度搜索引擎工作原理

吴忠住房和城乡建设局网站,百度搜索引擎工作原理,上海用哪个网站网购,空中花园做网站的公司在 go 的 sync 包中,有一个 singleflight 包,里面有一个 singleflight.go 文件,代码加注释,一共 200 行出头。内容包括以下几块儿: Group 结构体管理一组相关的函数调用工作,它包含一个互斥锁和一个 map,map 的 key 是…

gosync 包中,有一个 singleflight 包,里面有一个 singleflight.go 文件,代码加注释,一共 200 行出头。内容包括以下几块儿:

  1. Group 结构体管理一组相关的函数调用工作,它包含一个互斥锁和一个 map,mapkey 是函数的名称,value 是对应的 call 结构体。
  2. call 结构体表示一个 inflight 或已完成的函数调用,包含等待组件 WaitGroup、调用结果 valerr、调用次数 dups 和通知通道 chans
  3. Do 方法接收一个 key 和函数 fn,它会先查看 map 中是否已经有这个 key 的调用在 inflight,如果有则等待并返回已有结果,如果没有则新建一个 call 并执行函数调用。
  4. DoChan 类似 Do 但返回一个 channel 来接收结果。
  5. doCall 方法包含了具体处理调用的逻辑,它会在函数调用前后添加 deferrecover panic 和区分正常 returnruntime.Goexit
  6. 如果发生 panic,会将 panicwraps 成错误返回给等待的 channel,如果是 goexit 会直接退出。正常 return 时会将结果发送到所有通知 channel
  7. Forget 方法可以忘记一个 key 的调用,下次 Do 时会重新执行函数。

这个包通过互斥锁和 map 实现了对相同 key 的函数调用去重,可以避免对已有调用的重复计算,同时通过 channel 机制可以通知调用者函数执行结果。在一些需要确保单次执行的场景中,可以使用这个包中的方法。

通过 singleflight 可以很容易实现缓存和去重的效果,避免重复计算,接下来,我们来模拟一下并发请求可能导致的缓存穿透场景,以及如何用 singleflight 包来解决这个问题:

package mainimport ("context""fmt""golang.org/x/sync/singleflight""sync/atomic""time")type Result string
// 模拟查询数据库
func find(ctx context.Context, query string) (Result, error) {return Result(fmt.Sprintf("result for %q", query)), nil
}func main() {var g singleflight.Groupconst n = 200waited := int32(n)done := make(chan struct{})key := "this is key"for i := 0; i < n; i++ {go func(j int) {v, _, shared := g.Do(key, func() (interface{}, error) {ret, err := find(context.Background(), key)return ret, err})if atomic.AddInt32(&waited, -1) == 0 {close(done)}fmt.Printf("index: %d, val: %v, shared: %v\n", j, v, shared)}(i)}select {case <-done:case <-time.After(time.Second):fmt.Println("Do hangs")}time.Sleep(time.Second * 4)
}

在这段程序中,如果重复使用查询结果,shared 会返回 true,穿透查询会返回 false

上面的设计中还有一个问题,就是在 Do 阻塞时,所有请求都会阻塞,内存可能会出现大的问题。

此时,Do 可以更换为DoChan,两者实现上完全一样,不同的是,DoChan() 通过 channel 返回结果。因此可以使用 select 语句实现超时控制

ch := g.DoChan(key, func() (interface{}, error) {ret, err := find(context.Background(), key)return ret, err
})
// Create our timeout
timeout := time.After(500 * time.Millisecond)var ret singleflight.Result
select {
case <-timeout: // Timeout elapsedfmt.Println("Timeout")return
case ret = <-ch: // Received result from channelfmt.Printf("index: %d, val: %v, shared: %v\n", j, ret.Val, ret.Shared)
}

在超时时主动返回,不阻塞。

此时又引入了另一个问题,这样的每一次的请求,并不是高可用的,成功率是无法保证的。这时候可以增加一定的请求饱和度来保证业务的最终成功率,此时一次请求还是多次请求,对于下游服务而言并没有太大区别,此时使用  singleflight  只是为了降低请求的数量级,那么可以使用 Forget() 来提高下游请求的并发。

ch := g.DoChan(key, func() (interface{}, error) {go func() {time.Sleep(10 * time.Millisecond)fmt.Printf("Deleting key: %v\n", key)g.Forget(key)}()ret, err := find(context.Background(), key)return ret, err
})

当然,这种做法依然无法保证100%的成功,如果单次的失败无法容忍,在高并发的场景下需要使用更好的处理方案,比如牺牲一部分实时性、完全使用缓存查询 + 异步更新等。

http://www.hkea.cn/news/780294/

相关文章:

  • wordpress访客ip记录福清市百度seo
  • 网站下载速度慢互联网广告推广公司
  • 电影网站空间配置网络营销的工具和方法有哪些
  • 包装设计网站免费百度seo搜索引擎优化厂家
  • 免费做公司网站sem对seo的影响有哪些
  • 网站空间购买费用关键词优化计划
  • 网站制作可以卖多少钱陕西网站建设制作
  • 深圳中小企业网站制作谷歌海外广告投放
  • 做游戏网站的需求分析创建app平台
  • 青岛胶南做网站的有多少seo商学院
  • 二月网站建设南宁百度个人中心登录
  • 如何在相关网站免费做宣传广告免费建立个人网站官网
  • 做搜狗网站优化首自己建立网站步骤
  • 企业资质查询官方网站最好的小说网站排名
  • 乐平网站设计北京互联网公司
  • 朝阳企业网站建设方案费用郑州网络营销学校
  • 建站行业发展百度广告代运营
  • 如何做积分商城网站鸡西seo顾问
  • p2p网站开发文档免费b站软件下载
  • 有没有做q版头像的网站今天百度数据
  • wordpress页面修改插件seo顾问阿亮
  • 政府门户网站建设标准国际婚恋网站排名
  • 上海青浦网站建设郑州靠谱seo电话
  • 网站建设怎么样seo专家招聘
  • 在网盘上怎么做自己的网站整站优化推广
  • php建设网站实训百度搜索引擎的总结
  • 怎么在360自己做网站重庆seo排名收费
  • 外贸网站建设浩森宇特教育培训报名
  • 网站开发价目表深圳市前十的互联网推广公司
  • php做视频直播网站关键词竞价广告