您的当前位置:首页正文

【转帖】文件缓存相关

2024-11-25 来源:个人技术集锦

 

 

文件缓存系统的设计与实现
2008-09-23 15:22

 

 

作者:刘晨光 QQ:64452627 MSN:liuchenguang_pro@hotmail.com 转载请注明出处 2008-09-23

 

 

 

 

 

 

 

 

一、项目背景
    
随着系统运营时间的增加,数据量与日俱增,数据库系统单张表的数量超过百万以上,数据的慢查询日志频频出现慢查询语句。根据观察得出以下规律:

 

大部分是查询的历史数据且重复率不高。

 

现行处理办法:

方法

可扩展性

复杂度

效果

查询优化

结构调整

Memcache


      

二、系统架构

 

4.使用
$sql = “SELECT id FROM table”;
$data = $db->getAll($sql);
$arr_post_list = array();
foreach($data as $record) {
    $cache_file = getLocalCacheFile($record[“id”]);
    require_once($cache_file);

}

5.
服务器部署
    
Web服务器与文件缓存服务器之间通过nfs mount进行通信, Web服务器与文件缓存服务器之间是一对多的关系,每个Web服务器上有多个mount点已解决单点故障问题。每次数据更新是更新到所有的cache节点上。

 

6.数据表id作为主索引

因为数据表id作为主索引,因此查询时至通过索引就可以得到所需数据。

 

 

四、测试
以一张记录总数为277376条数据的表为例进行测试。
测试工具webbench


结构比较

 

结构

SQL + Memcache( 前 n 页 )

SQL + File Cache( 所有数据 )

SQL

SELECT id,… FROM table …

SELECT id FROM table

      

       结果 (时长30)    speed(pages/min) transfer(bytes/sec)  

并发

speed

transfer

requets

slow log

speed

transfer

requets

slow log

1

170

221430

85

228

294333

114

5

272

354360

136

有 3

382

493089

191

100

242

134336

121

有 5

236

117174

118

500

196

141882

98

有 12

120

154856

60

1000

140

174381

70

有 23

146

154074

73


       
结论 :

       系统改造后的方案比改造前随并发量(或运行时长)的增加对数据库产生压力增长缓慢。


 

 

五、文件散列
散列结果相对均衡,都在9-10M之间

9.4M    ./cache/b8

9.8M    ./cache/7a

9.3M    ./cache/7c


 

六、问题与挑战
       1.
生成的缓存文件占用硬盘较大,未压缩处理时大致十倍于数据库。

2.把对数据库的压力转嫁到磁盘IO上,产生大量的随机读取,磁盘损害几率加大。

3.大量零星的小文件存储可能遇到linux inode问题。

4.合适的文件系统未测试证实。

 

说明:本方案测试用例非通用,需结合自身系统自行设置业务逻辑。

 

 

 

 

 

前言
在开发MooPHP的过程中,为了寻找更为高效的缓存方式,对两种最常用的缓存方式进行了测试。

PHP常用缓存方式
第一种,把需要缓存的数据进行处理,形成PHP可以直接执行的文件。在需要缓存数据的时候,通过include方式引入,并使用。
第二种,把需要的数据通过serialize函数序列化后直接保存到文件。在需要使用缓存数据的时候,通过反序列化读入文件内容并复制给需要的变量,然后使用。

原因分析
include方式读取缓存的时候,PHP需要执行几个过程
1.读取文件
2.解析所Include的文件
3.执行,给变量赋值

而serialize序列化方式读取缓存的时候:
1.读取数据
2.反序列化数据内容
3.给变量赋值

从以上内容对比的话,可能是由于解析PHP文件内的数组需要的时间超过unserialize反序列化数组的时间。如果你有兴趣可以查看《》:http://www.ccvita.com/163.html

< ?php

$t1 = gettimeofday();

for ($i = 0; $i < 10000; $i++){
include("CacheTest_IncludeData.php");
}

$t2 = gettimeofday();

echo ($t2['sec'] - $t1['sec']) * 1000 + ($t2['usec'] - $t1['usec']) / 1000 . "/n";

CacheTest_SerializeFile.php

< ?php

function read_cache($filename) {

if(@$fp = fopen($filename, 'r')) {
@$data = fread($fp,filesize($cachefile));
fclose($fp);
}
return $s;
}

$t1 = gettimeofday();

for ($i = 0; $i < 10000; $i++){
$x = read_cache("CacheTest_SerializeData.php");
$x_r = unserialize($x);
}

$t2 = gettimeofday();

echo ($t2['sec'] - $t1['sec']) * 1000 + ($t2['usec'] - $t1['usec']) / 1000 . "/n";

 

总结分析
第一种,include缓存的方式
优点:增加数据的保密性,和安全性,缓存内容不会被外界发现。
缺点:速度相对较慢。
用途:保存禁止系统外部得知的数据,比如web系统的设置,甚至MySQL信息等的保存

第二种,serialize序列化缓存的方式
优点:速度较快。
缺点:缓存系统文件路径一旦曝光,缓存内容会泄露。
用途:缓存最新文章,相关文章等不担心外部得知的数据的时候,可以使用这种方式。

 

 

 

 

权限问题:如果XML路径是很有规律的,并且可以被直接访问到,那么就没有什么权限和隐私可言了,一种比较直接有效的方法,就是通过HttpHandler来隐藏缓存的XML文件的真实路径,并且判断用户是否有权限看到。如果你担心XML文件路径可能被猜出来,那么可以将缓存文件禁止直接外部访问,或者对上面提到的XML文件命名方案进行改进:对于Post增加一个属性——缓存文件名,第一次创建时生成一个随机数作为文件名,如果后来帖子有修改,同时更新这个属性。

换皮肤问题:XSLT本身就可以很方便的实现换肤功能——每种皮肤一个XSLT文件即可,不过这样的一个问题就是需要对XSLT比较熟悉。如果要在传统的论坛换皮肤基础上实现这个功能,可以考虑一个折中的方案:将每个缓存后的Post的XML作为XML数据岛嵌入在帖子显示的位置,本身IE对XML数据岛就支持非常好,即使是FireFox之类不支持XML数据岛的浏览器(貌似是不支持的),也可以结合XSLT来做,这个XSLT只要解析显示帖子内容这部分就好了,相对难度小很多。

显示全文