最新消息:Hello,word!

一个PHP小数据缓存类,可见的控制缓存文件数量。

程序分享 小竣 1509浏览 0评论

朋友写的一个文件缓存类,可以控制缓存碎片文件的数目。

前几天需要用到一个数据缓存的方法。

去网上找了一圈,发现大多数方法不是把所有的缓存数据都存到同一个文件。

或者就是把每条缓存记录都存到一个单独的文件。

然后,这些东西并不能达到我的要求。

于是想自己写一个自己用的缓存类。

PHP文件缓存。

参考ThinkPHP框架文件缓存的部分概念。

由于把所有的数据都存到一个缓存文件中,会导致文件越来越大,到了一定程度以后,反而会降低IO速度。

因为每次读写数据,都要把文件加载到内存,然后整理出来。在写入到文件。

而每个记录都存到单独的一个目录(ThinkPHP就是这样),确实挺好,

但是,时间久了,数据量很多的时候,单个目录下会有非常多的缓存文件。

磁盘IO效率又变得不高了,而且,单个目录下的文件数量是有限的。

我写的这个缓存类,会根据配置,把文件分散到一定数量的文件夹

而且能限制单个文件夹内的文件数量。

并且,这些数量是可以控制,可预见的。

数据达到一定量以后,肯定会保证只有这么多目录。这么多文件出现。

合理的控制数目,就可以达到尽可能高效的处理缓存了。

程序源码

Cache.class.php

/**
* 文件缓存系统
*
* 普通Cache缓存类,适用于大量零碎小数据缓存。大文件缓存不适用。
*
* 特点:缓存文件分目录储存,防止单个目录下文件过多导致IO效率变低。
* 		可以控制子目录数,文件数始终在一个可以预见的数量范围之内。
*
* 说明:
* @author 青石  http://www.qs5.org
* @version 0.1 完成于 2015/6/8
*
*/
class Cache {

	// 定义类默认设置
	static $Config = array(
		'Cache_Dir'			=> './Cache',	// 默认保存目录
		'File_Life'			=> 86400,		// 默认缓存有效时间 24小时 单位(s)
		'File_Suffix'		=> '.Cache.php',// 默认缓存文件名后缀 建议使用 .php 结尾
		'Group_Dir_Size'	=> -3,			// 文件夹分组命名字符节数	必须使用负数 设置为0则不分子文件夹
		'Group_File_Size'	=> 4,			// 文件名字命名字符节数	目录下文件数会限制在 16的N次方
		'Group_Dir_Depr'	=> '_',			// 分类多级目录替换符 为空则不分级
		);

	// 保存缓存信息
	static public function save($Name, $Data, $Time = 0){
		if(strlen($Name) < 1) return false;

		$path = self::_getPathName($Name);
		if(!self::_mkDir($path['dir'])){
			die('Error: Create a cache directory fails, check whether write permission.');
		}
		$Time = (($Time == 0) ? self::$Config['File_Life'] : $Time) + time();
		if(is_file($path['path'])){
			$file_str = file($path['path']);
			$file_str = $file_str[1];
			$file_info = unserialize($file_str);
		}
		$file_info[$path['hash']] = array('n' => $Name, 't' => $Time, 'd' => $Data);
		$file_text = "\n" . serialize($file_info);
		if(!file_put_contents($path['path'], $file_text, LOCK_EX)){
			return false;
		}
		return true;
	}

	// 读取缓存信息
	static public function read($Name){
		if(strlen($Name) < 1) return false;

		$path = self::_getPathName($Name);
		if(!is_file($path['path'])){
			return NULL;
		}
		$file_info = file($path['path']);
		$ret_info = unserialize($file_info[1]);
		$ret_info = $ret_info[$path['hash']];
		if($ret_info['t'] < time()){
			self::del($Name);
			return NULL;
		}
		return $ret_info['d'];
	}

	// 删除缓存信息
	static public function del($Name){
		if(strlen($Name) < 1) return false;

		$path = self::_getPathName($Name);
		if(!is_file($path['path'])){
			return true;
		}
		$file_info = file($path['path']);
		$ret_info = unserialize($file_info[1]);
		unset($ret_info[$path['hash']]);

		// 保存信息
		$file_text = "\n" . serialize($ret_info);
		if(!file_put_contents($path['path'], $file_text, LOCK_EX)){
			return false;
		}
		return true;
	}

	// 私有方法 循环创建目录
	static private function _mkDir($dir, $mode = 0666){
		if(is_dir($dir)){
			return true;
		}else if(!is_dir(dirname($dir)) && !self::_mkDir(dirname($dir), $mode)){
			return false;
		}
		return mkdir($dir, $mode);
	}

	// 私有方法 获取文件目录与关键字信息
	static private function _getPathName($Name){
		$path = explode('/', $Name);	// 分解名称
		if(count($path)<=1){
			$path = array('', $path[0]);
		}else{
			$path[0] = str_replace(self::$Config['Group_Dir_Depr'], '/', $path[0]) . '/';
		}
		$ret_path['hash'] = md5(strtolower($Name));
		$ret_path['dir'] = self::$Config['Cache_Dir'] . '/' . $path[0] . (self::$Config['Group_Dir_Size'] < 0 ? substr($ret_path['hash'], self::$Config['Group_Dir_Size']) . '/' : '');
		$ret_path['name'] = substr($ret_path['hash'], 0, self::$Config['Group_File_Size']) . self::$Config['File_Suffix'];
		$ret_path['path'] = $ret_path['dir'] . $ret_path['name'];
		return $ret_path;
	}
}
// 封装成快捷调用方法 S(); 可根据需要更改方法名
function S($Name, $Data = '', $time = 0){

	if(strlen($Name) < 1) return false;
	if($Data == ''){
		return Cache::read($Name);
	}elseif($Data == NULL){
		return Cache::del($Name);
	}else{
		return Cache::save($Name, $Data, $time);
	}
}

Demo.php

require "Cache.class.php";
header("Content-type: text/html; charset=utf-8");

// 设置示例 重置缓存目录
Cache::$Config['Cache_Dir'] = './.Cache';

// 使用方法示例
$data = S('TangShi_LiBai/ChuHe');

if(!$data){
	$data = array(
		'Name' => "锄禾",
		'Author' => "李白",
		'Contents' => "锄禾日当午,汗滴禾下土。谁知盘中餐,粒粒皆辛苦。",
		'Time' => time()
	);
	$ret = S('TangShi_LiBai/ChuHe', $data, 60);
	
}
print_r($data);

// 删除缓存信息
// S("TangShi_LiBai/ChuHe", NULL);

欢迎各路大牛优化代码,修改代码。优化后也请再发我一份。谢谢。

相关下载

转载请注明:小竣博客 » 一个PHP小数据缓存类,可见的控制缓存文件数量。