最近,我读了这篇Stack Overflow博客文章,介绍了他们如何布置一些基础架构。

我很好奇,Stack Exchange是否使用缓存(在应用程序层和/或数据库层) ),如果可以,怎么办?

评论

我认为问题不属于meta,但我认为它涉及面太广:在诸如SO之类的大型网站的实现中,存在不同级别的上千种内容可能会被缓存。许多无疑是。大多数缓存层都是透明的(它或多或少是规范的一部分),因此程序员不必担心,思考它们甚至知道它们的存在。

当然,如果要使系统扩展到如今Stack Overflow拥有的活动水平,那将是非常昂贵的(读:“不可能”)。这是Stack Exchange今天如此高效运行的最大原因。
相关:哪些工具和技术用于构建Stack Exchange网络?

#1 楼

哦,天哪,我是否一直在等待有人问这样的事情?

我们真的积极地缓存...基本上所有内容。

几乎所有(并随后提供给到)通过输出缓存将匿名用户整个存储起来。尽管我们最近从少量路由中删除了输出缓存,但这并不是很有趣,但是却非常快。

也许更有趣,我们将Redis用作整个缓存层网络。凯尔(Kyle)最近提到了该机器的规格。在纽约迁移之前,我们的Redis实例位于(轻载)Web层计算机上的虚拟机中。

在我们(​​有限的)经验中,Redis是如此之快,以至于缓存中最慢的部分查找是将字节读取和写入网络所花费的时间。如果您考虑一下,这并不奇怪。

我们通过两种方式对此进行补偿:


我们保留“ L1”缓存(基本上,HttpRuntime.Cache)最近在服务器上设置/读取的值


自然,通过网络发送的最快字节数是0。


我们先压缩值*,然后再将其发送到Redis


,我们大多数缓存的值都是字符串,因此即使在CPU使用率较低的情况下,我们也可以获得很高的压缩率
Web层上有大量的CPU时间,尤其是在纽约数据中心。
我们已经变得更加智能,只压缩实际上压缩得更小的东西(读取键时需要一些健美操)和.NET 4.5的GZip实现要好得多




从概念上讲,每个站点都有3个不同的缓存:
”只能从1个服务器/站点对中访问


包含诸如用户会话和待处理的视图库之类的内容nt更新
这完全驻留在内存中,没有网络或数据库访问权限


一个“站点缓存”,可以由单个站点的任何实例(在任何服务器上)访问


大多数缓存的值都在这里,诸如热点问题ID列表和用户接受率之类的东西都是很好的例子
它位于Redis中(位于一个单独的数据库中,纯粹是为了简化调试)


“全局缓存”,在所有站点和服务器之间共享
/>

收件箱,API使用配额和其他一些真正的全局信息都存放在这里
这位于Redis中(在DB 0中,同样是为了方便调试)



我们将尽最大努力避免缓存失效,因此缓存中的大多数内容只会过期,并且永远不会明确删除。但是,在极少数需要删除的情况下,我们使用Redis消息发布删除通知**(仅出于扩展目的仅在那些关心的站点上发布)。

一些快速统计信息:


在任何时候,我们的Redis缓存中大约有1,300,000个键


其中大多数键会在几分钟左右到期
此数字不断增长,因为我们对Redis越来越有信心


在高峰时间,我们可以对Redis进行每秒几百次读/写操作


这远低于目前的基准测试

我们专用的Redis机器上的CPU使用率实际上一直为0%

实际上,一直如此
经过几个月的增长,我们看到了0.5%的CPU使用量峰值
经过了更长的时间,我们看到了大约1%的CPU使用率


内存使用率一直保持在1/2 GB的南部,现在已降至8 GB左右,现在约为6 GB。


如w e主要存储整数和压缩字符串集。
我们还开始在Redis中存储更大的内容,例如收件箱。
较新的Redis版本节省了一些空间,并且精简了一些通用键





*仍然,对于某些常见用例,Redis命令的最大部分是键名。这些天之一,我将花一些时间来尝试压缩整个命令流,并查看可以带来什么样的性能提升。

**这些删除操作对于使“ L1缓存”,Redis在删除时自然会保持一致状态。

评论


您的网络服务器是否粘滞? ip是否被路由到他们首先到达的同一Web服务器?如果是,haproxy可以管理吗?

–谢里安
2011-3-6在4:32

嗨,您在Windows上使用Redis吗?如果是,它的稳定性如何?当我们要开始进行高流量的本地分类站点时,请回复,并且需要在Windows上使用Redis。

– Ajax2020
2011-10-20 15:54

@ Ajax2020-我们在Linux(特别是Ubuntu服务器)上托管Redis,我们从未遇到任何稳定性问题。

–凯文·蒙特罗斯♦
2011年10月20日在16:02

您是否可以添加SQL服务器与缓存之间的交互详细信息,例如如何填充缓存?是否所有内容都是惰性加载的(暗示着如果没有请求,它将不会在缓存中)?如果是这样,您是否明确保留了某些数据片段/类别?您是否使用SQL通知来使高速缓存保持更新,还是使用DAL更新高速缓存?

–丹尼尔·谢弗(Daniel Schaffer)
2012年3月14日在21:02



您是否在客户端上缓存页面?如果这样做,当匿名用户成为登录用户后,如何使该用户的缓存无效?如果我以匿名身份访问页面A,然后以登录用户身份访问页面A,您将如何处理?

– StackOverflower
2012年5月17日14:59



@KevinMontrose:您目前是否有特定的方式来缓存用户特定数据? 。用户帐户太多,每个用户的数据各不相同。我想知道Redis是否可以为我们提供解决此类情况的任何方法。

– Boddhisattva
2012年8月23日在11:53

@boddhisattva-在这种情况下,我们作弊了一点,我们的路由被IP粘住了,因此用户会话可以在本地缓存以提高速度。

–凯文·蒙特罗斯♦
2012年8月23日在16:33

用于将内容发送到Redis的压缩算法是什么? zlib?只是好奇

–马恩
2012年9月3日在16:03

@Mahn-我们使用GZip,它在.NET 4.5中由zlib支持。

–凯文·蒙特罗斯♦
2012年9月3日下午16:38

您能否告诉您您正在使用哪个客户端库从.net环境访问Redis?

–wallice
2012年9月10日上午8:09

@wallice-Booksleeve是为供Redis使用而内部开发的。

–凯文·蒙特罗斯♦
2012-09-10 19:43

我知道这个问题有点老了,但我对一件事很好奇:您说过避免缓存失效,基本上让Redis缓存本身失效。您使用的TTL是多少?我熟悉另一种方法-长TTL,但是有一个复杂的失效系统,可以在实际数据更改后立即处理失效。有什么更好的方法?

– Przemek
13年5月29日在15:42

有谁知道自定义OutputCache Provider是否用于在Redis层中存储输出缓存?

–拉胡尔·帕特尔(Rahul Patel)
13年11月27日在8:08



@tobi:SQL仅缓存基础数据,而不缓存结果集。因此,SQL查询仍然针对RAM运行。这样的查询可能会引起争用(读/写锁定),特别是因为它们可能命中多个表。

–布赖恩
16-09-20在15:18



第三方试图提供SQL查询缓存,但没有一个成功。我对mysql知之甚少,但会注意到它有多个数据库引擎,因此缓存的方法可能会因配置而异。也许在stackoverflow上问这个问题?

–布赖恩
16-09-22在13:01