西西河

主题:谈谈大型网站架构的一些关键技术 -- 季侯

共:💬43 🌺225
全看分页树展 · 主题 跟帖
家园 【原创】Cache使用过程的一些陷阱

使用Cache有一些前提,这是做Cache规划时必须记住的。第一个前提是:缓存下来的东西需要频繁读取但不需要频繁变化,第二个前提是:读取缓存的代价应远小于读取源数据的代价。通常第二个前提很容易满足,一般不需要考虑太多。而第一个前提则经常隐含一些陷阱,当我们使用一些Cache技术的时候,这些陷阱通常会带来一些新问题。

我们把老季的例子推广到余票查询,这个余票数量就不是完全不变了。不过呢,按目前的情况我们可以合理假定余票数量变化期间还是有大量的重复查询动作。比较一下每天14亿的点击和100万的售票数量我们就知道有多少个查询是返回相同的结果了。那么我们是否可以把余票数据也放入缓存中呢?

我的直觉是......有陷阱。以memcached为例,这只是一个缓存服务器,它并不了解你缓存的是什么东西——实际上大多数的通用缓存技术都是这样。那么自然无法了解余票数量会因为有人订票而发生变化。这就要求你必须在做订票功能的时候,更新缓存了相关车次数据的所有缓存项。如果通过订票资料我们可以反推出影响了哪些查询结果,那很好办。我们只需要在订票功能上增加查询,然后用新的查询结果更新对应的缓存项就好了。第一个陷阱就是我们必须能通过修改操作的参数反推出需要修改哪些缓存结果。好在据说12306网站不能自己生成车票,所以这个应该是陷阱不存在的。

我们也可以在订票操作中直接删除受影响的缓存项,直到有人再次查询的时候顺便更新这个缓存。但这样很容易就踩进另一个小陷阱。尤其是查询量很大的时候,当我们突然删除一个缓存项,而同时又有大量的用户同时进行查询,那么极有可能在数据库出现一次查询爆发。因为在第一个查询尚未返回并更新缓存数据前,所有的相同查询都要访问数据库。在用户流量极大的时候这将会是一个问题。我经手的一个用户在使用memcached的时候就曾经碰到过这种情况,表现为网站随机地反应很慢。抑制这种突发的查询爆发,一般建议是在变更时直接更新缓存。如果做不到通过一种机制只让第一个查询访问数据库并更新缓存,其他的缓存访问则暂时等待一下。memcache在去年的一个更新里增加了一个新的API解决这个问题。不过我好像没在最新的发布版本上看到。

另外,就是像memcached这类成熟的通用缓存,为了在多线程环境下保护缓存数据(读的时候不能改,改的时候不能读)使用了锁(memcached使用互斥量)来做线程同步。这个锁对并发性是有影响的。memcached使用一个全局的互斥量,虽然简单,但在高并发访问下这是一个潜在的瓶颈。

以上的问题在大多数场合下并不严重,如果你的网站每秒不过一千的数据库访问可以基本忽视。

全看分页树展 · 主题 跟帖


有趣有益,互惠互利;开阔视野,博采众长。
虚拟的网络,真实的人。天南地北客,相逢皆朋友

Copyright © cchere 西西河