-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7e8b84c
commit f24a9b4
Showing
2 changed files
with
67 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// Copyright 2021 Peanutzhen. All rights reserved. | ||
// Use of this source code is governed by a MIT style | ||
// license that can be found in the LICENSE file. | ||
|
||
package singlefilght | ||
|
||
import "sync" | ||
|
||
// singlefilght 为peanutcache提供缓存击穿的保护 | ||
// 当cache并发访问peer获取缓存时 如果peer未缓存该值 | ||
// 则会向db发送大量的请求获取 造成db的压力骤增 | ||
// 因此 将所有由key产生的请求抽象成flight | ||
// 这个flight只会起飞一次(single) 这样就可以缓解击穿的可能性 | ||
// flight载有我们要的缓存数据 称为packet | ||
|
||
type packet struct { | ||
wg sync.WaitGroup | ||
val interface{} | ||
err error | ||
} | ||
|
||
type Flight struct { | ||
mu sync.Mutex | ||
flight map[string]*packet | ||
} | ||
|
||
// Fly 负责key航班的飞行 fn是获取packet的方法 | ||
func (f *Flight) Fly(key string, fn func() (interface{}, error)) (interface{}, error) { | ||
f.mu.Lock() | ||
if f.flight == nil { | ||
f.flight = make(map[string]*packet) | ||
} | ||
if p, ok := f.flight[key]; ok { | ||
f.mu.Unlock() | ||
p.wg.Wait() | ||
return p.val, p.err | ||
} | ||
p := new(packet) | ||
p.wg.Add(1) | ||
f.flight[key] = p | ||
f.mu.Unlock() | ||
|
||
p.val, p.err = fn() | ||
p.wg.Done() | ||
|
||
f.mu.Lock() | ||
delete(f.flight, key) // 航班已完成 | ||
f.mu.Unlock() | ||
|
||
return p.val, p.err | ||
} |