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