Files
unitech-golib/cache/cache.go
2025-07-22 14:08:24 +08:00

123 lines
2.0 KiB
Go

package cache
import (
"errors"
"github.com/MAN00K/unitech_golib/tlog"
"github.com/creachadair/cityhash"
"sync"
"time"
)
//API
var Nil error = errors.New("cache: nil")
func Set(key string, value interface{}) error {
return SetEx(key, value, 86400)
}
func SetEx(key string, value interface{}, exp int) error {
return setEx(key, value, exp)
}
func Get(key string) (interface{}, error) {
return get(key)
}
func Del(key string) error {
return del(key)
}
//internal
var dbs map[byte]*db
type db struct {
m map[string]*item
t time.Duration
sync.RWMutex
}
type item struct {
t int
d interface{}
}
func init() {
if dbs == nil {
dbs = make(map[byte]*db, 256)
for i := 0; i <= 255; i++ {
dbs[byte(i)] = newdb(time.Duration(3600+i) * time.Second)
}
}
}
func newdb(t time.Duration) *db {
ret := &db{
t: t,
m: make(map[string]*item),
}
go ret.flush()
return ret
}
//定期扫描过期的key
func (this *db) flush() {
for range time.NewTicker(this.t).C {
this.doflush()
}
}
func (this *db) doflush() {
start := time.Now()
tt := int(start.Unix())
var i, j int
this.Lock()
for key, item := range this.m {
i++
if item.t != 0 && item.t < tt {
j++
delete(this.m, key)
}
}
this.Unlock()
tlog.Infof("FlushCacheKey||Totoal=%d||Expired=%d||t=%s", i, j, time.Since(start))
}
func setEx(key string, value interface{}, exp int) error {
if exp <= 0 {
return errors.New("args error, expTime must be > 0")
}
db, _ := dbs[hash(key)]
db.Lock()
db.m[key] = &item{
d: value,
t: int(time.Now().Unix()) + exp}
db.Unlock()
return nil
}
func get(key string) (interface{}, error) {
db, _ := dbs[hash(key)]
db.RLock()
item, ok := db.m[key]
db.RUnlock()
if ok {
if item.t >= int(time.Now().Unix()) {
return item.d, nil
}
del(key)
}
return nil, Nil
}
func del(key string) error {
db, _ := dbs[hash(key)]
db.Lock()
delete(db.m, key)
db.Unlock()
return nil
}
func hash(key string) byte {
return byte(cityhash.Hash32([]byte(key)))
}