golang高性能内存键值存储与指针缓存插件库go-mcache的使用

Golang高性能内存键值存储与指针缓存插件库go-mcache的使用

简介

go-mcache是一个高性能、线程安全的内存键值缓存库,支持过期时间和最小GC压力。

特性

  • 分片存储:256个可配置分片,减少锁竞争并支持水平扩展
  • 单一过期调度器:使用一个后台goroutine和最小堆处理所有TTL,避免每个键使用定时器
  • 零分配热路径:使用池化条目和直接值存储,避免反射并减少GC压力
  • 原子计数器:O(1)复杂度获取长度,无需遍历分片
  • 标准接口:可作为map[string]interface{}的替代品,提供以下方法:
    • Set(key string, value interface{}, ttl time.Duration) error
    • Get(key string) (value interface{}, ok bool)
    • Delete(key string)
    • Len() int
    • Close() map[string]interface{}
  • 优雅关闭Close方法会停止过期调度器并返回剩余条目
  • 自定义选项
    • WithShardCount(n int)调整分片数量(必须是2的幂)
    • WithPollInterval(d time.Duration)设置GC轮询间隔
  • 全面的测试和基准测试:内置线程安全测试和微基准测试用于吞吐量分析

安装

go get -u github.com/OrlovEvgeny/go-mcache

使用示例

package main

import (
	"fmt"
	"log"
	"time"

	"github.com/OrlovEvgeny/go-mcache"
)

type User struct {
	Name string
	Age  int
}

func main() {
	// 创建默认配置的缓存(256分片)
	cache := mcache.New()
	defer func() {
		// 停止内部调度器并获取剩余条目
		items := cache.Close()
		fmt.Printf("Remaining entries: %d\n", len(items))
	}()

	// 存储一个结构体指针,TTL为20分钟
	key := "user:123"
	user := &User{Name: "Alice", Age: 30}
	if err := cache.Set(key, user, 20*time.Minute); err != nil {
		log.Fatalf("Set error: %v", err)
	}

	// 获取值
	if v, ok := cache.Get(key); ok {
		loaded := v.(*User)
		fmt.Printf("Loaded user: %s (age %d)\n", loaded.Name, loaded.Age)
	} else {
		fmt.Println("Key expired or not found")
	}

	// 删除条目
	cache.Delete(key)
}

高级配置

// 512分片和30秒GC间隔
cache := mcache.New(
	mcache.WithShardCount(512),
	mcache.WithPollInterval(30*time.Second),
)

基准测试

运行基准测试命令:

go test -bench . -benchmem

Apple M1 Pro上的典型结果:

goos: darwin
goarch: arm64
pkg: github.com/OrlovEvgeny/go-mcache
cpu: Apple M1 Pro
BenchmarkCacheOperations
BenchmarkCacheOperations/Write
BenchmarkCacheOperations/Write-8         	 1836590	       663.0 ns/op	     605 B/op	       3 allocs/op
BenchmarkCacheOperations/Read
BenchmarkCacheOperations/Read-8          	 6350031	       167.5 ns/op	      85 B/op	       1 allocs/op
BenchmarkCacheOperations/WriteRead
BenchmarkCacheOperations/WriteRead-8     	 1786278	       704.6 ns/op	     665 B/op	       4 allocs/op
BenchmarkCacheOperations/ParallelReadWrite
BenchmarkCacheOperations/ParallelReadWrite-8         	 4477581	       288.0 ns/op	     227 B/op	       5 allocs/op

贡献

欢迎贡献代码!请fork项目,改进后提交pull request。确保新代码包含测试并遵循Go标准(go fmt, go vet)。

许可证

本项目采用MIT许可证。


更多关于golang高性能内存键值存储与指针缓存插件库go-mcache的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang高性能内存键值存储与指针缓存插件库go-mcache的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Go-MCache:高性能内存键值存储与指针缓存库

Go-MCache 是一个高性能的 Golang 内存键值存储库,特别适合需要快速访问缓存数据的场景。它提供了类似 Redis 的接口但完全在内存中运行,避免了网络开销。

主要特性

  1. 极高性能:基于哈希表实现,O(1)时间复杂度
  2. 内存高效:自动过期和内存回收机制
  3. 并发安全:内置读写锁,支持高并发
  4. 丰富API:支持设置过期时间、批量操作等

基本使用

首先安装 go-mcache:

go get github.com/OrlovEvgeny/go-mcache

基础示例

package main

import (
	"fmt"
	"time"
	"github.com/OrlovEvgeny/go-mcache"
)

func main() {
	// 创建缓存实例
	cache := mcache.New()

	// 设置键值对,不带过期时间
	cache.Set("username", "john_doe")

	// 设置带过期时间的键值对(10秒后过期)
	cache.SetEx("session_token", "abc123", 10*time.Second)

	// 获取值
	if value, ok := cache.Get("username"); ok {
		fmt.Println("Username:", value) // 输出: Username: john_doe
	}

	// 检查键是否存在
	if cache.Has("session_token") {
		fmt.Println("Session token exists")
	}

	// 删除键
	cache.Delete("username")

	// 等待过期
	time.Sleep(11 * time.Second)
	if !cache.Has("session_token") {
		fmt.Println("Session token has expired")
	}
}

高级功能

指针缓存

Go-MCache 特别适合缓存指针类型,避免值拷贝:

type User struct {
	ID       int
	Username string
	Email    string
}

func main() {
	cache := mcache.New()
	
	user := &User{
		ID:       1,
		Username: "johndoe",
		Email:    "john@example.com",
	}
	
	// 存储指针
	cache.Set("user:1", user)
	
	// 获取指针
	if val, ok := cache.Get("user:1"); ok {
		retrievedUser := val.(*User)
		fmt.Printf("User: %+v\n", retrievedUser)
	}
}

批量操作

func main() {
	cache := mcache.New()
	
	// 批量设置
	items := map[string]interface{}{
		"key1": "value1",
		"key2": "value2",
		"key3": "value3",
	}
	cache.MSet(items)
	
	// 批量获取
	keys := []string{"key1", "key2", "key3"}
	values := cache.MGet(keys...)
	
	for i, key := range keys {
		if val, ok := values[i]; ok {
			fmt.Printf("%s: %v\n", key, val)
		}
	}
}

自动删除回调

func main() {
	cache := mcache.New()
	
	// 设置删除回调函数
	cache.SetOnDeletedCallback(func(key string, value interface{}) {
		fmt.Printf("Key %s with value %v was deleted\n", key, value)
	})
	
	cache.SetEx("temp_data", "some value", 2*time.Second)
	
	time.Sleep(3 * time.Second) // 等待过期触发回调
}

性能优化建议

  1. 合理设置过期时间:避免内存无限增长
  2. 批量操作:减少锁竞争
  3. 指针存储:对于大型结构体,存储指针而非值
  4. 避免频繁创建/销毁:重用缓存实例

与标准库 sync.Map 对比

特性 go-mcache sync.Map
过期时间支持
内存回收
回调通知
原生Go实现
批量操作

适用场景

  • Web 会话存储
  • API 响应缓存
  • 频繁访问的配置数据
  • 临时计算结果的缓存

Go-MCache 通过其简单而强大的 API 为 Golang 应用程序提供了高效的内存缓存解决方案,特别适合需要快速键值访问的中小型数据缓存场景。

回到顶部