diff --git a/server/config.docker.yaml b/server/config.docker.yaml index a7783716f6..4e8a90924e 100644 --- a/server/config.docker.yaml +++ b/server/config.docker.yaml @@ -57,6 +57,7 @@ system: oss-type: local # 控制oss选择走本地还是 七牛等其他仓 自行增加其他oss仓可以在 server/utils/upload/upload.go 中 NewOss函数配置 use-redis: false # 使用redis use-mongo: false # 使用mongo + use-cache: false # 使用cache use-multipoint: false # IP限制次数 一个小时15000次 iplimit-count: 15000 @@ -217,4 +218,12 @@ cors: allow-headers: content-type allow-methods: GET, POST expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type - allow-credentials: true # 布尔值 \ No newline at end of file + allow-credentials: true # 布尔值 + +# 缓存配置 +cache: + mode: redis # 使用redis做缓存 + redis: + db: 0 + addr: 127.0.0.1:6379 + password: "" \ No newline at end of file diff --git a/server/config.yaml b/server/config.yaml index 7870759407..e8a1722cf6 100644 --- a/server/config.yaml +++ b/server/config.yaml @@ -57,6 +57,7 @@ system: oss-type: local # 控制oss选择走本地还是 七牛等其他仓 自行增加其他oss仓可以在 server/utils/upload/upload.go 中 NewOss函数配置 use-redis: false # 使用redis use-mongo: false # 使用mongo + use-cache: false # 使用cache use-multipoint: false # IP限制次数 一个小时15000次 iplimit-count: 15000 @@ -251,4 +252,12 @@ cors: allow-headers: content-type allow-methods: GET, POST expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type - allow-credentials: true # 布尔值 \ No newline at end of file + allow-credentials: true # 布尔值 + +# 缓存配置 +cache: + mode: redis # 使用redis做缓存 + redis: + db: 0 + addr: 127.0.0.1:6379 + password: "" \ No newline at end of file diff --git a/server/config/cache.go b/server/config/cache.go new file mode 100644 index 0000000000..56be3856ef --- /dev/null +++ b/server/config/cache.go @@ -0,0 +1,6 @@ +package config + +type Cache struct { + Mode string `mapstructure:"mode" json:"mode" yaml:"mode"` + Redis Redis +} diff --git a/server/config/config.go b/server/config/config.go index 892c28a221..ddd7f32554 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -30,4 +30,6 @@ type Server struct { // 跨域配置 Cors CORS `mapstructure:"cors" json:"cors" yaml:"cors"` + // 缓存配置 + Cache Cache `mapstructure:"cache" json:"cache" yaml:"cache"` } diff --git a/server/config/system.go b/server/config/system.go index 7ab3387626..6eabb7a61c 100644 --- a/server/config/system.go +++ b/server/config/system.go @@ -11,4 +11,5 @@ type System struct { UseMultipoint bool `mapstructure:"use-multipoint" json:"use-multipoint" yaml:"use-multipoint"` // 多点登录拦截 UseRedis bool `mapstructure:"use-redis" json:"use-redis" yaml:"use-redis"` // 使用redis UseMongo bool `mapstructure:"use-mongo" json:"use-mongo" yaml:"use-mongo"` // 使用redis + UseCache bool `mapstructure:"use-cache" json:"use-cache" yaml:"use-cache"` // 使用cache } diff --git a/server/core/cache/cache.go b/server/core/cache/cache.go new file mode 100644 index 0000000000..435d4dc08c --- /dev/null +++ b/server/core/cache/cache.go @@ -0,0 +1,21 @@ +package cache + +import ( + "context" + "errors" + "time" +) + +var ErrorKeyNotFound = errors.New("key not found") + +type ICache interface { + Get(ctx context.Context, key string) (string, error) + Set(ctx context.Context, key, value string) error + SetEx(ctx context.Context, key, value string, expiration time.Duration) error + Exist(ctx context.Context, key string) (bool, error) + Delete(ctx context.Context, key string) error + Incr(ctx context.Context, key string) (int64, error) + Decr(ctx context.Context, key string) (int64, error) + Expire(ctx context.Context, key string, expiration time.Duration) (bool, error) + Ttl(ctx context.Context, key string) (int, error) // -1 永不过期, -2 没有找到key +} diff --git a/server/core/cache/cache_factory.go b/server/core/cache/cache_factory.go new file mode 100644 index 0000000000..a784c307c5 --- /dev/null +++ b/server/core/cache/cache_factory.go @@ -0,0 +1,38 @@ +package cache + +import ( + "context" + "errors" + + "github.com/flipped-aurora/gin-vue-admin/server/config" + "github.com/redis/go-redis/v9" +) + +func Create(c config.Cache) (ICache, error) { + if len(c.Mode) == 0 { + return nil, errors.New("mode not found") + } + + switch c.Mode { + case "redis": + redisCfg := c.Redis + return createRedis(redisCfg.Addr, redisCfg.Password, redisCfg.DB) + default: + return nil, errors.New("mode not found") + } +} + +func createRedis(addr, password string, db int) (ICache, error) { + opt := &redis.Options{ + Addr: addr, + Password: password, // no password set + DB: db, // use default DB + } + + client := redis.NewClient(opt) + if err := client.Ping(context.Background()).Err(); err != nil { + return nil, err + } + + return NewCacheRedis(client), nil +} diff --git a/server/core/cache/cache_redis.go b/server/core/cache/cache_redis.go new file mode 100644 index 0000000000..91137e0943 --- /dev/null +++ b/server/core/cache/cache_redis.go @@ -0,0 +1,77 @@ +package cache + +import ( + "context" + "time" + + "github.com/redis/go-redis/v9" +) + +var _ ICache = (*CacheRedis)(nil) + +type CacheRedis struct { + rds *redis.Client +} + +func NewCacheRedis(client *redis.Client) *CacheRedis { + return &CacheRedis{ + rds: client, + } +} + +func (c *CacheRedis) Get(ctx context.Context, key string) (string, error) { + ret := c.rds.Get(ctx, key) + r, err := ret.Result() + switch { + case err == redis.Nil: + return "", ErrorKeyNotFound + case err != nil: + return "", err + } + return r, nil +} + +func (c *CacheRedis) Set(ctx context.Context, key, value string) error { + return c.rds.Set(ctx, key, value, redis.KeepTTL).Err() +} + +func (c *CacheRedis) SetEx(ctx context.Context, key, value string, expiration time.Duration) error { + return c.rds.SetEx(ctx, key, value, expiration).Err() +} + +func (c *CacheRedis) Exist(ctx context.Context, key string) (bool, error) { + result, err := c.rds.Exists(ctx, key).Result() + if err != nil { + return false, err + } + return result == 1, nil +} + +func (c *CacheRedis) Delete(ctx context.Context, key string) error { + return c.rds.Del(ctx, key).Err() +} + +func (c *CacheRedis) Expire(ctx context.Context, key string, expiration time.Duration) (bool, error) { + return c.rds.Expire(ctx, key, expiration).Result() +} + +func (c *CacheRedis) Ttl(ctx context.Context, key string) (int, error) { + result, err := c.rds.TTL(ctx, key).Result() + if err != nil { + return 0, err + } + + if result <= 0 { + return int(result), nil + } + + return int(result.Seconds()), nil +} + +func (c *CacheRedis) Incr(ctx context.Context, key string) (int64, error) { + return c.rds.Incr(ctx, key).Result() +} + +func (c *CacheRedis) Decr(ctx context.Context, key string) (int64, error) { + return c.rds.Decr(ctx, key).Result() +} diff --git a/server/core/cache/cache_redis_test.go b/server/core/cache/cache_redis_test.go new file mode 100644 index 0000000000..15d2811bb3 --- /dev/null +++ b/server/core/cache/cache_redis_test.go @@ -0,0 +1,486 @@ +package cache + +import ( + "context" + "github.com/redis/go-redis/v9" + "testing" + "time" +) + +var ( + rds = redis.NewClient(&redis.Options{ + Addr: "127.0.0.1:6379", + }) + ctx = context.Background() + cr = &CacheRedis{rds: rds} +) + +func TestCacheRedis_Decr(t *testing.T) { + cr.Set(context.Background(), "decr_name", "0") + cr.Delete(context.Background(), "decr_not_found") + cr.Set(ctx, "str", "str1") + + type fields struct { + redis *redis.Client + } + type args struct { + ctx context.Context + key string + } + + tests := []struct { + name string + fields fields + args args + want int64 + wantErr bool + }{ + { + name: "decr", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "decr_name"}, + want: -1, + wantErr: false, + }, + { + name: "decr", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "decr_name"}, + want: -2, + wantErr: false, + }, + { + name: "empty", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "decr_not_found"}, + want: -1, + wantErr: false, + }, + { + name: "string", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "str"}, + want: 0, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &CacheRedis{ + rds: tt.fields.redis, + } + got, err := c.Decr(tt.args.ctx, tt.args.key) + if (err != nil) != tt.wantErr { + t.Errorf("Decr() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("Decr() got = %v, want %v", got, tt.want) + } + + }) + } +} + +func TestCacheRedis_Delete(t *testing.T) { + cr.Set(ctx, "exits_name", "zhangsan") + + type fields struct { + redis *redis.Client + } + type args struct { + ctx context.Context + key string + } + tests := []struct { + name string + fields fields + args args + wantErr bool + }{ + { + name: "exits", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "exits_name"}, + wantErr: false, + }, + { + name: "not_exits", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "not_exits_name1"}, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &CacheRedis{ + rds: tt.fields.redis, + } + if err := c.Delete(tt.args.ctx, tt.args.key); (err != nil) != tt.wantErr { + t.Errorf("Delete() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestCacheRedis_Exist(t *testing.T) { + cr.Set(ctx, "exist_str", "hello") + cr.Delete(ctx, "not_exist_str") + + type fields struct { + redis *redis.Client + } + type args struct { + ctx context.Context + key string + } + tests := []struct { + name string + fields fields + args args + want bool + wantErr bool + }{ + { + name: "exist", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "exist_str"}, + want: true, + wantErr: false, + }, + { + name: "exist", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "not_exist_str"}, + want: false, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &CacheRedis{ + rds: tt.fields.redis, + } + got, err := c.Exist(tt.args.ctx, tt.args.key) + if (err != nil) != tt.wantErr { + t.Errorf("Exist() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("Exist() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestCacheRedis_Expire(t *testing.T) { + cr.Set(ctx, "exist_expire", "world") + cr.Delete(ctx, "not_exist_expire") + + type fields struct { + redis *redis.Client + } + type args struct { + ctx context.Context + key string + expiration time.Duration + } + tests := []struct { + name string + fields fields + args args + want bool + wantErr bool + }{ + { + name: "exist", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "exist_expire", expiration: time.Second * 10}, + want: true, + wantErr: false, + }, + { + name: "not_exist", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "not_exist_expire", expiration: time.Second * 10}, + want: false, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &CacheRedis{ + rds: tt.fields.redis, + } + got, err := c.Expire(tt.args.ctx, tt.args.key, tt.args.expiration) + if (err != nil) != tt.wantErr { + t.Errorf("Expire() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("Expire() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestCacheRedis_Get(t *testing.T) { + cr.Set(ctx, "exist_get", "world") + cr.Delete(ctx, "not_exist_get") + + type fields struct { + redis *redis.Client + } + type args struct { + ctx context.Context + key string + } + tests := []struct { + name string + fields fields + args args + want string + wantErr bool + }{ + { + name: "exist", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "exist_get"}, + want: "world", + wantErr: false, + }, + { + name: "not_exist", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "not_exist_get"}, + want: "", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &CacheRedis{ + rds: tt.fields.redis, + } + got, err := c.Get(tt.args.ctx, tt.args.key) + if (err != nil) != tt.wantErr { + t.Errorf("Get() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("Get() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestCacheRedis_Incr(t *testing.T) { + cr.Set(context.Background(), "incr_name", "0") + cr.Delete(context.Background(), "incr_not_found") + cr.Set(ctx, "str", "str1") + + type fields struct { + redis *redis.Client + } + type args struct { + ctx context.Context + key string + } + tests := []struct { + name string + fields fields + args args + want int64 + wantErr bool + }{ + { + name: "incr", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "incr_name"}, + want: 1, + wantErr: false, + }, + { + name: "incr", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "incr_name"}, + want: 2, + wantErr: false, + }, + { + name: "empty", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "incr_not_found"}, + want: 1, + wantErr: false, + }, + { + name: "string", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "str"}, + want: 0, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &CacheRedis{ + rds: tt.fields.redis, + } + got, err := c.Incr(tt.args.ctx, tt.args.key) + if (err != nil) != tt.wantErr { + t.Errorf("Incr() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("Incr() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestCacheRedis_Set(t *testing.T) { + cr.Set(ctx, "exist_set", "world") + cr.Delete(ctx, "not_exist_set") + + type fields struct { + redis *redis.Client + } + type args struct { + ctx context.Context + key string + value string + } + tests := []struct { + name string + fields fields + args args + wantErr bool + }{ + { + name: "exist", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "exist_set", value: "world"}, + wantErr: false, + }, + { + name: "not_exist", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "not_exist_set", value: "world"}, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &CacheRedis{ + rds: tt.fields.redis, + } + if err := c.Set(tt.args.ctx, tt.args.key, tt.args.value); (err != nil) != tt.wantErr { + t.Errorf("Set() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestCacheRedis_SetEx(t *testing.T) { + cr.Set(ctx, "exist_setex", "world") + cr.Delete(ctx, "not_exist_setex") + + type fields struct { + redis *redis.Client + } + type args struct { + ctx context.Context + key string + value string + expiration time.Duration + } + tests := []struct { + name string + fields fields + args args + wantErr bool + }{ + { + name: "exist", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "exist_setex", value: "world", expiration: time.Second * 20}, + wantErr: false, + }, + { + name: "not_exist", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "not_exist_setex", value: "world", expiration: time.Second * 20}, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &CacheRedis{ + rds: tt.fields.redis, + } + if err := c.SetEx(tt.args.ctx, tt.args.key, tt.args.value, tt.args.expiration); (err != nil) != tt.wantErr { + t.Errorf("SetEx() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestCacheRedis_Ttl(t *testing.T) { + cr.Set(ctx, "exist_durable_ttl", "world") + cr.SetEx(ctx, "exist_ttl", "world", time.Second*20) + cr.Delete(ctx, "not_exist_ttl") + + type fields struct { + redis *redis.Client + } + type args struct { + ctx context.Context + key string + } + tests := []struct { + name string + fields fields + args args + want int + wantErr bool + }{ + { + name: "exist", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "exist_ttl"}, + want: 20, + wantErr: false, + }, + { + name: "not_exist", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "not_exist_ttl"}, + want: -2, + wantErr: false, + }, + { + name: "exist_durable", + fields: fields{redis: rds}, + args: args{ctx: ctx, key: "exist_durable_ttl"}, + want: -1, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &CacheRedis{ + rds: tt.fields.redis, + } + got, err := c.Ttl(tt.args.ctx, tt.args.key) + if (err != nil) != tt.wantErr { + t.Errorf("Ttl() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("Ttl() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/server/core/server.go b/server/core/server.go index 8161e620d6..9eff7a1ffa 100644 --- a/server/core/server.go +++ b/server/core/server.go @@ -25,6 +25,10 @@ func RunWindowsServer() { zap.L().Error(fmt.Sprintf("%+v", err)) } } + // 初始化cache服务 + if global.GVA_CONFIG.System.UseCache { + initialize.InitCache() + } // 从db加载jwt数据 if global.GVA_DB != nil { system.LoadAll() diff --git a/server/global/global.go b/server/global/global.go index f7f93c2bbe..b4ef15041c 100644 --- a/server/global/global.go +++ b/server/global/global.go @@ -1,6 +1,7 @@ package global import ( + "github.com/flipped-aurora/gin-vue-admin/server/core/cache" "github.com/qiniu/qmgo" "sync" @@ -32,6 +33,8 @@ var ( BlackCache local_cache.Cache lock sync.RWMutex + + GVA_CACHE cache.ICache ) // GetGlobalDBByDBName 通过名称获取db list中的db diff --git a/server/go.mod b/server/go.mod index 5be6f78ee3..f5270e1645 100644 --- a/server/go.mod +++ b/server/go.mod @@ -40,7 +40,6 @@ require ( golang.org/x/crypto v0.10.0 golang.org/x/sync v0.3.0 golang.org/x/text v0.11.0 - gorm.io/datatypes v1.2.0 gorm.io/driver/mysql v1.5.1 gorm.io/driver/postgres v1.5.2 gorm.io/driver/sqlserver v1.5.1 diff --git a/server/go.sum b/server/go.sum index 7d4e90019a..1b31a98db9 100644 --- a/server/go.sum +++ b/server/go.sum @@ -312,7 +312,6 @@ github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/microsoft/go-mssqldb v1.1.0 h1:jsV+tpvcPTbNNKW0o3kiCD69kOHICsfjZ2VcVu2lKYc= github.com/microsoft/go-mssqldb v1.1.0/go.mod h1:LzkFdl4z2Ck+Hi+ycGOTbL56VEfgoyA2DvYejrNGbRk= github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= @@ -832,14 +831,11 @@ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/datatypes v1.2.0 h1:5YT+eokWdIxhJgWHdrb2zYUimyk0+TaFth+7a0ybzco= -gorm.io/datatypes v1.2.0/go.mod h1:o1dh0ZvjIjhH/bngTpypG6lVRJ5chTBxE09FH/71k04= gorm.io/driver/mysql v1.4.3/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c= gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw= gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o= gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0= gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8= -gorm.io/driver/sqlite v1.4.3 h1:HBBcZSDnWi5BW3B3rwvVTc510KGkBkexlOg0QrmLUuU= gorm.io/driver/sqlserver v1.5.1 h1:wpyW/pR26U94uaujltiFGXY7fd2Jw5hC9PB1ZF/Y5s4= gorm.io/driver/sqlserver v1.5.1/go.mod h1:AYHzzte2msKTmYBYsSIq8ZUsznLJwBdkB2wpI+kt0nM= gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= diff --git a/server/initialize/cache.go b/server/initialize/cache.go new file mode 100644 index 0000000000..6ab179fe88 --- /dev/null +++ b/server/initialize/cache.go @@ -0,0 +1,14 @@ +package initialize + +import ( + "github.com/flipped-aurora/gin-vue-admin/server/core/cache" + "github.com/flipped-aurora/gin-vue-admin/server/global" +) + +func InitCache() { + c, err := cache.Create(global.GVA_CONFIG.Cache) + if err != nil { + panic(err) + } + global.GVA_CACHE = c +}