-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbeegofreecache.go
216 lines (189 loc) · 5.52 KB
/
beegofreecache.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
package beegofreecache
import (
"github.com/coocood/freecache"
"encoding/gob"
"bytes"
"time"
"fmt"
"github.com/astaxie/beego/cache"
"encoding/json"
"errors"
)
//缺点:
// 1.当需要缓存的数据占用超过提前分配缓存的 1/1024 则不能缓存
// 2.当分配内存过多则会导致内存占用高 最好不要超过100MB的内存分配
// 3.key的长度需要小于65535字节
var (
DefaultSize = 64 //64M
free *freecache.Cache = nil
)
type Cache struct {
Free *freecache.Cache
}
// 如果是需要集成到beego,则init函数必须打开,反之可以注释掉
func init() {
gob.Register(map[string]interface{}{})
gob.Register(map[string][]int{})
gob.Register(map[string][]int64{})
cache.Register("beegofreecache", NewFreeRegister)
}
// 该函数是为了集成到beego框架中
func NewFreeRegister() cache.Cache {
return &Cache{}
}
// 该函数是可以在任意地方使用,初始化Free进程缓存
func NewFree(m int) *Cache {
if free == nil {
cacheSize := m * 1024 * 1024
free = freecache.NewCache(cacheSize)
}
//beeFree := Cache{}
beeFree :=new(Cache)
beeFree.Free = free
return beeFree
}
//根据key获取对应的value,如果不是在beego框架中,建议使用GetValue
func (free *Cache) Get(key string) interface{} {
cache, err := free.Free.Get([]byte(key))
if err != nil || len(cache) <= 0 {
return nil
}
return cache
}
// 推荐使用,但是beego框架不支持
func (free *Cache) GetValue(key string, value interface{}) error {
cache, err := free.Free.Get([]byte(key))
if len(cache) > 0 && err == nil {
err = GobDecode(cache, value)
return nil
} else {
return err
}
}
//批量获取keys
func (free *Cache) GetMulti(keys []string) []interface{} {
retList := make([]interface{}, 0)
for i := 0; i < len(keys); i++ {
retList = append(retList, free.Get(keys[i]))
}
return retList
}
//设置缓存
func (free *Cache) Put(key string, val interface{}, timeout time.Duration) error {
var cache []byte = make([]byte, 0)
var err error
// 如果value是[]byte就不需要转化了
switch val.(type) {
case []byte:
cache = val.([]byte)
default:
cache, err = GobEncode(val)
}
if err == nil {
err = free.Free.Set([]byte(key), cache, int(timeout.Seconds()))
}
return err
}
// 删除key
func (free *Cache) Delete(key string) error {
b := free.Free.Del([]byte(key))
if b {
return nil
} else {
return errors.New("del" + key + " error!!!")
}
}
//对key值为int64的加1
func (free *Cache) Incr(key string) error {
/*buf:=free.Get(key)
if buf ==nil {
return errors.New("key is empty")
}
var value int64
err:=GobDecode(buf.([]byte),&value)*/
var value int64
err := free.GetValue(key, &value)
if err != nil {
return errors.New("value is not an integer or out of range")
}
t, err := free.Free.TTL([]byte(key))
free.Put(key, value+1, time.Duration(t)*time.Second)
return err
}
//对key值为int64的减1
func (free *Cache) Decr(key string) error {
var value int64
err := free.GetValue(key, &value)
if err != nil {
return errors.New("value is not an integer or out of range")
}
t, err := free.Free.TTL([]byte(key))
free.Put(key, value-1, time.Duration(t)*time.Second)
return err
}
//判断指定key是否存在
func (free *Cache) IsExist(key string) bool {
buf := free.Get(key)
if buf == nil {
return false
}
return true
}
//清出所有缓存
func (free *Cache) ClearAll() error {
free.Free.Clear()
return nil
}
//在beego框架中,注册时会自动执行该函数初始化
func (cache *Cache) StartAndGC(config string) error {
var cf map[string]int
json.Unmarshal([]byte(config), &cf)
if _, ok := cf["size"]; !ok {
cf = make(map[string]int)
cf["size"] = DefaultSize
}
//NewFree(int(cf["size"]))
if free == nil {
cacheSize := int(cf["size"]) * 1024 * 1024
free = freecache.NewCache(cacheSize)
}
cache.Free = free
cache.Free.ResetStatistics()
// free = nil
return nil
}
//输出cache状态
func (free *Cache) String() string {
info := fmt.Sprintf("EntryCount is %d,ExpiredCount is %d,HitCount is %d,HitRate is %f,EvacuateCount Is %d,AverageAccessTime is %d,LookupCount is %d .", free.Free.EntryCount(), free.Free.ExpiredCount(),
free.Free.HitCount(), free.Free.HitRate(), free.Free.EvacuateCount(), free.Free.AverageAccessTime(), free.Free.LookupCount())
return info
}
//获取cache状态
func (free *Cache) CacheStatus() map[string]interface{} {
infoMap := map[string]interface{}{
"HitCount": free.Free.HitCount(),
"HitRate": free.Free.HitRate(),
"EvacuateCount": free.Free.EvacuateCount(),
"AverageAccessTime": free.Free.AverageAccessTime(),
"LookupCount": free.Free.LookupCount(),
"EntryCount": free.Free.EntryCount(),
"ExpiredCount": free.Free.ExpiredCount(),
}
return infoMap
}
// Gob序列化
func GobEncode(data interface{}) ([]byte, error) {
buf := bytes.NewBuffer(nil)
enc := gob.NewEncoder(buf)
err := enc.Encode(data)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// Gob反序列化
func GobDecode(data []byte, to interface{}) error {
buf := bytes.NewBuffer(data)
dec := gob.NewDecoder(buf)
return dec.Decode(to)
}