feat: 实现 cache,使用 redis 能基本使用

This commit is contained in:
tiglog 2023-06-21 10:52:25 +08:00
parent dbda182b10
commit 4c90ac7490
6 changed files with 205 additions and 8 deletions

View File

@ -7,4 +7,42 @@
package gcache
import (
"sync"
"time"
"git.hexq.cn/tiglog/golib/helper"
)
const default_cache_size = 1024
// 本地内存缓存
type localCacheAdapter struct {
mu sync.Mutex
data map[string][]byte
}
func NewLocalCacheAdapter() ICacheAdapter {
return &localCacheAdapter{
data: make(map[string][]byte, default_cache_size),
}
}
func (c *localCacheAdapter) Get(key string, dest interface{}) error {
val, ok := c.data[key]
if ok {
helper.Scan(val, dest)
}
return nil
}
func (c *localCacheAdapter) Set(key string, val interface{}, ttl time.Duration) error {
return nil
}
func (c *localCacheAdapter) Has(key string) bool {
return false
}
func (c *localCacheAdapter) Del(keys ...string) (int64, error) {
return 0, nil
}

View File

@ -7,4 +7,46 @@
package gcache
import (
"context"
"sync"
"time"
"github.com/go-redis/redis/v8"
)
// 使用 redis 服务缓存
type redisCacheAdapter struct {
mu sync.Mutex
redis *redis.Client
}
func NewRedisCacheAdapter(rds *redis.Client) ICacheAdapter {
return &redisCacheAdapter{
redis: rds,
}
}
func (c *redisCacheAdapter) Get(key string, dest interface{}) error {
cmd := c.redis.Get(context.Background(), key)
return cmd.Scan(dest)
}
func (c *redisCacheAdapter) Set(key string, val interface{}, ttl time.Duration) error {
cmd := c.redis.Set(context.Background(), key, val, ttl)
return cmd.Err()
}
func (c *redisCacheAdapter) Has(key string) bool {
cmd := c.redis.Exists(context.Background(), key)
result, _ := cmd.Result()
if result == 1 {
return true
}
return false
}
func (c *redisCacheAdapter) Del(keys ...string) (int64, error) {
cmd := c.redis.Del(context.Background(), keys...)
return cmd.Result()
}

View File

@ -7,10 +7,51 @@
package gcache
import (
"sync"
"time"
"github.com/go-redis/redis/v8"
)
type Engine struct {
ICacheAdapter
client ICacheAdapter
}
var once sync.Once
var engine *Engine
func New(adapter ICacheAdapter) *Engine {
return &Engine{adapter}
once.Do(func() {
engine = &Engine{
client: adapter,
}
})
return engine
}
func NewWithRedis(rds *redis.Client) *Engine {
once.Do(func() {
engine = &Engine{
client: NewRedisCacheAdapter(rds),
}
})
return engine
}
func (e *Engine) Get(key string, dest interface{}) error {
return e.client.Get(key, dest)
}
func (e *Engine) Set(key string, val interface{}, ttl time.Duration) error {
return e.client.Set(key, val, ttl)
}
func (e *Engine) Has(key string) bool {
return e.client.Has(key)
}
func (e *Engine) Del(keys ...string) (int64, error) {
return e.client.Del(keys...)
}

View File

@ -10,9 +10,8 @@ package gcache
import "time"
type ICacheAdapter interface {
Get(key string) (string, error)
Get(key string, dest interface{}) error
Set(key string, val interface{}, exp time.Duration) error
Del(keys ...string) int64
Del(keys ...string) (int64, error)
Has(key string) bool
End()
}

70
gcache/cache_test.go Normal file
View File

@ -0,0 +1,70 @@
//
// cache_test.go
// Copyright (C) 2023 tiglog <me@tiglog.com>
//
// Distributed under terms of the MIT license.
//
package gcache_test
import (
"context"
"fmt"
"os"
"testing"
"time"
"git.hexq.cn/tiglog/golib/gcache"
"git.hexq.cn/tiglog/golib/gtest"
"github.com/go-redis/redis/v8"
)
func getRedis() *redis.Client {
opt, _ := redis.ParseURL(os.Getenv("REDIS_URL"))
return redis.NewClient(opt)
}
func TestRedis(t *testing.T) {
rds := getRedis()
cmd := rds.Ping(context.Background())
ret, err := cmd.Result()
gtest.Nil(t, err)
fmt.Println(ret)
}
func TestCacheNew(t *testing.T) {
rds := getRedis()
cm1 := gcache.NewWithRedis(rds)
cm2 := gcache.NewWithRedis(rds)
gtest.Equal(t, cm1, cm2)
}
func TestRedisAdapter(t *testing.T) {
rds := getRedis()
cm := gcache.NewWithRedis(rds)
key := "foo"
cm.Del(key)
r1 := cm.Has(key)
gtest.False(t, r1)
var err error
val1 := "bar"
err = cm.Set(key, val1, time.Second)
gtest.Nil(t, err)
var r2 string
err = cm.Get(key, &r2)
gtest.Nil(t, err)
gtest.Equal(t, val1, r2)
val2 := 2
err = cm.Set(key, val2, time.Hour)
gtest.Nil(t, err)
var r3 int
err = cm.Get(key, &r3)
gtest.Nil(t, err)
gtest.Equal(t, val2, r3)
n, err := cm.Del(key)
gtest.Nil(t, err)
gtest.Equal(t, int64(1), n)
}

View File

@ -15,12 +15,19 @@
:imagesdir: ./img
**注:** 暂时直接使用 `go-resdis/cache`
== 实现
已于 2023-06-21 实现。
可以基于 `redis` 进行一些基本使用。
== 设计
从使用倒推设计。
== 场景1
=== 场景1
自己管理 `key`:
@ -38,7 +45,7 @@ return data
<1> `get` 值为 `false` 表示没有缓存或缓存已过期
<2> 7200 为缓存有效期(单位为秒),若指定为 0 表示不过期。
== 场景2
=== 场景2
程序自动管理 `key`: