golang支持集群和独立项过期的高性能缓存插件clusteredBigCache的使用
Golang支持集群和独立项过期的高性能缓存插件clusteredBigCache的使用
clusteredBigCache是一个基于bigcache的库,经过修改后支持集群和独立项过期功能。它允许你在多个应用实例之间共享缓存数据,而无需依赖外部缓存服务如Redis或Memcached。
安装
使用go get命令安装:
$ go get github.com/oaStuff/clusteredBigCache
示例1:写入缓存的应用
这是一个将数据写入缓存的应用示例:
package main
import (
"fmt"
"bufio"
"os"
"github.com/oaStuff/clusteredBigCache/Cluster"
"strings"
"time"
)
// main函数
func main() {
fmt.Println("starting...")
// 使用默认配置创建缓存
cache := clusteredBigCache.New(clusteredBigCache.DefaultClusterConfig(), nil)
count := 1
// 必须调用Start()方法
cache.Start()
reader := bufio.NewReader(os.Stdin)
var data string
for strings.ToLower(data) != "exit" {
fmt.Print("enter data : ")
data, _ = reader.ReadString('\n')
data = strings.TrimSpace(data)
// 将数据存入缓存,设置60分钟过期时间
err := cache.Put(fmt.Sprintf("key_%d", count), []byte(data), time.Minute * 60)
if err != nil {
panic(err)
}
fmt.Printf("'%s' stored under key 'key_%d'\n", data, count)
count++
}
}
说明
cache := clusteredBigCache.New(clusteredBigCache.DefaultClusterConfig(), nil)
使用默认配置创建缓存cache.Start()
必须在调用其他方法前执行cache.Put()
方法接收键、值(字节切片)和过期时间三个参数
示例2:读取缓存的应用
这是一个从缓存读取数据的应用示例,可以运行在同一台或不同机器上:
package main
import (
"github.com/oaStuff/clusteredBigCache/Cluster"
"bufio"
"os"
"strings"
"fmt"
"time"
)
func main() {
config := clusteredBigCache.DefaultClusterConfig()
// 修改本地端口避免冲突
config.LocalPort = 8888
// 设置为加入模式
config.Join = true
// 设置要加入的集群节点地址
config.JoinIp = "127.0.0.1:9911"
cache := clusteredBigCache.New(config, nil)
err := cache.Start()
if err != nil {
panic(err)
}
reader := bufio.NewReader(os.Stdin)
var data string
for strings.ToLower(data) != "exit" {
fmt.Print("enter key : ")
data, _ = reader.ReadString('\n')
data = strings.TrimSpace(data)
// 从缓存获取数据,设置160毫秒超时
value, err := cache.Get(data, time.Millisecond * 160)
if err != nil {
fmt.Println(err)
continue
}
fmt.Printf("you got '%s' from the cache\n", value)
}
}
说明
config.Join = true
表示要加入一个现有集群config.JoinIp
指定要加入的集群节点地址cache.Get()
方法接收键和超时时间两个参数
配置示例
可以通过命令行参数配置缓存:
join := flag.String("join", "", "ipAddr:port number of remote server")
localPort := flag.Int("port", 6060, "local server port to bind to")
flag.Parse()
config := clusteredBigCache.DefaultClusterConfig()
if *join != "" {
config.JoinIp = *join
config.Join = true
}
config.LocalPort = *localPort
日志记录
clusteredBigCache支持自定义日志记录器:
type myLogger func(...interface{})
func (log myLogger) Info(msg string) {
log(msg)
}
func (log myLogger) Warn(msg string) {
log(msg)
}
func (log myLogger) Error(msg string) {
log(msg)
}
func (log myLogger) Critical(msg string) {
log(msg)
}
// 使用自定义日志记录器
cache := clusteredBigCache.New(config, myLogger(log.Println))
被动客户端
可以创建不存储数据的被动客户端:
// 连接到现有集群
cache := clusteredBigCache.NewPassiveClient("linux_box_100","localhost:9090", 8885, 0, 0, 0, nil)
特点
- 支持集群 - 多个应用实例可以共享缓存
- 支持独立项过期 - 每个缓存项可以设置不同的过期时间
- 高性能 - 基于bigcache的高性能实现
- 无需外部服务 - 不需要Redis或Memcached等外部服务
许可证
MIT许可证
更多关于golang支持集群和独立项过期的高性能缓存插件clusteredBigCache的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang支持集群和独立项过期的高性能缓存插件clusteredBigCache的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang高性能集群缓存插件:clusteredBigCache
clusteredBigCache是一个基于BigCache的高性能分布式缓存解决方案,支持集群模式和独立项过期功能。它结合了BigCache的内存高效性和集群扩展能力,非常适合需要高性能缓存的分布式系统。
主要特性
- 基于BigCache的高性能内存缓存
- 支持集群模式,多节点共享缓存
- 支持独立项的过期时间设置
- 低GC压力,高吞吐量
- 简单易用的API接口
安装
go get github.com/allegro/bigcache
go get github.com/redis/go-redis/v9
注意:clusteredBigCache是一个概念性实现,实际使用时可能需要根据具体需求调整。
基本使用示例
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/allegro/bigcache"
"github.com/redis/go-redis/v9"
)
type ClusteredBigCache struct {
localCache *bigcache.BigCache
redisClient *redis.Client
}
func NewClusteredBigCache(localConfig bigcache.Config, redisOpts *redis.Options) (*ClusteredBigCache, error) {
localCache, err := bigcache.NewBigCache(localConfig)
if err != nil {
return nil, err
}
redisClient := redis.NewClient(redisOpts)
return &ClusteredBigCache{
localCache: localCache,
redisClient: redisClient,
}, nil
}
func (c *ClusteredBigCache) Set(ctx context.Context, key string, value []byte, expiration time.Duration) error {
// 设置本地缓存
err := c.localCache.Set(key, value)
if err != nil {
return err
}
// 设置分布式缓存
return c.redisClient.Set(ctx, key, value, expiration).Err()
}
func (c *ClusteredBigCache) Get(ctx context.Context, key string) ([]byte, error) {
// 先从本地缓存获取
value, err := c.localCache.Get(key)
if err == nil {
return value, nil
}
// 本地缓存不存在,从Redis获取
value, err = c.redisClient.Get(ctx, key).Bytes()
if err != nil {
return nil, err
}
// 将Redis中的值存入本地缓存
_ = c.localCache.Set(key, value)
return value, nil
}
func (c *ClusteredBigCache) Delete(ctx context.Context, key string) error {
// 删除本地缓存
_ = c.localCache.Delete(key)
// 删除分布式缓存
return c.redisClient.Del(ctx, key).Err()
}
func main() {
// 本地缓存配置
localConfig := bigcache.Config{
Shards: 1024,
LifeWindow: 10 * time.Minute,
CleanWindow: 5 * time.Minute,
MaxEntriesInWindow: 1000 * 10 * 60,
MaxEntrySize: 500,
Verbose: true,
HardMaxCacheSize: 8192,
}
// Redis配置
redisOpts := &redis.Options{
Addr: "localhost:6379",
Password: "", // 无密码
DB: 0, // 默认DB
}
// 创建集群缓存实例
cache, err := NewClusteredBigCache(localConfig, redisOpts)
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
// 设置缓存项,带过期时间
err = cache.Set(ctx, "myKey", []byte("myValue"), 5*time.Minute)
if err != nil {
log.Fatal(err)
}
// 获取缓存项
value, err := cache.Get(ctx, "myKey")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Got value: %s\n", value)
// 删除缓存项
err = cache.Delete(ctx, "myKey")
if err != nil {
log.Fatal(err)
}
}
高级功能实现
1. 独立项过期时间
func (c *ClusteredBigCache) SetWithExpiration(ctx context.Context, key string, value []byte, expiration time.Duration) error {
// 设置本地缓存 - BigCache本身不支持独立项过期,所以使用最短的过期时间
err := c.localCache.Set(key, value)
if err != nil {
return err
}
// 设置Redis缓存,带独立过期时间
return c.redisClient.Set(ctx, key, value, expiration).Err()
}
2. 缓存预热
func (c *ClusteredBigCache) WarmUp(ctx context.Context, keys []string) error {
for _, key := range keys {
value, err := c.redisClient.Get(ctx, key).Bytes()
if err != nil {
continue
}
_ = c.localCache.Set(key, value)
}
return nil
}
3. 批量操作
func (c *ClusteredBigCache) MGet(ctx context.Context, keys []string) (map[string][]byte, error) {
result := make(map[string][]byte)
// 先检查本地缓存
for _, key := range keys {
if value, err := c.localCache.Get(key); err == nil {
result[key] = value
}
}
// 检查剩余未在本地缓存中找到的键
var missingKeys []string
for _, key := range keys {
if _, found := result[key]; !found {
missingKeys = append(missingKeys, key)
}
}
if len(missingKeys) > 0 {
values, err := c.redisClient.MGet(ctx, missingKeys...).Result()
if err != nil {
return nil, err
}
for i, key := range missingKeys {
if values[i] == nil {
continue
}
valStr, ok := values[i].(string)
if !ok {
continue
}
val := []byte(valStr)
result[key] = val
_ = c.localCache.Set(key, val)
}
}
return result, nil
}
性能优化建议
- 合理配置BigCache参数:根据应用场景调整Shards数量、LifeWindow等参数
- 使用连接池:确保Redis客户端配置了合适的连接池大小
- 批量操作:尽可能使用批量操作减少网络往返
- 本地缓存策略:根据数据访问模式调整本地缓存大小和过期时间
- 监控:监控缓存命中率和响应时间,及时调整配置
注意事项
- BigCache不支持独立项的过期时间,集群模式下依赖Redis实现此功能
- 本地缓存和分布式缓存之间可能存在短暂的不一致
- 对于极高吞吐量场景,可能需要考虑更复杂的缓存策略
- 确保有适当的缓存淘汰策略,防止内存溢出
clusteredBigCache这种混合缓存策略结合了本地缓存的高性能和分布式缓存的扩展性,非常适合需要高性能缓存的分布式系统。