作为一种典型的超大规模WEB应用框架,维基百科的架构图流传很广,在前端使用LVS负载均衡,在请求服务层使用基于缓存反向代理,在核心业务块自然是使用数据库缓存memcached,而mysql数据库复制、读写分离自然无需熬言。

我更关注核心业务内的数据库缓存实现,这对从单机到大规模集群的站点都适用,在数据库问题没解决前,是相对长远的命题。

在windows平台上,因为稳定性,eaccelerator和xcache成为可能的选择,据kolidon测试,memcache服务器在windows上运行似乎会对CPU有较高要求(这个比较奇怪)。而在nix平台上,xcache+memcached当仁不让。

那么,缓存到何种程度为佳?基本上,目前通行的是:

1. 对开放式系统,若查询方式未作严格限定,则缓存到表级为佳,即:以表的更新为自动destroy所有相关缓存的信号;
2. 对专有系统,不妨针对每一种可能的选择决定如何缓存,而对每一个写查询,确定destroy哪些类型、哪些表、甚至哪些行级对象的缓存。

但前者的问题在于,在web2.0交互为王的时代,缓存生成后往往即刻被销毁,效率极低;
后者的问题在于,对专有系统的缓存计划,所耗人力成本相对较高。

但是,能否找出相对通行的准则?
关于这方面的讨论应该不少,个人思考如下:

1. 可以考虑配置信息不存储在数据库中而直接存成php文件或缓存对象,这能被xcache/apc/eaccelerate直接缓存在内存中执行,效率最佳(当然,在首次请求时从数据库中读出后写成php文件亦为合理方式)[DISCUZ],或缓存运算中间文档为PHP文件;
2. 另外,对一些结构简单且数据完整性并不重要的表,如session表,则可直接(读取后)利用eacc或xcache缓存机制在内存中建立对象,使用对象机制存取(失败则重新建立内存映象)(这和mysql基于内存的表性质相近,但应能节省sql语句编译时间和mysql引擎响应时间);
3. 尽量让一个表在一个页生命周期仅读或写一次,若有两个以上的交叉表查询,反复测试性能以比较它和事后的代码过滤机制何者开销为小(特别是数据库引擎严重承压的情况下);
4. 在某些基本命题下,事情可以简单化:如,若写表时若不涉及key字段(举例为:update时以key为条件但不包含目标行、insert新行、delete或replace以key字段为条件但非目标行),则以key字段为索引的单行查询不受影响(可以断定的是,有一半的查询是此类查询),除此之外,为节省人力成本计,均计算为完全更新所有目标表相关缓存;
5. 单一页面承载的业务逻辑不可过多(这是开放系统容易出现的状况),而专有系统亦不可将操作流程人为过度延长,前者是为节省单次请求时间,后者是为节省用户总点击时间。
6. 最疯狂的举动是,80%的用户读数据库请求发生在缓存内,也就是说,缓存系统自动为数据库绝大多数表建立内存镜像,一旦有写数据则更新所有相关缓存。

若单页逻辑过于复杂,而为了挽救这种复杂致缓存用得过多,通行的20ms单次页面执行时间的期望极可能落空。
因此,设计时多想想——没有缓存,怎么办?重建缓存的成本多大?
合理设计架构,减少单页逻辑单元是终极办法。