gin框架实践连载番外篇 | 3天打造专属Cache(Second day)

1,078 阅读2分钟

引言

  • 接着上一篇的文章,我们这期实现用redis做存储源
  • 没有看过上一篇的同学请关注第一天链接
  • 本文go-redis客户端引入是v8版本
  • 案例代码地址

1、定义store结构体

import (
	"context"
	"log"
	"time"

	"github.com/18211167516/gocache"
	"github.com/go-redis/redis/v8"
)

var (
	RedisName = "Redis"
	Ctx       context.Context //v8版本的reids除妖
)

type RedisStore struct {
	reidsClient *redis.Client
}

2、实例化store以及注册cache

func NewRedis(addr, password string, db, PoolSize int) *RedisStore {

	ClientRedis := redis.NewClient(&redis.Options{
		Addr:     addr,
		Password: password, // no password set
		DB:       db,       // use default DB
		PoolSize: PoolSize, // 连接池大小
		//MinIdleConns: 5,
	})

	Ctx = ClientRedis.Context()

	err := ClientRedis.Ping(Ctx).Err()
	if err != nil {
		log.Panic("Cache store redis:", err)
	}

	return &RedisStore{
		reidsClient: ClientRedis,
	}
}

//方便外部调用注册
func RegisterRedis(addr, password string, db, PoolSize int) {
	gocache.Register(RedisName, NewRedis(addr, password, db, PoolSize))
}

3、实现方法(是比较简单的,主要还是学习go-redis的用法)

// GC 定期扫删除过期键
func (ms *RedisStore) GC() {

}

func (ms *RedisStore) GetStoreName() string {
	return RedisName
}

func (ms *RedisStore) Get(key string) (interface{}, error) {
	return ms.reidsClient.Get(Ctx, key).Result()
}

func (ms *RedisStore) Set(key string, value interface{}, d int) error {
	return ms.reidsClient.Set(Ctx, key, value, time.Duration(d)*time.Second).Err()
}

func (ms *RedisStore) Delete(key string) error {
	return ms.reidsClient.Del(Ctx, key).Err()
}

func (ms *RedisStore) Has(key string) error {
	return ms.reidsClient.Exists(Ctx, key).Err()
}

func (ms *RedisStore) Forever(key string, value interface{}) error {
	return ms.reidsClient.Set(Ctx, key, value, 0).Err()
}

func (ms *RedisStore) Clear() error {
	return ms.reidsClient.FlushDB(Ctx).Err()
}

func (ms *RedisStore) Size() int {
	return int(ms.reidsClient.DBSize(Ctx).Val())
}

func (ms *RedisStore) GetTTl(key string) (time.Duration, error) {
	return ms.reidsClient.TTL(Ctx, key).Result()
}

func (ms *RedisStore) IsExpire(key string) (bool, error) {
	res, err := ms.reidsClient.Exists(Ctx, key).Result()
	if err != nil {
		return false, err
	} else {
		if res > 0 {
			return false, err
		} else {
			return true, err
		}
	}
}

4、go-redis的用法 推荐链接

有相关的文章,我就不写了

5、demo走起

package main

import (
	"fmt"
	"log"
	"time"

	"github.com/18211167516/gocache"
	"github.com/18211167516/gocache/store"
)

func main() {
	//先注册
	store.RegisterRedis("192.168.99.100:6379", "", 10, 10)
	cache, err := gocache.New("redis")
	if err != nil {
		log.Fatalf("初始化缓存管理器 失败 %s", err)
	}

	fmt.Println("获取store type:", cache.GetStoreName())

	fmt.Println(time.Now())
	fmt.Println("删除全部:", fmt.Sprintln(cache.Clear()))
	if err := cache.Set("aaaa", "123123", 100); err != nil {
		log.Fatalf("设置键 %s 的value 失败 %s", "aaaa", err)
	}

	fmt.Println("判断键值:", fmt.Sprintln(cache.Has("aaaa")))
	fmt.Println("获取键值:", fmt.Sprintln(cache.Get("aaaa")))
	fmt.Println("获取ttl:", fmt.Sprintln(cache.GetTTl("aaaa")))
	/* fmt.Println("设置永久键值:", cache.Forever("bbb", "bbbb"))
	fmt.Println("获取ttl:", fmt.Sprintln(cache.GetTTl("bbb")))
	fmt.Println("获取键值:", fmt.Sprintln(cache.Get("bbb"))) */

	_ = cache.Set("cccc", "cccc", 5)
	_ = cache.Set("dddd", "dddd", 20)
	fmt.Println("获取键值:", fmt.Sprintln(cache.Get("cccc")))
	time.Sleep(time.Duration(5) * time.Second)

	fmt.Println("延迟5秒获取键值:", fmt.Sprintln(cache.Get("cccc")))

	fmt.Println("获取键值:", fmt.Sprintln(cache.Get("dddd")))
	fmt.Println("获取ttl:", fmt.Sprintln(cache.GetTTl("dddd")))
	//fmt.Println("删除全部:", fmt.Sprintln(cache.Clear()))
	fmt.Println("缓存个数:", cache.Size())
	//select {}

	ticker := time.NewTicker(5 * time.Second)

exit:
	for {
		select {
		case <-ticker.C:
			size := cache.Size()
			fmt.Println("缓存个数:", size)
			if size == 0 {
				ticker.Stop()
				break exit
			}
		}
	}

}


6、结尾

go-redis的一些思路其实也可以用到,通过一个结构体来存储返回值(相对比较优雅,需要什么值就取什么值) redis的过期策略是惰性删除加定期删除(所以不需要我们)

7、系列文章