39 | 存储与缓存
该思维导图由 AI 生成,仅供参考
memcached
- 深入了解
- 翻译
- 解释
- 总结
本文介绍了存储与缓存之间的关系,以及三种不同模型的缓存系统:memcached、groupcache和Redis。缓存被描述为存储系统性能的补丁,虽然并不完美。文章首先介绍了groupcache,它引入了group的概念,允许创建独立的内存缓存集群,解决了memcached存在的一致性缺陷。然后,文章提到Redis,指出它在定位上特别奇怪,既可以作为内存缓存,也可以作为存储。然而,如果将Redis视为存储,就需要考虑持久性和重试的友好性等重要问题。最后,总结指出缓存是存储系统的补丁,虽然不完美,但对服务器性能有所改善。整体而言,本文通过介绍不同的缓存系统,展示了它们在解决存储系统性能问题上的特点和局限性。
《许式伟的架构课》,新⼈⾸单¥68
全部留言(19)
- 最新
- 精选
- Geek_88604f对于一个确定的 x 值,如果 F(x) 永远不变,这就没问题。但如果 F(x) 值是不确定的,那就有可能会出现并发的两个 F(x) 请求得到的结果不同,从而导致缓存中的值和存储中的值不一致。 这段描述我是这么理解的,老师的意思是不是两个线程同时去get同一个key,发现key不在缓存中,此时两个线程都会去计算key对应的value,当线程A拿到x完成计算后准备将计算结果刷到缓存(但还未刷新到缓存),线程B拿到了已经改变过的x(如果x表示select某个数据表的返回值,线程c有可能在线程B计算之前改变了x)也计算了值并先于线程A将值刷新到缓存,然后线程A才缓过劲来将它的计算结果刷新到缓存,这样导致的最终结果是缓存和存储中的值不一致。 对于这种情况我觉得可以考虑以下几个方案去改进或规避:(1)考虑缓存的key为空的情况毕竟占少数,因此可以考虑当读取到缓存为空时随机等待几个毫秒的延迟后再次读取,如果key还为空则计算y=f(x)。(2)缓存更新序列化,将y=f(x)的计算从fastf(x)中移除,当缓存没有命中时向消息队列发起异步更新消息,消费者从消息队列中取消息计算f(x)并刷新缓存(如果短时间内有大量的更新消息,可以考虑只处理最新的消息),当然业务侧要做读取缓存的重试。(3)将y=f(x)的计算从fastf(x)中移除,设置缓存不老化,fastf(x)只负责读取数据,当缓存没有命中的时候从存储中读取。由x的变化发起者或者定时任务来计算f(x),当x发生变化的时候完成计算并刷新缓存。
作者回复: 你的理解是对的,当存在并行的Set请求,自然存在时序问题,导致存储和缓存数据不一致。解决方案来说: 1、sleep不能解决多任务协同问题,所以这个方案不可行。 2、是可行的思路,把 F(x) 和 Set 一起串行执行。不过这会导致在缓存未命中时 F(x) 执行两遍。你说的缓存未命中从存储读,本质上是执行 F(x) 的意思。 3、存储中 x 对应的数据发生变化时,我们通常的做法是把 x 从缓存中清除(Delete),而不是执行 F(x) 和 Set。原因是缓存空间是有限的,所以要给 Get 次数比较多的数据缓存,而不是一发生变更就缓存,这样非常可能反而降低了缓存命中率。
2019-09-07217 - Dean如何理解groupcache值不可变就解决了一致性问题,此时如果存储的值变了,缓存中的相应的计算结果如果不变的话,不是也不一致么?
作者回复: 你可以这么理解:以键值存储为例,它存储的是 key => (value, ver),而 groupcache 存储的是 (key, ver) => value。这样就可以做到存储的值改变而 groupcache 值不变。只不过怎么用,这个需要好好考虑一下。
2019-09-1629 - Tachyon缓存雪崩并不是说缓存大量宕机,而是大量key几乎同时过期导致请求直接打到后端存储上。
作者回复: 成因可以多样化,同时过期的效果和宕机显然类似。
2019-09-206 - Charles所以许老师怎么去评估一个系统是否应该上缓存,假设目前存储都可以顶住负载?谢谢
作者回复: 要分析清楚压力和和效率瓶颈。压力大了,可以考虑加缓存,当然也可以考虑存储扩容。效率瓶颈,通常只能用缓存解决。
2019-09-086 - ecareyu讲述人对于专业名词的英文读的我一脸懵逼啊?memcache要是我不看文档都不知道是啥
作者回复: 嗯,之前讲述人是非科技领域的。我们在重新录音频。
2020-07-15 - Geek_88604ffunc FastF(x TypeX) (y TypeY) { key := toBytes(x) hash := hashOf(key) i := hash % countOf(memcaches) val, err := memcaches[i].Get(key) if err != nil { y = F(x) val = toBytes(y) memcaches[i].Set(key, val) } else { y = fromBytes(val) } return } 这段代码第六行判断条件是=还是≠,没太明白整个逻辑。
作者回复: err != nil 表示失败
2019-09-06 - 诗泽如果 F(x) 值是不确定的,这种情况下放缓存里也就没意义了吧?
作者回复: 这里说的不确定不是太准确,正确应该说会改变,有多个版本
2019-09-06 - 风清扬许老师,缓存血崩的原因是命中率降低,大量请求直达后端,后端性能极速下降导致,解决办法是抛弃过多的请求。想到的一个是应用层既网关层限流。能详细讲解下吗?
作者回复: 后面还会细聊这些问题
2019-09-06 - mickey祝许老师以及极客全体老师教师节快乐,工作顺利,身体健康!2019-09-104
- dovefi个人总结一下: 缓存的用途: 1、数据缓存 2、计算缓存(还是第一次听到)用户缓存复杂的计算结果2020-06-212