直接上代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
package main // 一个使用sync.Once的缓存示例,它不会出现缓存击穿,还缺少缓存过期机制可进一步优化 import ( "log" "sync" "time" ) type CacheEntry struct { data []byte // 存放实际数据 err error once *sync.Once } type OrderSever struct { cache map[string]*CacheEntry mutex sync.Mutex } // Query 查询缓存 第一次会去后端获取 因为加了锁 其他并发线程只能等待 func (order *OrderSever) Query(key string) ([]byte, error) { order.mutex.Lock() if order.cache == nil { order.cache = make(map[string]*CacheEntry) // 初始化缓存池 } entry, ok := order.cache[key] // 找不到就初始化一个 if !ok { entry = &CacheEntry{ data: make([]byte, 0), err: nil, once: new(sync.Once), // 注意这里是new } order.cache[key] = entry } order.mutex.Unlock() // 只执行一次 entry.once.Do(func() { entry.data, entry.err = getOrder() // 填充缓存 去后端获取数据 如数据库等 }) // 数据被赋值了 返回 return entry.data, entry.err } func getOrder() ([]byte, error) { time.Sleep(50 * time.Millisecond) log.Println("后端获取数据") return []byte("hello world"), nil } func main() { var order OrderSever for i := 0; i < 10; i++ { query, err := order.Query("test") if err != nil { return } log.Println(string(query)) } } |
转载请注明:轻风博客 » 一个使用sync.Once特性的缓存示例