我需要建立一个这样的数据结构:
map[string]SomeType
但是它必须存储值大约10分钟,然后从内存中清除。第二个条件是记录的数量——必须是巨大的。这个数据结构必须至少每秒增加2-5K条记录。
那么,在Go中最正确的方法是什么呢?
我正在尝试为每个新元素创建超时例程。以及一个(或多个)垃圾收集器例程,该例程具有接收超时和清除元素的通道。但我不确定这是最清晰的方式。有数百万个带有超时的等待程序可以吗?
谢谢。
您必须创建一个结构体来保存您的map,并提供自定义的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
}
游乐场注释(2020-09-23):由于某种原因,当前版本的操场上的时间分辨率是很远的,这工作得很好,但是要在操场上尝试,你必须将睡眠更改为3-5秒。
看看buntdb。
tinykv
不再被维护
只是为了记录,我有同样的问题,并编写了一个内部使用map的tinykv包。
- 使用
time.Time
堆来处理超时,所以它不会覆盖整个地图。 - 创建实例时可以设置最大时间间隔。但是检查超时的实际间隔可以是
time.Duration
大于0小于max的任何值,基于最后一个超时的项。 - 提供
CAS
和Take
功能 - 可以设置一个回调(可选),通知哪个键和值超时。
- 超时可以是显式的,也可以是滑动的。
我建议使用Map的golang的内置包sync
,它很容易使用,已经处理并发https://golang.org/pkg/sync/#Map