在Go中使用TTL选项进行映射

时间:2014-08-25 10:43:45

标签: data-structures go timeout ttl

我需要建立一个像这样的数据结构:

map[string]SomeType 

但它必须存储大约10分钟的值,然后从内存中清除它。 第二个条件是记录数量 - 它必须是巨大的。此数据结构必须至少每秒添加 2-5K记录

那么,Go中最正确的方法是什么?

我试图用每个新元素的超时来制作goroutine。和一个(或更多)垃圾收集器goroutine与通道接收超时和清除元素。 但我不确定它是最明确的方式。拥有数百万等待超时的goroutine是否可以?

感谢。

3 个答案:

答案 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

}

playground

答案 1 :(得分:2)

我建议使用golang内置软件包sync的Map,它非常易于使用并且已经处理了并发https://golang.org/pkg/sync/#Map

答案 2 :(得分:1)

为了记录,我遇到了同样的问题并编写了tinykv包,内部使用了地图。

  • 它使用一堆time.Time进行超时,因此它不会覆盖整个地图。
  • 创建实例时可以设置最大间隔。但是,根据超时的最后一项,检查超时的实际间隔可以是time.Duration大于零且小于最大值的任何值。
  • 它提供CASTake功能。
  • 可以设置回调(可选),通知哪个键和值超时。
  • 超时可以是明确的或滑动的。