golang如何实现高效的内存键值存储

golang如何实现高效的内存键值存储,go,Go,我想知道在golang有没有过期有效的包裹 我检查了一些,这里是其中之一,但从实现的角度来看,它是锁定整个缓存来写入一个不需要的条目(检查),对吗 是否可以锁定一个条目而不是锁定整个缓存?仅锁定一个条目并不容易,但要提高效率,Go中的一个良好做法是使用通道与顺序进程通信。这样,就没有共享变量和锁 这方面的一个简单示例: type request struct { reqtype string key string val interface{}

我想知道在golang有没有过期有效的包裹

我检查了一些,这里是其中之一,但从实现的角度来看,它是锁定整个缓存来写入一个不需要的条目(检查),对吗


是否可以锁定一个条目而不是锁定整个缓存?

仅锁定一个条目并不容易,但要提高效率,Go中的一个良好做法是使用通道与顺序进程通信。这样,就没有共享变量和锁

这方面的一个简单示例:

type request struct {
    reqtype string
    key      string
    val      interface{}
    response chan<- result 
}

type result struct {
    value interface{}
    err   error
}


type Cache struct{ requests chan request }

func New() *Cache {
    cache := &Cache{requests: make(chan request)}
    go cache.server()
    return cache
}

func (c *Cache) Get(key string) (interface{}, error) {
    response := make(chan result)
    c.requests <- request{key, response}
    res := <-response
    return res.value, res.err
}

func (c *Cache) Set(key, val string) {
    c.requests <- request{"SET", key, val, response}
}

func (c *Cache) server() {
    cache := make(map[string]interface{})
    for req := range memo.requests {
        switch req.reqtype {
            case "SET":
                cache[req.key] = req.val
            case "GET":
                e := cache[req.key]
                if e == nil {
                    req.response <- result{e, errors.New("not exist")}
                } else {
                    req.response <- result{e, nil}
                }
        }
    }
}
类型请求结构{
reqtype字符串
键串
val接口{}

response chan从您在问题中链接的同一个repo中,还有一种分片策略的实现,它应该为您提供每个分区的锁,而不是整个缓存的锁。例如,如果您决定使用4个缓存进行分区,您可以计算密钥的某些哈希的模,并将其存储在该索引处的缓存中。Refini如果使用相同的方法,理论上可以使用子分区进行切分,通过二叉树分解密钥,以提供所需的缓存(和锁定)粒度。

我不是自吹自擂,但我写这篇文章只是为了解决这个问题。切分的实现方式看起来不错。但我希望密钥也有到期时间,这在CMAP中是不存在的。虽然这样做有效,但它甚至比使用
sync.RWMutex
我对通道的经验是,除非你有一些Decent的异步任务在网络开销(或本地计算)水平上,与内存锁相比,它们的使用性能还不够好。因此,它回到了互斥锁(以及在其实现下面的自旋锁)YMMV。我推荐的一个建议是,始终将互斥定义放在它在结构中锁定的字段之上。捕捉得好!!我没有看到分片实现,但它仅处于实验阶段:(好吧,只需分叉,导出符号,使用它,修复它并提交PR:)