Skip to content

[开源推荐] 🚀 JetCache-Go - 媲美阿里 JetCache 的Go版本多级缓存框架 #2981

Open
@daoshenzzg

Description

@daoshenzzg

项目地址

https://github.com/mgtv-tech/jetcache-go

类别

Go

项目标题

🚀 JetCache-Go - 媲美阿里 JetCache 的Go版本多级缓存框架

项目描述

一、背景

背景是用 golang 开发一个并发量要求比较高的项目。提到高并发系统设计,就离不开三大利器:缓存、限流、降级。然而,在 golang 的开源世界,居然没找到一个趁手的工具:

要支持:

  • 多级缓存
  • 批量查询
  • 泛型
  • 自动刷新缓存
  • 缓存一致性机制
  • 指标采集
  • 自动降级

要解决:

  • 缓存穿透
  • 缓存击穿
  • 大 Key
  • 热 Key
  • 雪崩

要好用:

  • 透明代理
  • 灵活拓展

因此,就参考阿里巴巴开源的 JetCache 核心设计,打造了 Go 版本的 jetcache-go

亮点

jetcache-go是基于go-redis/cache拓展的通用缓存访问框架。 实现了类似Java版JetCache的核心功能,包括:

✅ 二级缓存自由组合:本地缓存、分布式缓存、本地缓存+分布式缓存
✅ Once接口采用单飞(singleflight)模式,高并发且线程安全
✅ 默认采用MsgPack来编解码Value。可选sonic、原生json
✅ 本地缓存默认实现了RistrettoFreeCache
✅ 分布式缓存默认实现了go-redis/v9的适配器,你也可以自定义实现
✅ 可以自定义errNotFound,通过占位符替换,缓存空结果防止缓存穿透
✅ 支持开启分布式缓存异步刷新
✅ 指标采集,默认实现了通过日志打印各级缓存的统计指标(QPM、Hit、Miss、Query、QueryFail)
✅ 分布式缓存查询故障自动降级
✅ MGet接口支持Load函数。带分布缓存场景,采用Pipeline模式实现 (v1.1.0+)
✅ 支持拓展缓存更新后所有GO进程的本地缓存失效 (v1.1.1+)

示例代码

截图或演示视频

使用示例:

Image

例举了两种常用的接口使用方式

  • Once 接口查询,并开启缓存自动刷新
  • MGet(稀疏列表缓存)泛型接口查询

我们内部脚手架封装好了通过配置即可初始化缓存实例。红线部分就是被代理的接口,哪怕是遇到了类似 gorm.RecordNotFound 也能被缓存并透明代理,有没有感觉使用非常简单?

功能概览:

Image

缓存指标统计:

支持实现stats.Handler接口并注册到 Cache 组件来自定义收集指标,例如使用Prometheus 采集指标。
我们默认实现了通过日志打印统计指标,如下所示:

2023/09/11 16:42:30.695294 statslogger.go:178: [INFO] jetcache-go stats last 1m0s.
cache       |         qpm|   hit_ratio|         hit|        miss|       query|  query_fail
------------+------------+------------+------------+------------+------------+------------
bench       |   216440123|     100.00%|   216439867|         256|         256|           0|
bench_local |   216440123|     100.00%|   216434970|        5153|           -|           -|
bench_remote|        5153|      95.03%|        4897|         256|           -|           -|
------------+------------+------------+------------+------------+------------+------------

实现stats.Handler接口并将指标采集到 Prometheus

Image

配置项说明:

可以看到,我们内置了很多例如 分布式缓存、本地缓存、序列化方式、命中率统计、日志等多种接口实现,用户也可以自己去实现相关接口做拓展。

配置项名称 配置项类型 缺省值 说明
name string default 缓存名称,用于日志标识和指标报告
remote remote.Remote 接口 nil remote 是分布式缓存,例如 Redis。也可以自定义,实现remote.Remote接口即可
local local.Local 接口 nil local 是内存缓存,例如 FreeCache、TinyLFU。也可以自定义,实现local.Local接口即可
codec string msgpack value的编码和解码方法。默认为 "msgpack"。可选:json | msgpack | sonic,也可以自定义,实现encoding.Codec接口并注册即可
errNotFound error nil 回源记录不存在时返回的错误,例:gorm.ErrRecordNotFound。用于防止缓存穿透(即缓存空对象)
remoteExpiry time.Duration 1小时 远程缓存 TTL,默认为 1 小时
notFoundExpiry time.Duration 1分钟 缓存未命中时占位符缓存的过期时间。默认为 1 分钟
offset time.Duration (0,10]秒 缓存未命中时的过期时间抖动因子
refreshDuration time.Duration 0 异步缓存刷新的间隔。默认为 0(禁用刷新)
stopRefreshAfterLastAccess time.Duration refreshDuration + 1秒 缓存停止刷新之前的持续时间(上次访问后)
refreshConcurrency int 4 刷新缓存任务池的并发刷新的最大数量
statsDisabled bool false 禁用缓存统计的标志
statsHandler stats.Handler 接口 stats.NewStatsLogger 指标统计收集器。默认内嵌实现了log统计,也可以使用jetcache-go-pluginPrometheus 插件。或自定义实现,只要实现stats.Handler接口即可
sourceID string 16位随机字符串 【缓存事件广播】缓存实例的唯一标识符
syncLocal bool false 【缓存事件广播】启用同步本地缓存的事件(仅适用于 "Both" 缓存类型)
eventChBufSize int 100 【缓存事件广播】事件通道的缓冲区大小(默认为 100)
eventHandler func(event *Event) nil 【缓存事件广播】处理本地缓存失效事件的函数
separatorDisabled bool false 禁用缓存键的分隔符。默认为false。如果为true,则缓存键不会使用分隔符。目前主要用于泛型接口的缓存key和ID拼接
separator string : 缓存键的分隔符。默认为 ":"。目前主要用于泛型接口的缓存key和ID拼接

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions