How to implement efficient in memory key value store in golang

huangapple go评论78阅读模式
英文:

How to implement efficient in memory key value store in golang

问题

我想知道在Golang中是否有任何具有过期和高效性的包。

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

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

英文:

I would like to know are there any packages in golang that will have expiry and efficient

I checked a few, Here is one of them, But from the implementation perspective it is locking entire cache to write one entry (Check this) which is not needed right?

Is it possible to lock one entry instead of locking entire cache?

答案1

得分: 1

从你在问题中提供的同一个存储库中,还有一个分片策略的实现,它可以为每个分区提供一个锁,而不是为整个缓存提供一个锁。例如,如果你决定使用4个缓存进行分区,你可以计算关键字的哈希值的模,并将其存储在该索引处的缓存中。通过改进这个方法,你可以理论上使用子分区进行分片,通过二叉树分解关键字,以实现所需的缓存(和锁定)粒度。

英文:

From the same repo you linked in your question, there is also an implementation of sharding strategy that should provide you with a lock per partition vs a lock for the whole cache. For example if you decide to partition using 4 caches, you can compute the modulo of some hash for the key and store in the cache at that index. Refining this same method, you could in theory shard using sub-partitions, decomposing the key thru a binary tree to give you the desired caching (and locking) granularity.

答案2

得分: 0

锁定单个条目并不容易,但如果你想要更高效的话,在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 c.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}
		}
	}
}
}

希望对你有帮助!

英文:

It is not easy to lock only one entry, but you wanna more efficient, a good practice in Go is to use channel to communicate with a sequential process. In this way, there is no shared variables and locks.

a simple example of this:

type request struct {
	reqtype string
	key      string
	val      interface{}
	response chan&lt;- result 
}

type result struct {
	value interface{}
	err   error
}


type Cache struct{ requests chan request }

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

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

func (c *Cache) Set(key, val string) {
	c.requests &lt;- request{&quot;SET&quot;, key, val, response}
}

func (c *Cache) server() {
	cache := make(map[string]interface{})
	for req := range memo.requests {
		switch req.reqtype {
			case &quot;SET&quot;:
				cache[req.key] = req.val
			case &quot;GET&quot;:
				e := cache[req.key]
				if e == nil {
					req.response &lt;- result{e, errors.New(&quot;not exist&quot;)}
				} else {
					req.response &lt;- result{e, nil}
				}
		}
	}
}

huangapple
  • 本文由 发表于 2016年4月16日 14:30:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/36660943.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定