添加自定义memorycache
This commit is contained in:
parent
ff3e032d6d
commit
c0b8c7ba63
8
main.go
8
main.go
|
|
@ -32,10 +32,12 @@ func main() {
|
|||
if err != nil {
|
||||
panic("failed to connect database:" + err.Error())
|
||||
}
|
||||
if proto.Config.MEMORY_CACHE == false { //不开启内存缓存,才使用redis
|
||||
err = worker.InitRedis()
|
||||
if err != nil {
|
||||
panic("failed to connect redis:" + err.Error())
|
||||
}
|
||||
}
|
||||
r.Use(handler.CrosHandler())
|
||||
r.Use(JWTAuthMiddleware()) // 使用 JWT 认证中间件
|
||||
handler.SetUpVideoGroup(r) // Video
|
||||
|
|
@ -233,7 +235,11 @@ func myTask() {
|
|||
service.ShellWillRunFromServer()
|
||||
service.SyncTokenSecretFromUserCenter()
|
||||
service.DelDBMMap() //定时处理DBMMap中的数据
|
||||
|
||||
if proto.Config.MEMORY_CACHE {
|
||||
worker.DeleteMemoryCacheCron()
|
||||
// 清理后持久化
|
||||
worker.WriteMemoryCacheToFile()
|
||||
}
|
||||
}
|
||||
|
||||
func ReadConfigToSetSystem() {
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ type ConfigStruct struct {
|
|||
TOKEN_USE_REDIS bool `json:"token_use_redis"`
|
||||
REDIS_User_PW bool `json:"redis_user_pw"` // 是否使用密码
|
||||
REDIS_PASSWORD string `json:"redis_password"`
|
||||
MEMORY_CACHE bool `json:"memory_cache"` //使用程序内缓存,开启这个redis将不生效
|
||||
REDIS_DB int `json:"redis_db"`
|
||||
TOKEN_SECRET string `json:"token_secret"`
|
||||
CID_BASE_DIR string `json:"cid_base_dir"`
|
||||
|
|
|
|||
|
|
@ -0,0 +1,186 @@
|
|||
package worker
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"math"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// MemoryCacheValue 缓存值结构,包含值和过期时间
|
||||
type MemoryCacheValue struct {
|
||||
Value string `json:"value"`
|
||||
ExpireAt int64 `json:"expireAt"` // 过期时间戳,秒级
|
||||
}
|
||||
|
||||
var (
|
||||
memoryCacheData = NewMemoryCache()
|
||||
)
|
||||
|
||||
// MemoryCache 线程安全的内存缓存
|
||||
type MemoryCache struct {
|
||||
data map[string]MemoryCacheValue
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
// NewMemoryCache 创建新的内存缓存实例
|
||||
func NewMemoryCache() *MemoryCache {
|
||||
return &MemoryCache{
|
||||
data: make(map[string]MemoryCacheValue),
|
||||
}
|
||||
}
|
||||
|
||||
// InitStaticMemoryCache 初始化全局缓存实例
|
||||
func InitStaticMemoryCache() {
|
||||
// 先尝试从文件加载
|
||||
ReadMemoryCacheFromJsonFile()
|
||||
|
||||
}
|
||||
|
||||
// SetWithExp 设置带过期时间的键值对
|
||||
func (mc *MemoryCache) SetWithExp(key string, value string, expireAt int64) {
|
||||
mc.mu.Lock()
|
||||
defer mc.mu.Unlock()
|
||||
mc.data[key] = MemoryCacheValue{value, expireAt}
|
||||
}
|
||||
|
||||
// Get 获取键值,如果已过期则返回空并删除
|
||||
func (mc *MemoryCache) Get(key string) string {
|
||||
// 先加读锁检查
|
||||
mc.mu.RLock()
|
||||
value, ok := mc.data[key]
|
||||
mc.mu.RUnlock()
|
||||
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 检查是否过期
|
||||
now := time.Now().Unix()
|
||||
if value.ExpireAt > now {
|
||||
return value.Value
|
||||
}
|
||||
|
||||
// 已过期,删除该键
|
||||
mc.mu.Lock()
|
||||
// 二次检查,防止并发情况下已被删除
|
||||
if v, exists := mc.data[key]; exists && v.ExpireAt <= now {
|
||||
delete(mc.data, key)
|
||||
}
|
||||
mc.mu.Unlock()
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// Set 设置永不过期的键值对
|
||||
func (mc *MemoryCache) Set(key string, value string) {
|
||||
mc.SetWithExp(key, value, math.MaxInt64)
|
||||
}
|
||||
|
||||
// Del 删除指定键
|
||||
func (mc *MemoryCache) Del(key string) {
|
||||
mc.mu.Lock()
|
||||
defer mc.mu.Unlock()
|
||||
delete(mc.data, key)
|
||||
}
|
||||
|
||||
// Clear 清空所有缓存
|
||||
func (mc *MemoryCache) Clear() {
|
||||
mc.mu.Lock()
|
||||
defer mc.mu.Unlock()
|
||||
mc.data = make(map[string]MemoryCacheValue)
|
||||
}
|
||||
|
||||
const CRON_MAX_DEL_NUMBER = 100 // 每次清理的最大数量
|
||||
|
||||
// DeleteMemoryCacheCron 定时清理过期键
|
||||
func DeleteMemoryCacheCron() {
|
||||
memoryCacheData.mu.Lock()
|
||||
defer memoryCacheData.mu.Unlock()
|
||||
|
||||
now := time.Now().Unix()
|
||||
i := 0
|
||||
for key, value := range memoryCacheData.data {
|
||||
if i >= CRON_MAX_DEL_NUMBER {
|
||||
break
|
||||
}
|
||||
if value.ExpireAt < now {
|
||||
delete(memoryCacheData.data, key)
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetMemoryCacheFilePath 获取缓存持久化文件路径
|
||||
func GetMemoryCacheFilePath() string {
|
||||
if os.Getenv("OS") == "Windows_NT" {
|
||||
return "C:/Users/Administrator/vp_mc.json"
|
||||
}
|
||||
return "/etc/vp_mc.json"
|
||||
}
|
||||
|
||||
// WriteMemoryCacheToFile 将缓存写入文件持久化
|
||||
func WriteMemoryCacheToFile() {
|
||||
memoryCacheData.mu.RLock()
|
||||
defer memoryCacheData.mu.RUnlock()
|
||||
|
||||
path := GetMemoryCacheFilePath()
|
||||
data, err := json.MarshalIndent(memoryCacheData.data, "", " ")
|
||||
if err != nil {
|
||||
log.Println("mc write file json err:", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 先写入临时文件,再原子替换,防止文件损坏
|
||||
tempPath := path + ".tmp"
|
||||
if err := os.WriteFile(tempPath, data, 0644); err != nil {
|
||||
log.Println("mc write temp file err:", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := os.Rename(tempPath, path); err != nil {
|
||||
log.Println("mc rename file err:", err)
|
||||
os.Remove(tempPath) // 清理临时文件
|
||||
}
|
||||
}
|
||||
|
||||
// ReadMemoryCacheFromJsonFile 从文件加载缓存
|
||||
func ReadMemoryCacheFromJsonFile() {
|
||||
path := GetMemoryCacheFilePath()
|
||||
_, err := os.Stat(path)
|
||||
if err != nil {
|
||||
log.Println("mc file not exists:", err)
|
||||
return
|
||||
}
|
||||
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
log.Println("mc open file err:", err)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
var data map[string]MemoryCacheValue
|
||||
decoder := json.NewDecoder(file)
|
||||
if err := decoder.Decode(&data); err != nil {
|
||||
log.Println("mc decode file err:", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 过滤已过期的数据
|
||||
now := time.Now().Unix()
|
||||
memoryCacheData.mu.Lock()
|
||||
for k, v := range data {
|
||||
if v.ExpireAt > now || v.ExpireAt == math.MaxInt64 {
|
||||
memoryCacheData.data[k] = v
|
||||
}
|
||||
}
|
||||
memoryCacheData.mu.Unlock()
|
||||
}
|
||||
|
||||
// 提供全局缓存的访问方法
|
||||
func GetGlobalCache() *MemoryCache {
|
||||
return memoryCacheData
|
||||
}
|
||||
Loading…
Reference in New Issue