-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathmap.go
183 lines (162 loc) · 3.6 KB
/
map.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
package expire_map
import (
"sync"
"time"
)
type val struct {
data interface{}
expiredTime int64
}
const delChannelCap = 100
type ExpiredMap struct {
m map[interface{}]*val
timeMap map[int64][]interface{}
lck *sync.Mutex
stop chan struct{}
}
func NewExpiredMap() *ExpiredMap {
e := ExpiredMap{
m: make(map[interface{}]*val),
lck: new(sync.Mutex),
timeMap: make(map[int64][]interface{}),
stop: make(chan struct{}),
}
go e.run(time.Now().Unix())
return &e
}
type delMsg struct {
keys []interface{}
t int64
}
//background goroutine 主动删除过期的key
//数据实际删除时间比应该删除的时间稍晚一些,这个误差会在查询的时候被解决。
func (e *ExpiredMap) run(now int64) {
t := time.NewTicker(time.Second * 1)
defer t.Stop()
delCh := make(chan *delMsg, delChannelCap)
go func() {
for v := range delCh {
e.multiDelete(v.keys, v.t)
}
}()
for {
select {
case <-t.C:
now++ //这里用now++的形式,直接用time.Now().Unix()可能会导致时间跳过1s,导致key未删除。
e.lck.Lock()
if keys, found := e.timeMap[now]; found {
e.lck.Unlock()
delCh <- &delMsg{keys: keys, t: now}
} else {
e.lck.Unlock()
}
case <-e.stop:
close(delCh)
return
}
}
}
func (e *ExpiredMap) Set(key, value interface{}, expireSeconds int64) {
if expireSeconds <= 0 {
return
}
e.lck.Lock()
defer e.lck.Unlock()
expiredTime := time.Now().Unix() + expireSeconds
e.m[key] = &val{
data: value,
expiredTime: expiredTime,
}
e.timeMap[expiredTime] = append(e.timeMap[expiredTime], key) //过期时间作为key,放在map中
}
func (e *ExpiredMap) Get(key interface{}) (found bool, value interface{}) {
e.lck.Lock()
defer e.lck.Unlock()
if found = e.checkDeleteKey(key); !found {
return
}
value = e.m[key].data
return
}
func (e *ExpiredMap) Delete(key interface{}) {
e.lck.Lock()
delete(e.m, key)
e.lck.Unlock()
}
func (e *ExpiredMap) Remove(key interface{}) {
e.Delete(key)
}
func (e *ExpiredMap) multiDelete(keys []interface{}, t int64) {
e.lck.Lock()
defer e.lck.Unlock()
delete(e.timeMap, t)
for _, key := range keys {
delete(e.m, key)
}
}
func (e *ExpiredMap) Length() int { //结果是不准确的,因为有未删除的key
e.lck.Lock()
defer e.lck.Unlock()
return len(e.m)
}
func (e *ExpiredMap) Size() int {
return e.Length()
}
//返回key的剩余生存时间 key不存在返回负数
func (e *ExpiredMap) TTL(key interface{}) int64 {
e.lck.Lock()
defer e.lck.Unlock()
if !e.checkDeleteKey(key) {
return -1
}
return e.m[key].expiredTime - time.Now().Unix()
}
func (e *ExpiredMap) Clear() {
e.lck.Lock()
defer e.lck.Unlock()
e.m = make(map[interface{}]*val)
e.timeMap = make(map[int64][]interface{})
}
func (e *ExpiredMap) Close() { // todo 关闭后在使用怎么处理
e.lck.Lock()
defer e.lck.Unlock()
e.stop <- struct{}{}
//e.m = nil
//e.timeMap = nil
}
func (e *ExpiredMap) Stop() {
e.Close()
}
func (e *ExpiredMap) DoForEach(handler func(interface{}, interface{})) {
e.lck.Lock()
defer e.lck.Unlock()
for k, v := range e.m {
if !e.checkDeleteKey(k) {
continue
}
handler(k, v)
}
}
func (e *ExpiredMap) DoForEachWithBreak(handler func(interface{}, interface{}) bool) {
e.lck.Lock()
defer e.lck.Unlock()
for k, v := range e.m {
if !e.checkDeleteKey(k) {
continue
}
if handler(k, v) {
break
}
}
}
func (e *ExpiredMap) checkDeleteKey(key interface{}) bool {
if val, found := e.m[key]; found {
if val.expiredTime <= time.Now().Unix() {
delete(e.m, key)
//delete(e.timeMap, val.expiredTime)
return false
}
return true
}
return false
}