我需要建立一个像这样的数据结构:
map[string]SomeType
但它必须存储大约10分钟的值,然后从内存中清除它。 第二个条件是记录数量 - 它必须是巨大的。此数据结构必须至少每秒添加 2-5K记录。
那么,Go中最正确的方法是什么?
我试图用每个新元素的超时来制作goroutine。和一个(或更多)垃圾收集器goroutine与通道接收超时和清除元素。 但我不确定它是最明确的方式。拥有数百万等待超时的goroutine是否可以?
感谢。
答案 0 :(得分:15)
您必须创建一个结构来保存地图并提供自定义的get / put / delete功能来访问它。
请注意,每秒2-5k次访问并不是那么多,所以你不必担心这一点。
这是一个简单的实现:
type item struct {
value string
lastAccess int64
}
type TTLMap struct {
m map[string]*item
l sync.Mutex
}
func New(ln int, maxTTL int) (m *TTLMap) {
m = &TTLMap{m: make(map[string]*item, ln)}
go func() {
for now := range time.Tick(time.Second) {
m.l.Lock()
for k, v := range m.m {
if now.Unix() - v.lastAccess > int64(maxTTL) {
delete(m.m, k)
}
}
m.l.Unlock()
}
}()
return
}
func (m *TTLMap) Len() int {
return len(m.m)
}
func (m *TTLMap) Put(k, v string) {
m.l.Lock()
it, ok := m.m[k]
if !ok {
it = &item{value: v}
m.m[k] = it
}
it.lastAccess = time.Now().Unix()
m.l.Unlock()
}
func (m *TTLMap) Get(k string) (v string) {
m.l.Lock()
if it, ok := m.m[k]; ok {
v = it.value
it.lastAccess = time.Now().Unix()
}
m.l.Unlock()
return
}
答案 1 :(得分:2)
我建议使用golang内置软件包sync
的Map,它非常易于使用并且已经处理了并发https://golang.org/pkg/sync/#Map
答案 2 :(得分:1)
为了记录,我遇到了同样的问题并编写了tinykv包,内部使用了地图。
time.Time
进行超时,因此它不会覆盖整个地图。time.Duration
大于零且小于最大值的任何值。CAS
和Take
功能。