Berkeley DB:网站数据缓存方案测试
January 28th, 2009 | by 超群.com | 知识共享署名-非商业性使用-相同方式共享,转载请保留链接。本博客所有原创文章采用知识共享署名-非商业性使用-相同方式共享,转载请保留链接http://chaoqun.17348.com/2009/01/bdb-cache/
做网站,好像大家都比较喜欢文件缓存,把那些读操作多写操作少的内容缓存成一个文件放服务器硬盘上,下次直接读取或者更新。针对每一个key缓存成一个文件,当需要缓存的内容多的时候,文件数也就相应的多,这么多文件的同步和备份都是大问题,数据的可靠性也无从保证。
可是为了”效率”,我们也忍了,但文件缓存的效率真的好吗?有没有更好的方案?当然,memcached是很好的解决方案,今天这里测试另外一种方案:使用Berkeley DB作为网站数据缓存方案。
测试环境:CentOS 5.2,Core2 T5500@ 1.66GHz,1.5G内存,Ext3文件系统,apache 2.2.3,php 5.2.8 with php_dba
数据初始化:为了不至于在一个目录下文件数目过多,文件缓存分了两级hash目录,初始化数据数10万条。
/** * 初始化缓存 * * @param int $limit */ function init_cache($limit = 100000) { $str = 'good good study,and day day up.'; $bdb = dba_open('./bdb.db', 'c', 'db4'); for ($i = 0; $i < $limit; $i++) { $data = str_repeat($str, rand(1,100)); dba_insert($i, $data, $bdb); $cache_file = get_cache_file($i); file_put_contents($cache_file, $data); } dba_close($bdb); } /** * 获得缓存文件 * * @param string $cache_key * @param string $md5_key * @return string */ function get_cache_file($cache_key, $md5_key = '9527') { $dir_md5 = md5($cache_key . $md5_key); $file_md5 = md5($cache_key); $dir = './cache/' . substr($dir_md5, 0, 2); is_dir($dir) || mkdir($dir); $dir .= '/' . substr($dir_md5, 2, 2); is_dir($dir) || mkdir($dir); return $dir . '/' . $file_md5 . '.txt'; }
同样的缓存内容,占用磁盘大小:
文件缓存:348.9MB
BDB缓存:296.5MB
BDB缓存占用磁盘空间要小一些。
测试程序尽可能的模拟真实环境,90%的读操作,10%的写操作,很多应用可能98%的读操作,2%的写操作,另外还模拟了一些新增缓存。
文件缓存测试程序代码:
/** * 文件缓存测试程序 */ require_once './common.php'; // 随机一个key $key = rand(0, 109999); $cache_file = get_cache_file($key); // 读写标记 $flag = rand(0,9); if (file_exists($cache_file) && 9 > $flag) { echo file_get_contents($cache_file); }else { file_put_contents($cache_file, str_repeat('learn from LeiFeng!', rand(1,100))); echo file_get_contents($cache_file); }
BDB缓存测试程序代码:
/** * BDB缓存测试程序 */ // 随机一个key $key = rand(0, 109999); // 读写标记 $flag = rand(0,9); $bdb = dba_popen('./bdb.db', 'w', 'db4'); $data = dba_fetch($key, $bdb); // dba_close($bdb); if ($data && 9 > $flag) { echo $data; }else { dba_replace($key, str_repeat('learn from Comrade LeiFeng!', rand(1,100)), $bdb); echo dba_fetch($key, $bdb); } dba_close($bdb);
文件缓存测试结果:
ab -n10000 -c200 http://127.0.0.1/labs/TestCache/file.php
Requests per second: 189.92 [#/sec] (mean)
Time per request: 1053.055 [ms] (mean)
Time per request: 5.265 [ms] (mean, across all concurrent requests)
BDB缓存测试结果:
ab -n10000 -c200 http://127.0.0.1/labs/TestCache/bdb.php
Requests per second: 220.69 [#/sec] (mean)
Time per request: 906.249 [ms] (mean)
Time per request: 4.531 [ms] (mean, across all concurrent requests)
反复测试了几次,文件缓存每秒大概能处理170~200个请求,BDB缓存每秒大概能处理190~230个请求,貌似BDB还比文件缓存要快一些,其实BDB还可以更快一些,我们在测试代码里面用了不管是读操作还是写操作都用了$bdb = dba_popen(‘./bdb.db’, ‘w’, ‘db4′);写的方式,其实我们很多的应用只是读操作,如果把BDB测试代码换成只有在写的时候才用写操作:
/** * BDB缓存测试程序 */ // 随机一个key $key = rand(0, 109999); // 读写标记 $flag = rand(0,9); $bdb = dba_popen('./bdb.db', 'r', 'db4'); $data = dba_fetch($key, $bdb); if ($data && 9 > $flag) { echo $data; }else { dba_close($bdb); $bdb = dba_popen('./bdb.db', 'w', 'db4'); dba_replace($key, str_repeat('learn from Comrade LeiFeng!', rand(1,100)), $bdb); echo dba_fetch($key, $bdb); dba_close($bdb); }
测试结果:
ab -n10000 -c200 http://127.0.0.1/labs/TestCache/bdb.php
Requests per second: 361.62 [#/sec] (mean)
Time per request: 553.068 [ms] (mean)
Time per request: 2.765 [ms] (mean, across all concurrent requests)
有点吓人,速度快要翻翻了。
后记:
php_dba扩展中建立数据库句柄,有dba_open和dba_popen两个函数,dba_popen建立的是持久连接,我在测试中发现使用dba_popen的性能要大大好于dba_open,测试中使用亦非常稳定。
其实memcachedb的核心还是BDB,引入了缓存和兼容memcached协议的socket接口,memcachedb当然会比单纯的BDB快,如果没办法用memcachedb,纯粹的BDB也是一种不错的方案,照测试看,各个方面比文件缓存都要好一些,当然,写频繁的操作可能要差些,因为存在文件锁的问题,换个思路想,写频繁缓存又有什么用呢。
Tags: Berkeley DB, cache
2 Responses to “Berkeley DB:网站数据缓存方案测试”
By david on Feb 28, 2009 | Reply
小文件cache居然比db慢,有点不解。
在我理解中,db打开和cache打开应该是一样的io操作,db还要进行索引,而cache不用。不知理解的对不对?
把ab测试换成在php脚本内的循环测试是否更可靠?
By 超群.com on Mar 1, 2009 | Reply
@david
当目录下文件数过多时,文件的定位会是个大问题,尤其都是小文件,我猜测可能是这一个原因。
php内的循环测试没有多大的意义,ab可以模拟并发访问的情况,更有实际意义。
使用文件cache还有一个更大的问题是文件的可靠性和一致性没法保证。我们就发现会出现cache写错误的情况,尤其当你的磁盘是通过nfs mount过来的。