feat: 实现 cache,使用 redis 能基本使用
This commit is contained in:
parent
dbda182b10
commit
4c90ac7490
@ -7,4 +7,42 @@
|
|||||||
|
|
||||||
package gcache
|
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
|
||||||
|
}
|
||||||
|
@ -7,4 +7,46 @@
|
|||||||
|
|
||||||
package gcache
|
package gcache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
|
)
|
||||||
|
|
||||||
// 使用 redis 服务缓存
|
// 使用 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()
|
||||||
|
}
|
||||||
|
@ -7,10 +7,51 @@
|
|||||||
|
|
||||||
package gcache
|
package gcache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
|
)
|
||||||
|
|
||||||
type Engine struct {
|
type Engine struct {
|
||||||
ICacheAdapter
|
client ICacheAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var once sync.Once
|
||||||
|
|
||||||
|
var engine *Engine
|
||||||
|
|
||||||
func New(adapter ICacheAdapter) *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...)
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,8 @@ package gcache
|
|||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type ICacheAdapter interface {
|
type ICacheAdapter interface {
|
||||||
Get(key string) (string, error)
|
Get(key string, dest interface{}) error
|
||||||
Set(key string, val interface{}, exp time.Duration) error
|
Set(key string, val interface{}, exp time.Duration) error
|
||||||
Del(keys ...string) int64
|
Del(keys ...string) (int64, error)
|
||||||
Has(key string) bool
|
Has(key string) bool
|
||||||
End()
|
|
||||||
}
|
}
|
||||||
|
70
gcache/cache_test.go
Normal file
70
gcache/cache_test.go
Normal 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)
|
||||||
|
}
|
@ -15,12 +15,19 @@
|
|||||||
:imagesdir: ./img
|
:imagesdir: ./img
|
||||||
|
|
||||||
|
|
||||||
**注:** 暂时直接使用 `go-resdis/cache`
|
== 实现
|
||||||
|
|
||||||
|
已于 2023-06-21 实现。
|
||||||
|
|
||||||
|
可以基于 `redis` 进行一些基本使用。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
== 设计
|
||||||
|
|
||||||
从使用倒推设计。
|
从使用倒推设计。
|
||||||
|
|
||||||
== 场景1
|
=== 场景1
|
||||||
|
|
||||||
自己管理 `key`:
|
自己管理 `key`:
|
||||||
|
|
||||||
@ -38,7 +45,7 @@ return data
|
|||||||
<1> `get` 值为 `false` 表示没有缓存或缓存已过期
|
<1> `get` 值为 `false` 表示没有缓存或缓存已过期
|
||||||
<2> 7200 为缓存有效期(单位为秒),若指定为 0 表示不过期。
|
<2> 7200 为缓存有效期(单位为秒),若指定为 0 表示不过期。
|
||||||
|
|
||||||
== 场景2
|
=== 场景2
|
||||||
|
|
||||||
程序自动管理 `key`:
|
程序自动管理 `key`:
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user