更新 cache/cache.go
This commit is contained in:
86
cache/cache.go
vendored
86
cache/cache.go
vendored
@@ -4,6 +4,7 @@ package cache
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -17,11 +18,11 @@ type CacheEntry struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MemoryCache struct {
|
type MemoryCache struct {
|
||||||
entries sync.Map
|
entries sync.Map
|
||||||
maxSize int64
|
maxSize int64
|
||||||
currentSize int64
|
currentSize int64
|
||||||
ttl time.Duration
|
ttl time.Duration
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMemoryCache(maxSize int64, ttl time.Duration) *MemoryCache {
|
func NewMemoryCache(maxSize int64, ttl time.Duration) *MemoryCache {
|
||||||
@@ -31,20 +32,24 @@ func NewMemoryCache(maxSize int64, ttl time.Duration) *MemoryCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 启动清理协程
|
// 启动清理协程
|
||||||
go mc.cleanup()
|
if ttl > 0 {
|
||||||
|
go mc.cleanup()
|
||||||
|
}
|
||||||
|
|
||||||
return mc
|
return mc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Age 返回缓存条目的年龄(秒)
|
||||||
func (e *CacheEntry) Age() string {
|
func (e *CacheEntry) Age() string {
|
||||||
age := time.Since(e.Timestamp)
|
age := time.Since(e.CreatedAt)
|
||||||
return strconv.FormatInt(int64(age.Seconds()), 10)
|
return strconv.FormatInt(int64(age.Seconds()), 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *MemoryCache) Get(key string) (*CacheEntry, bool) {
|
// Get 获取缓存条目
|
||||||
|
func (mc *MemoryCache) Get(key string) *CacheEntry {
|
||||||
val, ok := mc.entries.Load(key)
|
val, ok := mc.entries.Load(key)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, false
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
entry := val.(*CacheEntry)
|
entry := val.(*CacheEntry)
|
||||||
@@ -52,15 +57,26 @@ func (mc *MemoryCache) Get(key string) (*CacheEntry, bool) {
|
|||||||
// 检查是否过期
|
// 检查是否过期
|
||||||
if time.Now().After(entry.ExpiresAt) {
|
if time.Now().After(entry.ExpiresAt) {
|
||||||
mc.Delete(key)
|
mc.Delete(key)
|
||||||
return nil, false
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return entry, true
|
return entry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set 设置缓存条目
|
||||||
func (mc *MemoryCache) Set(key string, data []byte, headers map[string]string) bool {
|
func (mc *MemoryCache) Set(key string, data []byte, headers map[string]string) bool {
|
||||||
|
// 如果禁用缓存(maxSize = 0),直接返回
|
||||||
|
if mc.maxSize == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
size := int64(len(data))
|
size := int64(len(data))
|
||||||
|
|
||||||
|
// 如果单个条目超过最大缓存大小,不缓存
|
||||||
|
if size > mc.maxSize {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
mc.mu.Lock()
|
mc.mu.Lock()
|
||||||
defer mc.mu.Unlock()
|
defer mc.mu.Unlock()
|
||||||
|
|
||||||
@@ -84,12 +100,19 @@ func (mc *MemoryCache) Set(key string, data []byte, headers map[string]string) b
|
|||||||
Size: size,
|
Size: size,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果 key 已存在,先删除旧的
|
||||||
|
if oldVal, exists := mc.entries.Load(key); exists {
|
||||||
|
oldEntry := oldVal.(*CacheEntry)
|
||||||
|
mc.currentSize -= oldEntry.Size
|
||||||
|
}
|
||||||
|
|
||||||
mc.entries.Store(key, entry)
|
mc.entries.Store(key, entry)
|
||||||
mc.currentSize += size
|
mc.currentSize += size
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete 删除缓存条目
|
||||||
func (mc *MemoryCache) Delete(key string) {
|
func (mc *MemoryCache) Delete(key string) {
|
||||||
val, ok := mc.entries.LoadAndDelete(key)
|
val, ok := mc.entries.LoadAndDelete(key)
|
||||||
if ok {
|
if ok {
|
||||||
@@ -100,11 +123,26 @@ func (mc *MemoryCache) Delete(key string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear 清空所有缓存
|
||||||
|
func (mc *MemoryCache) Clear() {
|
||||||
|
mc.mu.Lock()
|
||||||
|
defer mc.mu.Unlock()
|
||||||
|
|
||||||
|
mc.entries.Range(func(key, value interface{}) bool {
|
||||||
|
mc.entries.Delete(key)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
mc.currentSize = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateKey 生成缓存键
|
||||||
func (mc *MemoryCache) GenerateKey(url string) string {
|
func (mc *MemoryCache) GenerateKey(url string) string {
|
||||||
hash := sha256.Sum256([]byte(url))
|
hash := sha256.Sum256([]byte(url))
|
||||||
return hex.EncodeToString(hash[:])
|
return hex.EncodeToString(hash[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// evictExpired 清理过期条目
|
||||||
func (mc *MemoryCache) evictExpired() {
|
func (mc *MemoryCache) evictExpired() {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
mc.entries.Range(func(key, value interface{}) bool {
|
mc.entries.Range(func(key, value interface{}) bool {
|
||||||
@@ -117,6 +155,7 @@ func (mc *MemoryCache) evictExpired() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// evictOldest 清理最旧的条目
|
||||||
func (mc *MemoryCache) evictOldest(needed int64) {
|
func (mc *MemoryCache) evictOldest(needed int64) {
|
||||||
type entryWithKey struct {
|
type entryWithKey struct {
|
||||||
key string
|
key string
|
||||||
@@ -133,7 +172,7 @@ func (mc *MemoryCache) evictOldest(needed int64) {
|
|||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
// 按创建时间排序
|
// 按创建时间排序(最旧的在前)
|
||||||
for i := 0; i < len(entries)-1; i++ {
|
for i := 0; i < len(entries)-1; i++ {
|
||||||
for j := i + 1; j < len(entries); j++ {
|
for j := i + 1; j < len(entries); j++ {
|
||||||
if entries[i].entry.CreatedAt.After(entries[j].entry.CreatedAt) {
|
if entries[i].entry.CreatedAt.After(entries[j].entry.CreatedAt) {
|
||||||
@@ -154,6 +193,7 @@ func (mc *MemoryCache) evictOldest(needed int64) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cleanup 定期清理过期条目
|
||||||
func (mc *MemoryCache) cleanup() {
|
func (mc *MemoryCache) cleanup() {
|
||||||
ticker := time.NewTicker(10 * time.Minute)
|
ticker := time.NewTicker(10 * time.Minute)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
@@ -165,6 +205,30 @@ func (mc *MemoryCache) cleanup() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stats 返回缓存统计信息
|
||||||
|
func (mc *MemoryCache) Stats() (entries int, size int64) {
|
||||||
|
count := 0
|
||||||
|
mc.entries.Range(func(key, value interface{}) bool {
|
||||||
|
count++
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return count, mc.currentSize
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStats 返回详细的缓存统计信息
|
||||||
|
func (mc *MemoryCache) GetStats() map[string]interface{} {
|
||||||
|
entries, size := mc.Stats()
|
||||||
|
|
||||||
|
return map[string]interface{}{
|
||||||
|
"entries": entries,
|
||||||
|
"size": size,
|
||||||
|
"max_size": mc.maxSize,
|
||||||
|
"utilization": float64(size) / float64(mc.maxSize) * 100,
|
||||||
|
"ttl_seconds": int64(mc.ttl.Seconds()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (mc *MemoryCache) Stats() (entries int, size int64) {
|
func (mc *MemoryCache) Stats() (entries int, size int64) {
|
||||||
count := 0
|
count := 0
|
||||||
mc.entries.Range(func(key, value interface{}) bool {
|
mc.entries.Range(func(key, value interface{}) bool {
|
||||||
|
|||||||
Reference in New Issue
Block a user