feat: backend core - auth, user, role, permission, device, webhook, monitoring, cache, repository, service, middleware, API handlers
This commit is contained in:
171
internal/cache/l1.go
vendored
Normal file
171
internal/cache/l1.go
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// maxItems 是L1Cache的最大条目数
|
||||
// 超过此限制后将淘汰最久未使用的条目
|
||||
maxItems = 10000
|
||||
)
|
||||
|
||||
// CacheItem 缓存项
|
||||
type CacheItem struct {
|
||||
Value interface{}
|
||||
Expiration int64
|
||||
}
|
||||
|
||||
// Expired 判断缓存项是否过期
|
||||
func (item *CacheItem) Expired() bool {
|
||||
return item.Expiration > 0 && time.Now().UnixNano() > item.Expiration
|
||||
}
|
||||
|
||||
// L1Cache L1本地缓存(支持LRU淘汰策略)
|
||||
type L1Cache struct {
|
||||
items map[string]*CacheItem
|
||||
mu sync.RWMutex
|
||||
// accessOrder 记录key的访问顺序,用于LRU淘汰
|
||||
// 第一个是最久未使用的,最后一个是最近使用的
|
||||
accessOrder []string
|
||||
}
|
||||
|
||||
// NewL1Cache 创建L1缓存
|
||||
func NewL1Cache() *L1Cache {
|
||||
return &L1Cache{
|
||||
items: make(map[string]*CacheItem),
|
||||
}
|
||||
}
|
||||
|
||||
// Set 设置缓存
|
||||
func (c *L1Cache) Set(key string, value interface{}, ttl time.Duration) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
var expiration int64
|
||||
if ttl > 0 {
|
||||
expiration = time.Now().Add(ttl).UnixNano()
|
||||
}
|
||||
|
||||
// 如果key已存在,更新访问顺序
|
||||
if _, exists := c.items[key]; exists {
|
||||
c.items[key] = &CacheItem{
|
||||
Value: value,
|
||||
Expiration: expiration,
|
||||
}
|
||||
c.updateAccessOrder(key)
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否超过最大容量,进行LRU淘汰
|
||||
if len(c.items) >= maxItems {
|
||||
c.evictLRU()
|
||||
}
|
||||
|
||||
c.items[key] = &CacheItem{
|
||||
Value: value,
|
||||
Expiration: expiration,
|
||||
}
|
||||
c.accessOrder = append(c.accessOrder, key)
|
||||
}
|
||||
|
||||
// evictLRU 淘汰最久未使用的条目
|
||||
func (c *L1Cache) evictLRU() {
|
||||
if len(c.accessOrder) == 0 {
|
||||
return
|
||||
}
|
||||
// 淘汰最久未使用的(第一个)
|
||||
oldest := c.accessOrder[0]
|
||||
delete(c.items, oldest)
|
||||
c.accessOrder = c.accessOrder[1:]
|
||||
}
|
||||
|
||||
// removeFromAccessOrder 从访问顺序中移除key
|
||||
func (c *L1Cache) removeFromAccessOrder(key string) {
|
||||
for i, k := range c.accessOrder {
|
||||
if k == key {
|
||||
c.accessOrder = append(c.accessOrder[:i], c.accessOrder[i+1:]...)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// updateAccessOrder 更新访问顺序,将key移到最后(最近使用)
|
||||
func (c *L1Cache) updateAccessOrder(key string) {
|
||||
for i, k := range c.accessOrder {
|
||||
if k == key {
|
||||
// 移除当前位置
|
||||
c.accessOrder = append(c.accessOrder[:i], c.accessOrder[i+1:]...)
|
||||
// 添加到末尾
|
||||
c.accessOrder = append(c.accessOrder, key)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get 获取缓存
|
||||
func (c *L1Cache) Get(key string) (interface{}, bool) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
item, ok := c.items[key]
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if item.Expired() {
|
||||
delete(c.items, key)
|
||||
c.removeFromAccessOrder(key)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// 更新访问顺序
|
||||
c.updateAccessOrder(key)
|
||||
|
||||
return item.Value, true
|
||||
}
|
||||
|
||||
// Delete 删除缓存
|
||||
func (c *L1Cache) Delete(key string) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
delete(c.items, key)
|
||||
c.removeFromAccessOrder(key)
|
||||
}
|
||||
|
||||
// Clear 清空缓存
|
||||
func (c *L1Cache) Clear() {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
c.items = make(map[string]*CacheItem)
|
||||
c.accessOrder = make([]string, 0)
|
||||
}
|
||||
|
||||
// Size 获取缓存大小
|
||||
func (c *L1Cache) Size() int {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
|
||||
return len(c.items)
|
||||
}
|
||||
|
||||
// Cleanup 清理过期缓存
|
||||
func (c *L1Cache) Cleanup() {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
now := time.Now().UnixNano()
|
||||
keysToDelete := make([]string, 0)
|
||||
for key, item := range c.items {
|
||||
if item.Expiration > 0 && now > item.Expiration {
|
||||
keysToDelete = append(keysToDelete, key)
|
||||
}
|
||||
}
|
||||
for _, key := range keysToDelete {
|
||||
delete(c.items, key)
|
||||
c.removeFromAccessOrder(key)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user