Initial commit
This commit is contained in:
108
lrucache/lrucache.go
Normal file
108
lrucache/lrucache.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package lrucache
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/creachadair/cityhash"
|
||||
"github.com/hashicorp/golang-lru"
|
||||
"globalfintech/golib/tlog"
|
||||
"time"
|
||||
)
|
||||
|
||||
// API
|
||||
var (
|
||||
Nil error = errors.New("cache: nil")
|
||||
ErrExpTime error = errors.New("args error, expTime must be > 0")
|
||||
dbs map[int]*lru.Cache
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
func init() {
|
||||
if dbs == nil {
|
||||
dbs = make(map[int]*lru.Cache, 1024)
|
||||
for i := 0; i < 1024; i++ {
|
||||
dbs[i], _ = lru.New(3000)
|
||||
}
|
||||
}
|
||||
go flush()
|
||||
}
|
||||
|
||||
func flush() {
|
||||
i := 0
|
||||
for range time.NewTicker(time.Minute).C {
|
||||
start := time.Now()
|
||||
shard := i % 1024
|
||||
db, _ := dbs[shard]
|
||||
keys := db.Keys()
|
||||
for _, key := range keys {
|
||||
if keyS, ok := key.(string); ok {
|
||||
getByDb(keyS, db)
|
||||
}
|
||||
}
|
||||
i++
|
||||
tlog.Infof("FlushKey||time=%s||shard=%d||old=%d||new=%d", time.Since(start), shard, len(keys), db.Len())
|
||||
}
|
||||
}
|
||||
|
||||
type item struct {
|
||||
d interface{}
|
||||
t int
|
||||
}
|
||||
|
||||
func setEx(key string, value interface{}, exp int) error {
|
||||
if exp < 1 {
|
||||
return ErrExpTime
|
||||
}
|
||||
|
||||
db, _ := dbs[hash(key)]
|
||||
db.Add(key, &item{d: value, t: int(time.Now().Unix()) + exp})
|
||||
return nil
|
||||
}
|
||||
|
||||
func get(key string) (interface{}, error) {
|
||||
db, _ := dbs[hash(key)]
|
||||
return getByDb(key, db)
|
||||
}
|
||||
|
||||
func getByDb(key string, db *lru.Cache) (interface{}, error) {
|
||||
if value, ok := db.Get(key); ok {
|
||||
if item, ok := value.(*item); ok {
|
||||
if item.t >= int(time.Now().Unix()) {
|
||||
return item.d, nil
|
||||
} else {
|
||||
delByDb(key, db)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, Nil
|
||||
}
|
||||
|
||||
func del(key string) error {
|
||||
db, _ := dbs[hash(key)]
|
||||
return delByDb(key, db)
|
||||
}
|
||||
|
||||
func delByDb(key string, db *lru.Cache) error {
|
||||
db.Remove(key)
|
||||
return nil
|
||||
}
|
||||
|
||||
func hash(key string) int {
|
||||
return int(cityhash.Hash32([]byte(key)) % 1024)
|
||||
}
|
||||
Reference in New Issue
Block a user