文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Golang实现多存储驱动设计SDK案例

2024-04-02 19:55

关注

前言:

Gocache是一个基于Go语言编写的多存储驱动的缓存扩展组件。它为您带来了许多缓存数据的功能。

支持功能

多个缓存驱动存储:支持内存、redis或您自定义存储驱动。

支持如下功能:

默认情况下,Gocache支持如下几种缓存驱动:

开发缘由

在作者的官网博客中提到这样的几句话:

当我开始在 GraphQL Go 项目上实现缓存时,它已经有一个内存缓存,它使用了一个具有简单 API 的小库,但也使用了另一个内存缓存库来使用具有不同库和 API 的批处理模式加载数据,做同样的事情:缓存项目。后来,我们还有一个需求:除了这个内存缓存之外,我们还想使用 Redis 添加一层分布式缓存,主要是为了避免我们的新 Kubernetes pod 在将新版本的应用程序投入生产时出现空缓存。

因此,作者想到是时候拥有一个统一的API来管理多个缓存存储:内存、redis、memcache 或任何你想要的。

如何使用

安装

要开始使用最新版本的 go-cache,您可以使用以下命令:

go get github.com/eko/gocache/v3

为避免尝试导入库时出现任何错误,请使用以下导入语句:

import (
	"github.com/eko/gocache/v3/cache"
	"github.com/eko/gocache/v3/store"
)

如果您遇到任何错误,请务必运行go mod tidy以清理您的 go.mod 文件。

存储适配器

首先,当您要缓存项目时,您必须选择要缓存项目的位置:在内存中?在共享的 redis 或 memcache 中?或者可能在另一个存储中。

目前,Gocache 实现了以下存储:

所有这些商店都实现了一个非常简单的 API,它遵循以下接口:

type StoreInterface interface {
	Get(key interface{}) (interface{}, error)
	Set(key interface{}, value interface{}, options *Options) error
	Delete(key interface{}) error
	Invalidate(options InvalidateOptions) error
	Clear() error
	GetType() string
}

此接口代表您可以在商店中执行的所有操作,并且每个操作都调用客户端库中的必要方法。所有这些存储都有不同的配置,具体取决于您要使用的客户端库,

例如,初始化 Memcache 存储:

store := store.NewMemcache(
	memcache.New("10.0.0.1:11211", "10.0.0.2:11211", "10.0.0.3:11212"),
	&store.Options{
		Expiration: 10*time.Second,
	},
)

然后,必须将初始化的存储传递给缓存对象构造函数。

缓存适配器

一个缓存接口来统治它们。

缓存接口与存储接口完全相同,因为基本上,缓存将对存储执行操作:

type CacheInterface interface {
	Get(key interface{}) (interface{}, error)
	Set(key, object interface{}, options *store.Options) error
	Delete(key interface{}) error
	Invalidate(options store.InvalidateOptions) error
	Clear() error
	GetType() string
}

使用这个界面,我可以对缓存项执行所有必要的操作:设置、获取、删除、无效数据、清除所有缓存和另一个方法 (GetType),它可以让我知道当前缓存项是什么,很有用在某些情况下。

从这个接口开始,实现的缓存类型如下:

下面是一个简单的 Memcache 示例:

memcacheStore := store.NewMemcache(
	memcache.New("10.0.0.1:11211", "10.0.0.2:11211", "10.0.0.3:11212"),
	&store.Options{
		Expiration: 10*time.Second,
	},
)
cacheManager := cache.New(memcacheStore)
err := cacheManager.Set("my-key", []byte("my-value"), &cache.Options{
	Expiration: 15*time.Second, // Override default value of 10 seconds defined in the store
})
if err != nil {
    panic(err)
}
value := cacheManager.Get("my-key")
cacheManager.Delete("my-key")
cacheManager.Clear() 
// Clears the entire cache, in case you want to flush all cache

现在,假设您想要一个链式缓存,其中包含一个内存 Ristretto 存储和一个分布式 Redis 存储作为后备,

并带有一个 marshaller 和指标作为结果:

// Initialize Ristretto cache and Redis client
ristrettoCache, err := ristretto.NewCache(&ristretto.Config{NumCounters: 1000, MaxCost: 100, BufferItems: 64})
if err != nil {
    panic(err)
}
redisClient := redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379"})

// Initialize stores
ristrettoStore := store.NewRistretto(ristrettoCache, nil)
redisStore := store.NewRedis(redisClient, &cache.Options{Expiration: 5*time.Second})

// Initialize Prometheus metrics
promMetrics := metrics.NewPrometheus("my-amazing-app")
// Initialize chained cache
cacheManager := cache.NewMetric(promMetrics, cache.NewChain(
    cache.New(ristrettoStore),
    cache.New(redisStore),
))
// Initializes a marshaler
marshal := marshaler.New(cacheManager)

key := BookQuery{Slug: "my-test-amazing-book"}
value := Book{ID: 1, Name: "My test amazing book", Slug: "my-test-amazing-book"}

// Set the value in cache using given key
err = marshal.Set(key, value)
if err != nil {
    panic(err)
}
returnedValue, err := marshal.Get(key, new(Book))
if err != nil {
    panic(err)
}
// Then, do what you want with the value

我们还没有谈到 Marshaler,但它是 Gocache 的另一个功能:我们提供了一项服务来帮助您自动编组/解组您的对象从/到您的存储。

这在使用 struct 对象作为键而不是内存存储时很有用,因为您必须将对象转换为字节。

所有这些功能:带有内存和 redis 的链式缓存、Prometheus 指标和封送处理程序只需大约 20 行代码即可完成。

编写自己的缓存或存储

如果您想实现自己的专有缓存,也很容易做到。

这是一个简单的示例,以防您想要记录在缓存中完成的每个操作(这不是一个好主意,但很好,这是一个简单的 todo 示例):

package customcache
import (
	"log"

	"github.com/eko/gocache/cache"
	"github.com/eko/gocache/store"
)
const LoggableType = "loggable"
type LoggableCache struct {
	cache cache.CacheInterface
}
func NewLoggable(cache cache.CacheInterface) *LoggableCache {
	return &LoggableCache{
		cache: cache,
	}
}

func (c *LoggableCache) Get(key interface{}) (interface{}, error) {
	log.Print("Get some data...")
	return c.cache.Get(key)
}

func (c *LoggableCache) Set(key, object interface{}, options *store.Options) error {
	log.Print("Set some data...")
	return c.cache.Set(key, object, options)
}
func (c *LoggableCache) Delete(key interface{}) error {
	log.Print("Delete some data...")
	return c.cache.Delete(key)
}
func (c *LoggableCache) Invalidate(options store.InvalidateOptions) error {
	log.Print("Invalidate some data...")
	return c.cache.Invalidate(options)
}
func (c *LoggableCache) Clear() error {
	log.Print("Clear some data...")
	return c.cache.Clear()
}
func (c *LoggableCache) GetType() string {
	return LoggableType
}

同样,您也可以实现自定义存储。如果您认为其他人可以使您的缓存或存储实现受益,请不要犹豫,打开拉取请求并直接为项目做出贡献,以便我们一起讨论您的想法并带来更强大的缓存库。

压缩

生成模拟测试数据:

go get github.com/golang/mock/mockgen
make mocks

测试套件可以运行:

make test # run unit test
make benchmark-store # run benchmark test

到此这篇关于Golang实现多存储驱动设计SDK案例的文章就介绍到这了,更多相关Golang SDK内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯