tar xvzf db-6.tar.gz
cd db-6/
cd build_unix/
../dist/configure
make
make install
$path
,
string$mode
[,
string$handler
)
$full_info
= false ] )
php -r "var_dump(dba_handlers());"
array(5) {
[0]=>
string(3) "cdb"
[1]=>
string(8) "cdb_make"
[2]=>
string(3) "db4"
[3]=>
string(7) "inifile"
[4]=>
string(8) "flatfile"
}
php --re dba
Extension [ <persistent> extension #31 dba version <no_version> ] {
- INI {
Entry [ dba.default_handler <ALL> ]
Current = 'flatfile'
}
}
- Functions {
Function [ <internal:dba> function dba_open ] {
- Parameters [4] {
Parameter #0 [ <required> $path ]
Parameter #1 [ <required> $mode ]
Parameter #2 [ <optional> $handlername ]
Parameter #3 [ <optional> $... ]
}
}
Function [ <internal:dba> function dba_popen ] {
- Parameters [4] {
Parameter #0 [ <required> $path ]
Parameter #1 [ <required> $mode ]
Parameter #2 [ <optional> $handlername ]
Parameter #3 [ <optional> $... ]
}
}
Function [ <internal:dba> function dba_close ] {
- Parameters [1] {
Parameter #0 [ <required> $handle ]
}
}
Function [ <internal:dba> function dba_delete ] {
- Parameters [2] {
Parameter #0 [ <required> $key ]
Parameter #1 [ <required> $handle ]
}
}
Function [ <internal:dba> function dba_exists ] {
- Parameters [2] {
Parameter #0 [ <required> $key ]
Parameter #1 [ <required> $handle ]
}
}
Function [ <internal:dba> function dba_fetch ] {
- Parameters [3] {
Parameter #0 [ <required> $key ]
Parameter #1 [ <required> $skip ]
Parameter #2 [ <optional> $handle ]
}
}
Function [ <internal:dba> function dba_insert ] {
- Parameters [3] {
Parameter #0 [ <required> $key ]
Parameter #1 [ <required> $value ]
Parameter #2 [ <required> $handle ]
}
}
Function [ <internal:dba> function dba_replace ] {
- Parameters [3] {
Parameter #0 [ <required> $key ]
Parameter #1 [ <required> $value ]
Parameter #2 [ <required> $handle ]
}
}
Function [ <internal:dba> function dba_firstkey ] {
- Parameters [1] {
Parameter #0 [ <required> $handle ]
}
}
Function [ <internal:dba> function dba_nextkey ] {
- Parameters [1] {
Parameter #0 [ <required> $handle ]
}
}
Function [ <internal:dba> function dba_optimize ] {
- Parameters [1] {
Parameter #0 [ <required> $handle ]
}
}
Function [ <internal:dba> function dba_sync ] {
- Parameters [1] {
Parameter #0 [ <required> $handle ]
}
}
Function [ <internal:dba> function dba_handlers ] {
- Parameters [1] {
Parameter #0 [ <optional> $full_info ]
}
}
Function [ <internal:dba> function dba_list ] {
- Parameters [0] {
}
}
Function [ <internal:dba> function dba_key_split ] {
- Parameters [1] {
Parameter #0 [ <required> $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); //写入BDB
$cache_file = get_cache_file($i);
file_put_contents($cache_file, $data); //写入file
}
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/bhp
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', <strong>'r</strong>', 'db4'); <strong>//读时 用r,速度翻倍</strong>
$data = dba_fetch($key, $bdb);
if ($data && 9 > $flag)
{
echo $data;
}else
{
dba_close($bdb);
$bdb = dba_popen('./bdb.db', '<strong>w</strong>', 'db4'); <strong>//写时 用 w</strong>
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.phpTime 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也是一种不错的方案,照测试看,各个方面比文件缓存都要好一些,当然,写频繁的操作可能要差些,因为存在文件锁的问题,换个思路想,写频繁缓存又有什么用呢。