go get github.com/smokezl/matryoshka
import "github.com/smokezl/matryoshka"
// 1、初始化全局缓存
conf := &matryoshka.RedisConfig{
Addr: "127.0.0.1:6379",
MaxRetry: 2,
Pwd: "",
IdleTimeout: 10,
ConnTimeout: 100,
MaxIdle: 50,
MaxActive: 500,
}
cache := matryoshka.Init(
matryoshka.WithErrHandler(func(ctx context.Context, err error) {
fmt.Println("test print,", err)
}),
matryoshka.WithDistributedCache(matryoshka.NewDefaultCache(conf)),
matryoshka.WithPubSubChannel(matryoshka.NewDefaultPubSub("sub_key", conf)),
)
// 2、根据不同的使用场景, 创建独立场景的缓存
scene := "productInfo"
// 内存 cache 超时时间(redis超时是内存的n倍,默认20倍,可以通过 WithRedisTtlFactor 设置倍数)
expire := 20
soureLoadFn:= func(ctx context.Context, "cachePre", key string) (string, error) {
return "product info", nil
}
batchSoureLoadFn = func(ctx context.Context, "cachePre", keys []string) (map[string]string, error) {
valMap := make(map[string]string)
for _, key := range keys{
valMap[key] = "product info"
}
return valMap, nil
}
h := cache.NewCache(scene, expire)
// 3、获取单个数据
val, err := h.Get(ctx, "key",soureLoadFn)
if err == matryoshka.ErrNotFound {
//deal empty
}
if err != nil {
//deal err
}
// 4、获取批量数据
valMap, err := h.BatchGet(ctx, []string{"key1","key2"},batchSoureLoadFn)
if err != nil {
//deal err
}
if len(valMap) == 0 {
//deal empty
}
设置全局缓存内存大小,单位 byte,默认为 1024 1024 100(100m)
设置错误执行函数,默认为 nil
type errHandler func(ctx context.Context, err error)
设置从redis缓存io数据的接口,如果不设置,redis缓存将无法使用,内置 NewDefaultCache
type DistributedCacheI interface {
IsNilErr(err error) bool
Get(key string) (val string, err error)
MGet(keys []string) (valMap map[string]string, err error)
SetEx(key string, val string, ttl int) (err error)
Del(keys []string) (err error)
}
设置订阅发布的接口,如果不设置,内存缓存分布式同步功能将无法使用,内置 NewDefaultPubSub
type PubSubChannelI interface {
GetKey() string
Subscribe(key string, receiver func(message string, err error))
Publish(key string, val string) (err error)
}
conf := &matryoshka.RedisConfig{
Addr: "127.0.0.1:6379",
MaxRetry: 2,
Pwd: "",
IdleTimeout: 10,
ConnTimeout: 100,
MaxIdle: 50,
MaxActive: 500,
WriteTimeout:100,
ReadTimeout: 100,
}
type externalCache struct {
rp *redis.Pool
}
func NewExternalCache() *externalCache {
return &externalCache{
rp: &redis.Pool{
MaxIdle: pubSubMaxConn,
MaxActive: pubSubMaxConn,
IdleTimeout: time.Duration(idleTimeout) * time.Second,
Dial: func() (conn redis.Conn, e error) {
return redis.Dial("tcp", conf.Addr,
redis.DialPassword(pwd),
redis.DialConnectTimeout(time.Duration(connTimeout)*time.Millisecond),
redis.DialReadTimeout(time.Duration(c.ReadTimeout)*time.Millisecond),
redis.DialWriteTimeout(time.Duration(c.WriteTimeout)*time.Millisecond),
)
},
},
}
}
func (e *externalCache) IsNilErr(err error) bool {
return err == redis.ErrNil
}
func (e *externalCache) MGet(keys []string) (valMap map[string]string, err error) {
conn := e.rp.Get()
defer conn.Close()
var args []interface{}
for _, key := range keys {
args = append(args, key)
}
vals, err := redis.Strings(conn.Do("MGET", args...))
if err != nil {
return nil, err
}
lv := len(vals)
valMap = make(map[string]string, lv)
for i := 0; i < lv; i++ {
valMap[keys[i]] = vals[i]
}
return
}
func (e *externalCache) Get(key string) (val string, err error) {
conn := e.rp.Get()
defer conn.Close()
val, err = redis.String(conn.Do("GET", key))
return
}
func (e *externalCache) SetEx(key string, val string, ttl int) (err error) {
conn := e.rp.Get()
defer conn.Close()
_, err = redis.String(conn.Do("SETEX", key, ttl, val))
return
}
func (e *externalCache) Del(key string) error {
conn := e.rp.Get()
defer conn.Close()
_, err := redis.Int(conn.Do("DEL", key))
return err
}
cache := matryoshka.Init(conf,
matryoshka.WithCacheSize(1024*1024*1024),
matryoshka.WithErrHandler(func(ctx context.Context, err error){
//deal err
}),
//内置
//matryoshka.WithDistributedCache(matryoshka.NewDefaultCache(conf)),
matryoshka.WithDistributedCache(NewExternalCache(conf)),
//内置
matryoshka.WithPubSubChannel(matryoshka.NewDefaultPubSub("sub_key", conf)),
)
设置开启的缓存,默认同时开启内存和redis缓存
CacheTypeAll = 1 //同时开启内存和redis缓存
CacheTypeMem = 2 //只开启内部缓存
CacheTypeExt = 3 //只开启redis缓存
设置redis缓存超时时间,默认为20倍expire时间 redis超时时间计算公式为: redisTtl = expire * factor
h := cache.NewCache(scene, expire,
matryoshka.WithCacheType(matryoshka.CacheTypeAll),
matryoshka.WithRedisTtlFactor(30)
)
MIT licence.