天天看点

大型web系统中缓存的使用

        对于一个规模很大的web系统,如PV在一亿以上,缓存就是一个不可或缺的重要组成部分,它可以挡掉大部分的用户访问的冲击,如果没有它,系统很可能将迅速不可用直至崩溃。

但是缓存带来了另外一些棘手的问题: 一致性和实时性。

一个很直观的场景就是,数据库中的数据状态已经改变,但是用户在页面上看到的仍然是缓存的旧值。

一般来说,缓存数据本身都是保持在内存中的,例如淘宝内部大量使用的tair系统(已开源)。tair拥有若干服务器,这些服务器内存都很大,可以存放大量数据。当然,考虑到内存的易失性,tair一般来说不能存放重要的数据。

什么样的数据可以放缓存,什么样的场景适合使用缓存,什么场景不应该使用,这几个问题是系统设计之初必须考虑的问题。

----

什么样的数据可以放缓存?

1,不需要实时更新但是又极其消耗数据库的数据。比如网站上商品销售排行榜,这种数据一天统计一次就可以了,用户不会关注其是否是实时的。

2,需要实时更新,但是更新频率不高的数据。比如一个用户的订单列表,他肯定希望能够实时看到自己下的订单,但是大部分用户不会频繁下单(炒信用之类的除外)。

3,在某个时刻访问量极大而且更新也很频繁的数据。这种数据有一个很典型的例子就是秒杀,在秒杀那一刻,可能有N倍于平时的流量进来,系统压力会很大。但是这种数据使用的缓存不能和普通缓存一样,这种缓存必须保证不丢失,否则会有大问题。

什么时候不应该使用缓存?

实际上在一个web站点中,大部分数据都是可以缓存的,反而不能使用缓存的是很小一部分。这类数据包括比如涉及到钱、密钥、业务关键性核心数据等。有一个经验之谈就是,如果在设计web系统的时候,发现大部分数据都不能使用缓存,则说明设计或者架构本身出了问题,此时需要考虑设计的合理性了。

如何解决一致性的问题?

一个总的原则就是:一旦数据库更新了,就必须把原来的缓存失效掉。

有的时候要做到这一点是很困难的,似乎听起来很可笑,但是当系统规模达到一定程度的时候,这个问题就会凸显。在一个大的团队中,每个开发都在系统里面提交自己的代码,很可能某段代码修改了数据库,但是忘了清缓存,造成生产环境发生故障。对于这种问题,主要得靠代码review来解决。

另外,在故障发生的时候,我们不能束手无策,换句话说,系统内部也要有可以直接触发的清理缓存的”接口“,这个接口可以是一个特殊的url,或者一个只有内部才能访问的控制台等。

关于折衷的问题。。。

假设有一个数据,它更新频繁,访问量很高,我们将其缓存,但是由于更新频繁,所以可能会频繁触发清缓存操作,这样缓存实际上就成了摆设。如果业务允许,我们不需要每次都清缓存,简而言之,就是允许系统存在一小段时间的数据显示不一致的情况。这是一个比较折衷的方法,对用户体验而言,也无大碍。

更加高级的缓存。。。

以上说的缓存,都是数据缓存,还有一种更加高级的缓存,即把动态页面(如JSP)进行静态化处理,这个比数据缓存复杂的多。目前有一些开源的框架可以支持,比如varnish,性能很高,当然学习成本也很高。关于varnish的使用,本文就不赘述了,有兴趣的可以自行去其官方网站查阅。

本文转自 kevx 51CTO博客,原文链接:http://blog.51cto.com/spinlock/851646,如需转载请自行联系原作者