php 高效缓存类,100%并发无误, PHP高效文本缓存类.

一个key对应一行记录, 首先读取首行的配置文件, 得到key对应的行数, 然后取之.

写入时同样会计算key对应的行数, 有则更新, 无则增加.

fopen + flock控制并发.

1.[代码]高效的文本缓存.

$old = sprintf('%1.4f', memory_get_peak_usage() / 1024) .' KB';

class caches{

public $keep_time = 3600;

public $file_path = './cache.txt';

private $handle = null;

private $time = 0;

public function __construct(){

$this->time = time();

}

public function read($key, $keep_time=0){

# 取得第一行. 判断过期, 不存在, 异常情况, 影响返回值即可. 返回值决定write方法的调用.

$keep_time === 0 && $keep_time = $this->keep_time;

$list = $this->__get_one();

# 是否更新判断.

$check = true;

if(!$list[$key])

$check = false;

if($check && (time() - $list[$key]['t']) >= $keep_time)

$check = false;

# 取得第几行数据.

$line = $list[$key]['l']+0;

$i = 1;

$data = '';

if($this->handle){

while(!feof($this->handle)){

if($i === $line){

$data = fgets($this->handle);

}else{

// TODO: 有没有好办法跳过这步...

fgets($this->handle);

}

$i ++;

}

}

# 无论如何都保障数据为数组返回.

if($data){

$data = $this->__data_parse($data,'DECODE');

}

!$data && $data = array();

return $data;

}

public function write($key, $val){

# 取得第一行. 判断key是否已经存在了..

$list = $this->__get_one();

# 什么情况下可以写入.

if($list[$key]){

# 已经过期的情况下. write函数被调用后, 不管如何都当作过期.

$list[$key]['t'] = $this->time;

$list['end'] = $list[$key]['l'];

}else{

$list[$key] = array('t'=>$this->time,'l'=>($list['end']+1));

$list['end'] = $list[$key]['l'];

}

# 数据加密处理后再传给__write. $list['end'] 表示更新哪一行.

return $this->__write($list['end'], $this->__data_parse($val), serialize($list));

}

private function __get_one(){

$this->__read_fopens();

if(!$this->handle)

return array();

$list = array();

if($seria = rtrim(fgets($this->handle))){

$list = unserialize($seria);

unset($seria);

}

!$list && $list = array();

return $list;

}

private function __data_parse($data, $cls='ENCODE'){

# $State 参数以减少is_string, count两函数的调用.

if($cls === 'ENCODE'){

# 一定要返回无换行的一行. 切记

# gzcompress 非常占内存, 只是写入时执行.

$data = base64_encode(gzcompress(serialize($data),9));

}else{

$data = unserialize(gzuncompress(base64_decode(rtrim($data))));

if($State === false && count($data) === 1 && isset($data[0]) === true){

$data = $data[0];

}

}

return $data;

}

private function __write($line, $data, $firstline){

$savedata = array();

$line +=0;

$i = 1;

$savedata[0] = $firstline;

if($this->handle){

while(!feof($this->handle)){

$savedata[$i] = rtrim(fgets($this->handle));

if($i === $line){

$savedata[$i]= $data;

}

$i ++;

}

}

if(!$savedata[$line])

$savedata[$line] = $data;

if($this->handle)

$this->__closes();

# 重新写入文件.

if(!$fp = fopen($this->file_path, 'wb'))

if(!$fp = fopen($this->file_path, 'wb'))

if(!$fp = fopen($this->file_path, 'wb'))

if(!$fp = fopen($this->file_path, 'wb'))

if(!$fp = fopen($this->file_path, 'wb'))

return 0;

flock($fp, LOCK_EX | LOCK_NB);

$ints = 0;

//$ints = fwrite($fp, implode(PHP_EOL, $savedata));

foreach($savedata AS $key => $val){

if($key === 0){

$ints += fwrite($fp,$val);

}else{

$ints += fwrite($fp,PHP_EOL.$val);

}

if($key === 0 && $ints <= 0)

break;

}

unset($savedata);

flock($fp, LOCK_UN);

fclose($fp);

return $ints;

}

private function __read_fopens(){

$cls = 'rb';

if($this->handle)

$this->__closes();

if(is_file($this->file_path) === false)

return false;

if(!$this->handle = fopen($this->file_path,$cls))

if(!$this->handle = fopen($this->file_path,$cls))

if(!$this->handle = fopen($this->file_path,$cls))

if(!$this->handle = fopen($this->file_path,$cls))

if(!$this->handle = fopen($this->file_path,$cls))

$this->handle = null;

if($this->handle)

flock($this->handle,LOCK_EX | LOCK_NB);

}

private function __closes(){

if($this->handle){

flock($this->handle, LOCK_UN);

fclose($this->handle);

$this->handle = null;

}

}

}

########################################### 调用代码 #########################################

set_time_limit(0);

$atime = microtime(true);

$obj = new caches();

$read = 1; // (0 / 1) 写入或者读, 测试效果.

$size = 10000; // 10K

$arr = range(1,100); // 首次要快得多, 200:1秒, 1000:11秒

foreach($arr AS $val){

if($read == 0){

// 写入测试.

$ints = $obj->write('key'.$val,array('key'=>str_repeat('A',$size)));

echo 'key'.$val.' write size: '. ($ints / 1000).' KB
';

}else{

// 读缓存测试.

$ints = $obj->read('key'.$val);

echo 'key'.$val.' read size: '. strlen($ints['key']) / 1000 .' KB
';

}

}

#################################### 以下代码为监控作用 ####################################

echo '
执行时间: ';

echo sprintf('%1.4f',microtime(true) - $atime).' 秒';

echo '


内存监控: ';

echo $new = sprintf('%1.4f', memory_get_peak_usage() / 1024) .' KB';

echo '


原始内存: ';

echo $old;

echo '


增加内存: ';

echo sprintf('%1.4f',$new - $old) .' KB';

exit();

?>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值