【问题标题】:Data-structure for concurent heavy read workload并发重读工作负载的数据结构
【发布时间】:2017-12-31 00:26:49
【问题描述】:

我正在寻找一种存储 32 字节字符串并允许以首选 O(1) 或 O(log N) 查找复杂度进行快速查找的数据结构(目标只是确定密钥是否存在)。移除和插入的复杂性并不重要,因为这些操作很少见。

这与问题无关,但我正在使用 Go。我可以使用由互斥体支持的 hashmap,但争用将是一个问题,如果有更好的解决方案,我更愿意避免分片。

谢谢

【问题讨论】:

  • 您是否对map[string]struct{}RWMutex 进行了基准测试?
  • This hasmap package 可以满足您的需求。
  • 我们在这里谈论每秒多少次查找?一共有多少把钥匙?您说删除和插入很少见。多少见?对我来说,这听起来像是一个哈希图和一个读/写锁对你来说非常有效。见stackoverflow.com/questions/19148809/…

标签: algorithm go data-structures containers


【解决方案1】:

map 对于并发读取是安全的。你可以把你想要的地图放在sync/atomic.Value里面,当你想写的时候,复制地图并改变它,然后把它放回Value里面。来自docs

下面的例子展示了如何保持一个可伸缩的频繁 使用写时复制读取但不经常更新的数据结构 成语。

代码:

type Map map[string]string
var m Value
m.Store(make(Map))
var mu sync.Mutex // used only by writers
// read function can be used to read the data without further synchronization
read := func(key string) (val string) {
        m1 := m.Load().(Map)
        return m1[key]
}
// insert function can be used to update the data without further synchronization
insert := func(key, val string) {
        mu.Lock() // synchronize with other potential writers
        defer mu.Unlock()
        m1 := m.Load().(Map) // load current value of the data structure
        m2 := make(Map)      // create a new value
        for k, v := range m1 {
                m2[k] = v // copy all data from the current object to the new one
        }
        m2[key] = val // do the update that we need
        m.Store(m2)   // atomically replace the current object with the new one
        // At this point all new readers start working with the new version.
        // The old version will be garbage collected once the existing readers
        // (if any) are done with it.
}
_, _ = read, insert

您也可以使用指向您的指针 map 而不是 Value 并使用 StorePointer/LoadPointer 以原子方式存储它,但这并不干净,因为您应该使用不安全的指针并强制转换它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-16
    • 2012-02-18
    • 1970-01-01
    • 1970-01-01
    • 2013-10-14
    • 1970-01-01
    相关资源
    最近更新 更多