102 lines
1.9 KiB
Go
102 lines
1.9 KiB
Go
|
package cache
|
||
|
|
||
|
import (
|
||
|
"crypto/sha256"
|
||
|
"encoding/binary"
|
||
|
"sync"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
type cacheData struct {
|
||
|
data any
|
||
|
expireAt time.Time
|
||
|
}
|
||
|
|
||
|
type localCache struct {
|
||
|
locker *sync.RWMutex
|
||
|
repo map[string]*cacheData
|
||
|
}
|
||
|
|
||
|
func newLocalCache() *localCache {
|
||
|
c := &localCache{
|
||
|
locker: new(sync.RWMutex),
|
||
|
repo: make(map[string]*cacheData),
|
||
|
}
|
||
|
|
||
|
return c
|
||
|
}
|
||
|
|
||
|
func (c *localCache) startBgCheckWorker() {
|
||
|
ticker := time.NewTicker(time.Second * 10)
|
||
|
for {
|
||
|
select {
|
||
|
case <-ticker.C:
|
||
|
timeNow := time.Now()
|
||
|
c.locker.Lock()
|
||
|
for k, v := range c.repo {
|
||
|
if v.expireAt.Before(timeNow) {
|
||
|
delete(c.repo, k)
|
||
|
}
|
||
|
}
|
||
|
c.locker.Unlock()
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (c *localCache) get(key string) (any, bool) {
|
||
|
c.locker.RLocker()
|
||
|
defer c.locker.RUnlock()
|
||
|
v, find := c.repo[key]
|
||
|
if find {
|
||
|
if v.expireAt.Before(time.Now()) {
|
||
|
return nil, false
|
||
|
}
|
||
|
return v.data, true
|
||
|
}
|
||
|
return nil, false
|
||
|
}
|
||
|
|
||
|
func (c *localCache) set(key string, value any, dura time.Duration) {
|
||
|
c.locker.Lock()
|
||
|
defer c.locker.Unlock()
|
||
|
c.repo[key] = &cacheData{
|
||
|
data: value,
|
||
|
expireAt: time.Now().Add(dura),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type LocalCache struct {
|
||
|
repoList [10]*localCache
|
||
|
}
|
||
|
|
||
|
func NewLocalCache() *LocalCache {
|
||
|
c := &LocalCache{}
|
||
|
for i := 0; i < len(c.repoList); i++ {
|
||
|
c.repoList[i] = newLocalCache()
|
||
|
}
|
||
|
return c
|
||
|
}
|
||
|
|
||
|
func (c *LocalCache) Get(key string) (any, bool) {
|
||
|
return c.getHashRepo(key).get(key)
|
||
|
}
|
||
|
|
||
|
func (c *LocalCache) Set(key string, value any, dura time.Duration) {
|
||
|
c.getHashRepo(key).set(key, value, dura)
|
||
|
}
|
||
|
|
||
|
func (c *LocalCache) getHashRepo(key string) *localCache {
|
||
|
return c.repoList[fastHashMod(key, len(c.repoList))]
|
||
|
}
|
||
|
|
||
|
func fastHashMod(key string, mod int) int {
|
||
|
// 使用前64位哈希值
|
||
|
hasher := sha256.New()
|
||
|
hasher.Write([]byte(key))
|
||
|
hashBytes := hasher.Sum(nil)
|
||
|
|
||
|
// 取前8字节转换为uint64
|
||
|
hashUint64 := binary.BigEndian.Uint64(hashBytes[:8])
|
||
|
return int(hashUint64 % uint64(mod))
|
||
|
}
|