123 lines
2.0 KiB
Go
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)))
|
|
}
|