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

问题描述 投票:6回答:2

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

map[string]SomeType 

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

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

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

谢谢。

data-structures go timeout ttl
2个回答
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
投票

只是为了记录,我有同样的问题,写了tinykv包,内部使用地图。

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