github.com/charlienet/go-mixed@v0.3.7/cache/cache.go (about) 1 package cache 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "time" 8 9 "github.com/charlienet/go-mixed/bytesconv" 10 "github.com/charlienet/go-mixed/locker" 11 "github.com/charlienet/go-mixed/logx" 12 ) 13 14 var ErrNotFound = errors.New("key not found") 15 16 type LoadFunc func(context.Context) (any, error) 17 18 type Cache struct { 19 prefix string // 键前缀 20 retry int // 资源获取时的重试次数 21 mem MemCache // 内存缓存 22 distributdCache DistributdCache // 分布式缓存 23 publishSubscribe PublishSubscribe // 发布订阅 24 lock locker.ChanLocker // 资源锁 25 qps *qps // 访问计数 26 logger logx.Logger // 日志记录 27 } 28 29 func NewCache(opts ...option) *Cache { 30 31 c := acquireDefaultCache() 32 for _, f := range opts { 33 if err := f(c); err != nil { 34 return c 35 } 36 } 37 38 go c.subscribe() 39 40 return c 41 } 42 43 func (c *Cache) Set(key string, value any, expiration time.Duration) error { 44 if c.mem != nil { 45 bytes, err := bytesconv.Encode(value) 46 if err != nil { 47 return err 48 } 49 50 c.mem.Set(key, bytes, expiration) 51 } 52 53 return nil 54 } 55 56 func (c *Cache) Get(key string, out any) error { 57 if c.mem != nil { 58 c.getFromMem(key, out) 59 } 60 61 if c.distributdCache != nil { 62 if err := c.distributdCache.Get(key, out); err != nil { 63 64 } 65 } 66 67 return nil 68 } 69 70 func (c *Cache) GetFn(ctx context.Context, key string, out any, fn LoadFunc, expiration time.Duration) (bool, error) { 71 c.Get(key, out) 72 73 // 多级缓存中未找到时,放置缓存对象 74 ret, err := fn(ctx) 75 if err != nil { 76 return false, err 77 } 78 79 c.Set(key, ret, expiration) 80 81 return false, nil 82 } 83 84 func (c *Cache) Exist(key string) (bool, error) { 85 return false, nil 86 } 87 88 func (c *Cache) Delete(key ...string) error { 89 if c.mem != nil { 90 c.mem.Delete(key...) 91 } 92 93 if c.distributdCache != nil { 94 c.distributdCache.Delete(key...) 95 } 96 97 return nil 98 } 99 100 func (c *Cache) subscribe() { 101 } 102 103 func (c *Cache) getFromMem(key string, out any) error { 104 bytes, err := c.mem.Get(key) 105 if err != nil { 106 return err 107 } 108 109 if err := bytesconv.Decode(bytes, out); err != nil { 110 return err 111 } 112 113 return nil 114 } 115 116 // 从缓存加载数据 117 func (c *Cache) getFromCache() { 118 // 从缓存加载数据 119 // 1. 检查内存是否存在 120 // 2. 检查分布缓存是否存在 121 } 122 123 // 从数据源加载数据 124 func (c *Cache) getFromSource(ctx context.Context, key string, fn LoadFunc) error { 125 126 // 1. 尝试获取资源锁,如成功获取到锁加载数据 127 // 2. 未获取到锁,等待从缓存中获取 128 ch, ok := c.lock.Get(key) 129 if ok { 130 defer c.lock.Release(key) 131 132 v, err := fn(ctx) 133 if err != nil { 134 return fmt.Errorf("load from source err:%v", err) 135 } 136 137 // 取出值存入多级缓存 138 _ = v 139 140 return nil 141 } 142 143 // 等待数据加载完成 144 select { 145 case <-ch: 146 147 // 未取到结果时,再次获取 148 return c.getFromSource(ctx, key, fn) 149 } 150 }