- 在 HoTimeCache 中新增 SessionsGet、SessionsSet 和 SessionsDelete 方法,支持批量获取、设置和删除 Session 缓存 - 优化缓存逻辑,减少数据库写入次数,提升性能 - 更新文档,详细说明批量操作的使用方法和性能对比 - 添加调试日志记录,便于追踪批量操作的执行情况
155 lines
3.0 KiB
Go
155 lines
3.0 KiB
Go
package cache
|
||
|
||
import (
|
||
. "code.hoteas.com/golang/hotime/common"
|
||
"strings"
|
||
"sync"
|
||
"time"
|
||
)
|
||
|
||
// CacheMemory 基于 sync.Map 的缓存实现
|
||
type CacheMemory struct {
|
||
TimeOut int64
|
||
DbSet bool
|
||
SessionSet bool
|
||
*Error
|
||
cache sync.Map // 替代传统的 Map
|
||
}
|
||
|
||
func (that *CacheMemory) GetError() *Error {
|
||
|
||
return that.Error
|
||
|
||
}
|
||
|
||
func (that *CacheMemory) SetError(err *Error) {
|
||
that.Error = err
|
||
}
|
||
func (c *CacheMemory) get(key string) (res *Obj) {
|
||
|
||
res = &Obj{
|
||
Error: *c.Error,
|
||
}
|
||
value, ok := c.cache.Load(key)
|
||
if !ok {
|
||
return res // 缓存不存在
|
||
}
|
||
|
||
data := value.(cacheData)
|
||
|
||
// 检查是否过期
|
||
if data.time < time.Now().Unix() {
|
||
c.cache.Delete(key) // 删除过期缓存
|
||
return res
|
||
}
|
||
res.Data = data.data
|
||
return res
|
||
}
|
||
func (c *CacheMemory) set(key string, value interface{}, expireAt int64) {
|
||
data := cacheData{
|
||
data: value,
|
||
time: expireAt,
|
||
}
|
||
c.cache.Store(key, data)
|
||
}
|
||
func (c *CacheMemory) delete(key string) {
|
||
if strings.Contains(key, "*") {
|
||
// 通配符删除
|
||
prefix := strings.TrimSuffix(key, "*")
|
||
c.cache.Range(func(k, v interface{}) bool {
|
||
if strings.HasPrefix(k.(string), prefix) {
|
||
c.cache.Delete(k)
|
||
}
|
||
return true
|
||
})
|
||
} else {
|
||
// 精确删除
|
||
c.cache.Delete(key)
|
||
}
|
||
}
|
||
func (c *CacheMemory) refreshMap() {
|
||
go func() {
|
||
now := time.Now().Unix()
|
||
c.cache.Range(func(key, value interface{}) bool {
|
||
data := value.(cacheData)
|
||
if data.time <= now {
|
||
c.cache.Delete(key) // 删除过期缓存
|
||
}
|
||
return true
|
||
})
|
||
}()
|
||
}
|
||
func (c *CacheMemory) Cache(key string, data ...interface{}) *Obj {
|
||
now := time.Now().Unix()
|
||
|
||
// 随机触发刷新
|
||
if x := RandX(1, 100000); x > 99950 {
|
||
c.refreshMap()
|
||
}
|
||
|
||
if len(data) == 0 {
|
||
// 读操作
|
||
return c.get(key)
|
||
}
|
||
|
||
if len(data) == 1 && data[0] == nil {
|
||
// 删除操作
|
||
c.delete(key)
|
||
return nil
|
||
}
|
||
|
||
// 写操作
|
||
expireAt := now + c.TimeOut
|
||
if len(data) == 2 {
|
||
if customExpire, ok := data[1].(int64); ok {
|
||
if customExpire > now {
|
||
expireAt = customExpire
|
||
} else {
|
||
expireAt = now + customExpire
|
||
}
|
||
}
|
||
}
|
||
|
||
c.set(key, data[0], expireAt)
|
||
return nil
|
||
}
|
||
|
||
// CachesGet 批量获取缓存
|
||
// 返回 Map,key 为缓存键,value 为缓存值(不存在或过期的 key 不包含在结果中)
|
||
func (c *CacheMemory) CachesGet(keys []string) Map {
|
||
result := make(Map, len(keys))
|
||
for _, key := range keys {
|
||
obj := c.get(key)
|
||
if obj != nil && obj.Data != nil {
|
||
result[key] = obj.Data
|
||
}
|
||
}
|
||
return result
|
||
}
|
||
|
||
// CachesSet 批量设置缓存
|
||
// data: Map,key 为缓存键,value 为缓存值
|
||
// timeout: 可选过期时间(秒),不传则使用默认超时时间
|
||
func (c *CacheMemory) CachesSet(data Map, timeout ...int64) {
|
||
now := time.Now().Unix()
|
||
expireAt := now + c.TimeOut
|
||
if len(timeout) > 0 && timeout[0] > 0 {
|
||
if timeout[0] > now {
|
||
expireAt = timeout[0]
|
||
} else {
|
||
expireAt = now + timeout[0]
|
||
}
|
||
}
|
||
|
||
for key, value := range data {
|
||
c.set(key, value, expireAt)
|
||
}
|
||
}
|
||
|
||
// CachesDelete 批量删除缓存
|
||
func (c *CacheMemory) CachesDelete(keys []string) {
|
||
for _, key := range keys {
|
||
c.delete(key)
|
||
}
|
||
}
|