2019-02-02 16:18:25 +08:00
|
|
|
|
// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
2018-09-15 16:40:13 +08:00
|
|
|
|
//
|
|
|
|
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
|
|
|
|
// If a copy of the MIT was not distributed with this file,
|
2019-02-02 16:18:25 +08:00
|
|
|
|
// You can obtain one at https://github.com/gogf/gf.
|
2018-09-15 16:40:13 +08:00
|
|
|
|
|
|
|
|
|
|
package gcache
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2019-02-02 16:18:25 +08:00
|
|
|
|
"github.com/gogf/gf/g/container/glist"
|
|
|
|
|
|
"github.com/gogf/gf/g/container/gset"
|
|
|
|
|
|
"github.com/gogf/gf/g/container/gtype"
|
|
|
|
|
|
"github.com/gogf/gf/g/os/gtime"
|
|
|
|
|
|
"github.com/gogf/gf/g/os/gtimer"
|
|
|
|
|
|
"github.com/gogf/gf/g/util/gconv"
|
2018-12-04 19:26:46 +08:00
|
|
|
|
"math"
|
|
|
|
|
|
"sync"
|
2018-09-15 16:40:13 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
2018-12-04 19:26:46 +08:00
|
|
|
|
|
2018-09-15 16:40:13 +08:00
|
|
|
|
// 缓存对象
|
|
|
|
|
|
type memCache struct {
|
2018-12-04 19:26:46 +08:00
|
|
|
|
dataMu sync.RWMutex
|
|
|
|
|
|
expireTimeMu sync.RWMutex
|
|
|
|
|
|
expireSetMu sync.RWMutex
|
|
|
|
|
|
|
|
|
|
|
|
cap int // 控制缓存池大小,超过大小则按照LRU算法进行缓存过期处理(默认为0表示不进行限制)
|
|
|
|
|
|
data map[interface{}]memCacheItem // 缓存数据(所有的缓存数据存放哈希表)
|
2018-12-30 14:53:16 +08:00
|
|
|
|
expireTimes map[interface{}]int64 // 键名对应的分组过期时间(用于相同键名过期时间快速更新),键值为1秒级时间戳
|
|
|
|
|
|
expireSets map[int64]*gset.Set // 分组过期时间对应的键名列表(用于自动过期快速删除),键值为1秒级时间戳
|
2018-12-04 19:26:46 +08:00
|
|
|
|
|
|
|
|
|
|
lru *memCacheLru // LRU缓存限制(只有限定cap池大小时才启用)
|
|
|
|
|
|
lruGetList *glist.List // Get操作的LRU记录
|
|
|
|
|
|
eventList *glist.List // 异步处理队列
|
|
|
|
|
|
closed *gtype.Bool // 关闭事件通知
|
2018-09-15 16:40:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 缓存数据项
|
|
|
|
|
|
type memCacheItem struct {
|
2018-12-04 19:26:46 +08:00
|
|
|
|
v interface{} // 键值
|
2018-09-15 16:40:13 +08:00
|
|
|
|
e int64 // 过期时间
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 异步队列数据项
|
|
|
|
|
|
type memCacheEvent struct {
|
2018-09-19 15:08:33 +08:00
|
|
|
|
k interface{} // 键名
|
|
|
|
|
|
e int64 // 过期时间
|
2018-09-15 16:40:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-12-04 19:26:46 +08:00
|
|
|
|
const (
|
|
|
|
|
|
// 当数据不过期时,默认设置的过期属性值,相当于:math.MaxInt64/1000000
|
|
|
|
|
|
gDEFAULT_MAX_EXPIRE = 9223372036854
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2018-09-15 16:40:13 +08:00
|
|
|
|
// 创建底层的缓存对象
|
2018-09-18 00:01:10 +08:00
|
|
|
|
func newMemCache(lruCap...int) *memCache {
|
2018-09-15 16:40:13 +08:00
|
|
|
|
c := &memCache {
|
2018-12-04 19:26:46 +08:00
|
|
|
|
lruGetList : glist.New(),
|
|
|
|
|
|
data : make(map[interface{}]memCacheItem),
|
|
|
|
|
|
expireTimes : make(map[interface{}]int64),
|
|
|
|
|
|
expireSets : make(map[int64]*gset.Set),
|
|
|
|
|
|
eventList : glist.New(),
|
|
|
|
|
|
closed : gtype.NewBool(),
|
2018-09-18 00:01:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
if len(lruCap) > 0 {
|
2018-12-04 19:26:46 +08:00
|
|
|
|
c.cap = lruCap[0]
|
2018-12-17 18:35:29 +08:00
|
|
|
|
c.lru = newMemCacheLru(c)
|
2018-09-15 16:40:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
return c
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-12-30 14:53:16 +08:00
|
|
|
|
// 计算过期缓存的键名(将毫秒换算成秒的整数毫秒,按照1秒进行分组)
|
2018-09-15 16:40:13 +08:00
|
|
|
|
func (c *memCache) makeExpireKey(expire int64) int64 {
|
2018-12-30 14:53:16 +08:00
|
|
|
|
return int64(math.Ceil(float64(expire/1000) + 1)*1000)
|
2018-09-15 16:40:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-12-30 14:53:16 +08:00
|
|
|
|
// 获取一个过期键名存放Set, 如果没有则返回nil
|
2018-12-04 19:26:46 +08:00
|
|
|
|
func (c *memCache) getExpireSet(expire int64) (expireSet *gset.Set) {
|
|
|
|
|
|
c.expireSetMu.RLock()
|
|
|
|
|
|
expireSet, _ = c.expireSets[expire]
|
|
|
|
|
|
c.expireSetMu.RUnlock()
|
2018-12-30 14:53:16 +08:00
|
|
|
|
return
|
2018-09-15 16:40:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取或者创建一个过期键名存放Set(由于是异步单线程执行,因此不会出现创建set时的覆盖问题)
|
2018-12-04 19:26:46 +08:00
|
|
|
|
func (c *memCache) getOrNewExpireSet(expire int64) (expireSet *gset.Set) {
|
|
|
|
|
|
if expireSet = c.getExpireSet(expire); expireSet == nil {
|
|
|
|
|
|
expireSet = gset.New()
|
|
|
|
|
|
c.expireSetMu.Lock()
|
|
|
|
|
|
// 写锁二次检索确认
|
|
|
|
|
|
if es, ok := c.expireSets[expire]; ok {
|
|
|
|
|
|
expireSet = es
|
2018-09-17 18:43:59 +08:00
|
|
|
|
} else {
|
2018-12-04 19:26:46 +08:00
|
|
|
|
c.expireSets[expire] = expireSet
|
2018-09-17 18:43:59 +08:00
|
|
|
|
}
|
2018-12-04 19:26:46 +08:00
|
|
|
|
c.expireSetMu.Unlock()
|
2018-09-15 16:40:13 +08:00
|
|
|
|
}
|
2018-12-04 19:26:46 +08:00
|
|
|
|
return
|
2018-09-15 16:40:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 设置kv缓存键值对,过期时间单位为毫秒,expire<=0表示不过期
|
|
|
|
|
|
func (c *memCache) Set(key interface{}, value interface{}, expire int) {
|
2018-12-04 19:26:46 +08:00
|
|
|
|
expireTime := c.getInternalExpire(expire)
|
|
|
|
|
|
c.dataMu.Lock()
|
|
|
|
|
|
c.data[key] = memCacheItem{v : value, e : expireTime}
|
|
|
|
|
|
c.dataMu.Unlock()
|
|
|
|
|
|
c.eventList.PushBack(&memCacheEvent{k : key, e : expireTime})
|
2018-09-18 00:01:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 设置kv缓存键值对,内部会对键名的存在性使用写锁进行二次检索确认,如果存在则不再写入;返回键名对应的键值。
|
|
|
|
|
|
// 在高并发下有用,防止数据写入的并发逻辑错误。
|
|
|
|
|
|
func (c *memCache) doSetWithLockCheck(key interface{}, value interface{}, expire int) interface{} {
|
|
|
|
|
|
expireTimestamp := c.getInternalExpire(expire)
|
2018-12-04 19:26:46 +08:00
|
|
|
|
c.dataMu.Lock()
|
2018-09-18 00:01:10 +08:00
|
|
|
|
if v, ok := c.data[key]; ok && !v.IsExpired() {
|
2018-12-04 19:26:46 +08:00
|
|
|
|
c.dataMu.Unlock()
|
2018-12-14 18:38:29 +08:00
|
|
|
|
return v.v
|
2018-09-18 00:01:10 +08:00
|
|
|
|
}
|
2018-09-19 15:08:33 +08:00
|
|
|
|
if f, ok := value.(func() interface {}); ok {
|
|
|
|
|
|
value = f()
|
|
|
|
|
|
}
|
2019-03-21 18:20:20 +08:00
|
|
|
|
if value == nil {
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
2018-09-18 00:01:10 +08:00
|
|
|
|
c.data[key] = memCacheItem{v : value, e : expireTimestamp}
|
2018-12-04 19:26:46 +08:00
|
|
|
|
c.dataMu.Unlock()
|
|
|
|
|
|
c.eventList.PushBack(&memCacheEvent{k : key, e : expireTimestamp})
|
2018-09-18 00:01:10 +08:00
|
|
|
|
return value
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 根据给定expire参数计算内部使用的expire过期时间
|
|
|
|
|
|
func (c *memCache) getInternalExpire(expire int) int64 {
|
2018-09-15 16:40:13 +08:00
|
|
|
|
if expire != 0 {
|
2018-09-18 00:01:10 +08:00
|
|
|
|
return gtime.Millisecond() + int64(expire)
|
2018-09-15 16:40:13 +08:00
|
|
|
|
} else {
|
2018-09-18 00:01:10 +08:00
|
|
|
|
return gDEFAULT_MAX_EXPIRE
|
2018-09-15 16:40:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 当键名不存在时写入,并返回true;否则返回false。
|
|
|
|
|
|
func (c *memCache) SetIfNotExist(key interface{}, value interface{}, expire int) bool {
|
|
|
|
|
|
if !c.Contains(key) {
|
2018-09-18 00:01:10 +08:00
|
|
|
|
c.doSetWithLockCheck(key, value, expire)
|
2018-09-15 16:40:13 +08:00
|
|
|
|
return true
|
|
|
|
|
|
}
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 批量设置
|
2019-05-08 17:21:18 +08:00
|
|
|
|
func (c *memCache) Sets(data map[interface{}]interface{}, expire int) {
|
2018-12-04 19:26:46 +08:00
|
|
|
|
expireTime := c.getInternalExpire(expire)
|
2018-09-15 16:40:13 +08:00
|
|
|
|
for k, v := range data {
|
2018-12-04 19:26:46 +08:00
|
|
|
|
c.dataMu.Lock()
|
|
|
|
|
|
c.data[k] = memCacheItem{v: v, e: expireTime}
|
|
|
|
|
|
c.dataMu.Unlock()
|
|
|
|
|
|
c.eventList.PushBack(&memCacheEvent{k: k, e: expireTime})
|
2018-09-15 16:40:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取指定键名的值
|
|
|
|
|
|
func (c *memCache) Get(key interface{}) interface{} {
|
2018-12-04 19:26:46 +08:00
|
|
|
|
c.dataMu.RLock()
|
2018-09-15 16:40:13 +08:00
|
|
|
|
item, ok := c.data[key]
|
2018-12-04 19:26:46 +08:00
|
|
|
|
c.dataMu.RUnlock()
|
2018-09-15 16:40:13 +08:00
|
|
|
|
if ok && !item.IsExpired() {
|
2018-12-04 19:26:46 +08:00
|
|
|
|
// 增加LRU(Least Recently Used)操作记录
|
2018-09-18 00:01:10 +08:00
|
|
|
|
if c.cap > 0 {
|
2018-09-19 09:47:50 +08:00
|
|
|
|
c.lruGetList.PushBack(key)
|
2018-09-17 18:43:59 +08:00
|
|
|
|
}
|
2018-09-15 16:40:13 +08:00
|
|
|
|
return item.v
|
|
|
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 当键名存在时返回其键值,否则写入指定的键值
|
|
|
|
|
|
func (c *memCache) GetOrSet(key interface{}, value interface{}, expire int) interface{} {
|
|
|
|
|
|
if v := c.Get(key); v == nil {
|
2018-09-18 00:01:10 +08:00
|
|
|
|
return c.doSetWithLockCheck(key, value, expire)
|
2018-09-15 16:40:13 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
return v
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 当键名存在时返回其键值,否则写入指定的键值,键值由指定的函数生成
|
|
|
|
|
|
func (c *memCache) GetOrSetFunc(key interface{}, f func() interface{}, expire int) interface{} {
|
|
|
|
|
|
if v := c.Get(key); v == nil {
|
2018-09-18 00:01:10 +08:00
|
|
|
|
// 可能存在多个goroutine被阻塞在这里,f可能是并发运行
|
2018-11-16 18:20:09 +08:00
|
|
|
|
return c.doSetWithLockCheck(key, f(), expire)
|
2018-09-15 16:40:13 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
return v
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-09-19 15:08:33 +08:00
|
|
|
|
// 与GetOrSetFunc不同的是,f是在写锁机制内执行
|
|
|
|
|
|
func (c *memCache) GetOrSetFuncLock(key interface{}, f func() interface{}, expire int) interface{} {
|
|
|
|
|
|
if v := c.Get(key); v == nil {
|
2018-11-16 18:20:09 +08:00
|
|
|
|
return c.doSetWithLockCheck(key, f, expire)
|
2018-09-19 15:08:33 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
return v
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-09-15 16:40:13 +08:00
|
|
|
|
// 是否存在指定的键名,true表示存在,false表示不存在。
|
|
|
|
|
|
func (c *memCache) Contains(key interface{}) bool {
|
|
|
|
|
|
return c.Get(key) != nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-09-17 09:52:24 +08:00
|
|
|
|
// 删除指定键值对,并返回被删除的键值
|
2018-12-04 19:26:46 +08:00
|
|
|
|
func (c *memCache) Remove(key interface{}) (value interface{}) {
|
|
|
|
|
|
c.dataMu.RLock()
|
2018-09-17 09:52:24 +08:00
|
|
|
|
item, ok := c.data[key]
|
2018-12-04 19:26:46 +08:00
|
|
|
|
c.dataMu.RUnlock()
|
2018-09-17 09:52:24 +08:00
|
|
|
|
if ok {
|
2018-12-04 19:26:46 +08:00
|
|
|
|
value = item.v
|
|
|
|
|
|
c.dataMu.Lock()
|
2018-09-17 09:52:24 +08:00
|
|
|
|
delete(c.data, key)
|
2018-12-04 19:26:46 +08:00
|
|
|
|
c.dataMu.Unlock()
|
|
|
|
|
|
c.eventList.PushBack(&memCacheEvent{k: key, e: gtime.Millisecond() - 1000})
|
2018-09-17 09:52:24 +08:00
|
|
|
|
}
|
2018-12-04 19:26:46 +08:00
|
|
|
|
return
|
2018-09-15 16:40:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-09-17 09:52:24 +08:00
|
|
|
|
// 批量删除键值对,并返回被删除的键值对数据
|
2019-05-08 17:21:18 +08:00
|
|
|
|
func (c *memCache) Removes(keys []interface{}) {
|
2018-09-15 16:40:13 +08:00
|
|
|
|
for _, key := range keys {
|
2018-12-04 19:26:46 +08:00
|
|
|
|
c.Remove(key)
|
2018-09-15 16:40:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-12-04 20:23:48 +08:00
|
|
|
|
// 返回缓存的所有数据键值对(不包含已过期数据)
|
|
|
|
|
|
func (c *memCache) Data() map[interface{}]interface{} {
|
|
|
|
|
|
m := make(map[interface{}]interface{})
|
|
|
|
|
|
c.dataMu.RLock()
|
|
|
|
|
|
for k, v := range c.data {
|
|
|
|
|
|
if !v.IsExpired() {
|
|
|
|
|
|
m[k] = v.v
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
c.dataMu.RUnlock()
|
|
|
|
|
|
return m
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-09-15 16:40:13 +08:00
|
|
|
|
// 获得所有的键名,组成数组返回
|
|
|
|
|
|
func (c *memCache) Keys() []interface{} {
|
|
|
|
|
|
keys := make([]interface{}, 0)
|
2018-12-04 19:26:46 +08:00
|
|
|
|
c.dataMu.RLock()
|
2018-09-15 16:40:13 +08:00
|
|
|
|
for k, v := range c.data {
|
|
|
|
|
|
if !v.IsExpired() {
|
|
|
|
|
|
keys = append(keys, k)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2018-12-04 19:26:46 +08:00
|
|
|
|
c.dataMu.RUnlock()
|
2018-09-15 16:40:13 +08:00
|
|
|
|
return keys
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获得所有的键名,组成字符串数组返回
|
|
|
|
|
|
func (c *memCache) KeyStrings() []string {
|
|
|
|
|
|
return gconv.Strings(c.Keys())
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获得所有的值,组成数组返回
|
|
|
|
|
|
func (c *memCache) Values() []interface{} {
|
|
|
|
|
|
values := make([]interface{}, 0)
|
2018-12-04 19:26:46 +08:00
|
|
|
|
c.dataMu.RLock()
|
2018-09-15 16:40:13 +08:00
|
|
|
|
for _, v := range c.data {
|
|
|
|
|
|
if !v.IsExpired() {
|
|
|
|
|
|
values = append(values, v.v)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2018-12-04 19:26:46 +08:00
|
|
|
|
c.dataMu.RUnlock()
|
2018-09-15 16:40:13 +08:00
|
|
|
|
return values
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获得缓存对象的键值对数量
|
2018-12-04 19:26:46 +08:00
|
|
|
|
func (c *memCache) Size() (size int) {
|
|
|
|
|
|
c.dataMu.RLock()
|
|
|
|
|
|
size = len(c.data)
|
|
|
|
|
|
c.dataMu.RUnlock()
|
|
|
|
|
|
return
|
2018-09-15 16:40:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 删除缓存对象
|
|
|
|
|
|
func (c *memCache) Close() {
|
2018-12-04 19:50:24 +08:00
|
|
|
|
if c.cap > 0 {
|
|
|
|
|
|
c.lru.Close()
|
|
|
|
|
|
}
|
2018-12-04 19:26:46 +08:00
|
|
|
|
c.closed.Set(true)
|
2018-09-15 16:40:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-12-04 19:26:46 +08:00
|
|
|
|
// 数据异步任务循环:
|
|
|
|
|
|
// 1、将事件列表中的数据异步处理,并同步结果到expireTimes和expireSets属性中;
|
|
|
|
|
|
// 2、清理过期键值对数据;
|
2018-12-30 14:53:16 +08:00
|
|
|
|
func (c *memCache) syncEventAndClearExpired() {
|
2018-12-04 19:26:46 +08:00
|
|
|
|
event := (*memCacheEvent)(nil)
|
|
|
|
|
|
oldExpireTime := int64(0)
|
|
|
|
|
|
newExpireTime := int64(0)
|
2018-12-30 14:53:16 +08:00
|
|
|
|
if c.closed.Val() {
|
2019-01-12 22:41:12 +08:00
|
|
|
|
gtimer.Exit()
|
2018-12-30 14:53:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
// ========================
|
|
|
|
|
|
// 数据同步处理
|
|
|
|
|
|
// ========================
|
2018-09-15 16:40:13 +08:00
|
|
|
|
for {
|
2018-12-30 14:53:16 +08:00
|
|
|
|
v := c.eventList.PopFront()
|
|
|
|
|
|
if v == nil {
|
|
|
|
|
|
break
|
2018-12-04 19:26:46 +08:00
|
|
|
|
}
|
2018-12-30 14:53:16 +08:00
|
|
|
|
event = v.(*memCacheEvent)
|
|
|
|
|
|
// 获得旧的过期时间分组
|
|
|
|
|
|
c.expireTimeMu.RLock()
|
|
|
|
|
|
oldExpireTime = c.expireTimes[event.k]
|
|
|
|
|
|
c.expireTimeMu.RUnlock()
|
|
|
|
|
|
// 计算新的过期时间分组
|
|
|
|
|
|
newExpireTime = c.makeExpireKey(event.e)
|
|
|
|
|
|
if newExpireTime != oldExpireTime {
|
|
|
|
|
|
c.getOrNewExpireSet(newExpireTime).Add(event.k)
|
|
|
|
|
|
if oldExpireTime != 0 {
|
|
|
|
|
|
c.getOrNewExpireSet(oldExpireTime).Remove(event.k)
|
2018-12-04 19:26:46 +08:00
|
|
|
|
}
|
2018-12-30 14:53:16 +08:00
|
|
|
|
// 重新设置对应键名的过期时间
|
|
|
|
|
|
c.expireTimeMu.Lock()
|
|
|
|
|
|
c.expireTimes[event.k] = newExpireTime
|
|
|
|
|
|
c.expireTimeMu.Unlock()
|
2018-12-04 19:26:46 +08:00
|
|
|
|
}
|
2018-12-30 14:53:16 +08:00
|
|
|
|
// 写入操作也会增加到LRU(Least Recently Used)操作记录
|
|
|
|
|
|
if c.cap > 0 {
|
|
|
|
|
|
c.lru.Push(event.k)
|
2018-12-04 19:26:46 +08:00
|
|
|
|
}
|
2018-12-30 14:53:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
// 异步处理读取操作的LRU列表
|
|
|
|
|
|
if c.cap > 0 && c.lruGetList.Len() > 0 {
|
|
|
|
|
|
for {
|
|
|
|
|
|
if v := c.lruGetList.PopFront(); v != nil {
|
|
|
|
|
|
c.lru.Push(v)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
break
|
2018-12-04 19:26:46 +08:00
|
|
|
|
}
|
2018-09-19 09:47:50 +08:00
|
|
|
|
}
|
2018-12-30 14:53:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
// ========================
|
|
|
|
|
|
// 缓存过期处理
|
|
|
|
|
|
// ========================
|
|
|
|
|
|
ek := c.makeExpireKey(gtime.Millisecond())
|
|
|
|
|
|
eks := []int64{ek - 1000, ek - 2000, ek - 3000, ek - 4000, ek - 5000}
|
|
|
|
|
|
for _, expireTime := range eks {
|
|
|
|
|
|
if expireSet := c.getExpireSet(expireTime); expireSet != nil {
|
|
|
|
|
|
// 遍历Set,执行数据过期删除
|
|
|
|
|
|
expireSet.Iterator(func(key interface{}) bool {
|
2018-12-30 18:56:21 +08:00
|
|
|
|
c.clearByKey(key)
|
|
|
|
|
|
return true
|
2018-12-30 14:53:16 +08:00
|
|
|
|
})
|
|
|
|
|
|
// Set数据处理完之后删除该Set
|
|
|
|
|
|
c.expireSetMu.Lock()
|
|
|
|
|
|
delete(c.expireSets, expireTime)
|
|
|
|
|
|
c.expireSetMu.Unlock()
|
|
|
|
|
|
}
|
2018-12-04 19:26:46 +08:00
|
|
|
|
}
|
2018-09-18 00:01:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-09-15 16:40:13 +08:00
|
|
|
|
// 删除对应键名的缓存数据
|
2018-12-30 18:56:21 +08:00
|
|
|
|
func (c *memCache) clearByKey(key interface{}, force...bool) {
|
2018-09-15 16:40:13 +08:00
|
|
|
|
// 删除缓存数据
|
2018-12-04 19:26:46 +08:00
|
|
|
|
c.dataMu.Lock()
|
2018-09-15 16:40:13 +08:00
|
|
|
|
// 删除核对,真正的过期才删除
|
|
|
|
|
|
if item, ok := c.data[key]; (ok && item.IsExpired()) || (len(force) > 0 && force[0]) {
|
|
|
|
|
|
delete(c.data, key)
|
|
|
|
|
|
}
|
2018-12-04 19:26:46 +08:00
|
|
|
|
c.dataMu.Unlock()
|
2018-09-15 16:40:13 +08:00
|
|
|
|
|
|
|
|
|
|
// 删除异步处理数据项
|
2018-12-04 19:26:46 +08:00
|
|
|
|
c.expireTimeMu.Lock()
|
|
|
|
|
|
delete(c.expireTimes, key)
|
|
|
|
|
|
c.expireTimeMu.Unlock()
|
2018-09-15 16:40:13 +08:00
|
|
|
|
|
|
|
|
|
|
// 删除LRU管理对象中指定键名
|
2018-12-30 14:53:16 +08:00
|
|
|
|
if c.cap > 0 {
|
|
|
|
|
|
c.lru.Remove(key)
|
|
|
|
|
|
}
|
2018-09-15 16:40:13 +08:00
|
|
|
|
}
|