【问题标题】:two-level cache (memory + redis) implementation in GoGo中的两级缓存(内存+redis)实现
【发布时间】:2019-08-13 07:41:52
【问题描述】:

我正在尝试写一个二级缓存(内存+redis),但是当一个key有高并发访问时遇到了瓶颈,我尝试为每个key使用互斥锁,但这增加了很多cpu因为 loadFromDB 需要 100-200 毫秒。

func (s *Store) GetJsonObjectWithExpire(key string, obj interface{}, ttl int, f StoreLoadFunc) error {
    // first read from memory
    v, ok := s.mem.Get(key)
    if ok {
        if v.Outdated() {
            to := deepcopy.Copy(obj)
            go s.updateMem(key, to, ttl, f)
        }
        return nil
    }

    // if missed in memory, check from redis
    v, ok = s.rds.Get(key, obj)
    if ok {
        if v.Outdated() {
            go s.rds.loadFromDB(key, nil, ttl, f, false)
        }
        return nil
    }
    return s.rds.loadFromDB(key, obj, ttl, f, true)
}

loadFromDB 将从 db 加载对象并将其写入 redis 和内存,这大约需要 100-200ms,loadFromDB 和 rds.Get 函数现在都使用 per-key RWMutex。

由于会有很多键(10000+),我不确定为每个键使用互斥锁是否是个好主意?

我可以做些什么来提高性能?

更新: 这是我在 github 上的代码,用于我的两级缓存模式实现。

https://github.com/seaguest/cache

【问题讨论】:

  • 拥有许多互斥锁并不能保证 CPU 资源。你如何使用它们可能会这样做。我们对您的实际代码知之甚少,因此很难为您提供帮助。
  • 如果我理解的任务正确,互斥体的数量(嗯...互斥体?)取决于正在访问的资源数量,而不是用户数量。综上所述,需要一个 MCVE 来提供更多信息。
  • “每个用户都需要一个互斥锁”很难想象这样的用例,你能详细说明一下吗?
  • 如果我理解,您正在做一些需要很长时间的计算,如果您同时收到请求,您不想做多次。如果两个相同的请求一起出现会发生什么?两者是否都需要等待计算完成,或者如果一个(甚至两个)都获得旧数据可以吗?
  • @Flimzyyes,完全正确

标签: go caching concurrency mutex


【解决方案1】:

最后,这是我的 github 仓库:

A lightweight distributed two-level cache (memory + redis) with loader function library for Go.

欢迎尝试,欢迎提出任何建议。

【讨论】:

    猜你喜欢
    • 2018-01-09
    • 2017-11-22
    • 1970-01-01
    • 2012-02-21
    • 1970-01-01
    • 2015-03-14
    • 2011-02-24
    • 2015-11-24
    • 1970-01-01
    相关资源
    最近更新 更多