php操作大缓存的存储与读取
2015-10-12 18:34
615 查看
什么是大缓存,按照我的理解,就是超过1MB的缓存都可以称之为大缓存了,频繁的读取超过此大小的文件去进行处理,不管从做项目还是做产品的角度,似乎都是不可理解的。
从数据缓存的角度来说,缓存分为数据缓存和网页缓存,网页缓存是一次性读取,一次性输出的,这个是没有办法,而且也很少看到那个网站的源代码体积几百K的,更不用说超过1024k了;剩下的就是数据缓存,缓存的数据类型无非就是字符串、数组、json、序列化等,一般序列化和JSON数据也是数组转换过来的,我觉得也太麻烦了。如果你真的有超过1MB的数据需要缓存,但是你还在内存中对数据进行格式化,我觉得你完全是要逆天了。
我用一个简单的案例来说说我这个大缓存的存储与读取。
案例:采集
现在采集可以设置从多少页采集到多少页,那么我是不是可以先获取所有的内容页,将内容页网址全部缓存后一条条处理?如果你没有巧妙的读取缓存的思想,而是用平常的一次性读取、一次性处理的思想的话,那绝对要悲剧。几千几万条数据放在缓存里面,也会被你骂成13B了。
现在开始构造缓存,我构造的缓存如下:
不得不解释一下,<?php是防下载,后面的十位数字是表示文件指针移动到哪里来了,是从后面的数据开始算起的,构造代码如下(文件大致为80MB):
下面讲讲整个数据的读取原理:
首先将上次缓存读取的指针位置读取出来,读取完之后,指针的位置应该为16
因为我存储的指针位置恰好是减去了16存储的,那么我在获取到指针位置后,就可以直接跳到指定存储指针
设置好要读取的行,每遇到一个\r,则计数器+1,一直读取完想要的行数后,跳出
获取目前的指针位置,然后将目前的指针位置存储到第6到16之间
当指针移动到文件尾部的时候,或返回false,也可以同时删除缓存。
我已经将读取处理过程写成了一个函数:
效率测试代码(不要使用你2B的行为来个for循环,完全不符合处理实际需要):
我将指针移动到263563了,读取效率为:
消耗的内存真是惊人,惊人的小
从数据缓存的角度来说,缓存分为数据缓存和网页缓存,网页缓存是一次性读取,一次性输出的,这个是没有办法,而且也很少看到那个网站的源代码体积几百K的,更不用说超过1024k了;剩下的就是数据缓存,缓存的数据类型无非就是字符串、数组、json、序列化等,一般序列化和JSON数据也是数组转换过来的,我觉得也太麻烦了。如果你真的有超过1MB的数据需要缓存,但是你还在内存中对数据进行格式化,我觉得你完全是要逆天了。
我用一个简单的案例来说说我这个大缓存的存储与读取。
案例:采集
现在采集可以设置从多少页采集到多少页,那么我是不是可以先获取所有的内容页,将内容页网址全部缓存后一条条处理?如果你没有巧妙的读取缓存的思想,而是用平常的一次性读取、一次性处理的思想的话,那绝对要悲剧。几千几万条数据放在缓存里面,也会被你骂成13B了。
现在开始构造缓存,我构造的缓存如下:
<?php 0000000000http://www.xxxx.cc/detail/?1.html http://www.xxxx.cc/detail/?2.html http://www.xxxx.cc/detail/?3.html http://www.xxxx.cc/detail/?4.html http://www.xxxx.cc/detail/?5.html
不得不解释一下,<?php是防下载,后面的十位数字是表示文件指针移动到哪里来了,是从后面的数据开始算起的,构造代码如下(文件大致为80MB):
$file_handle = fopen("./file.php", "w+"); fwrite($file_handle, '<?php 0000000000'); for ($index = 1; $index <= 2000000; $index++) { fwrite($file_handle, 'http://www.xxxxx.cc/detail/?'.$index.'.html'."\r"); } fclose($file_handle);
下面讲讲整个数据的读取原理:
首先将上次缓存读取的指针位置读取出来,读取完之后,指针的位置应该为16
因为我存储的指针位置恰好是减去了16存储的,那么我在获取到指针位置后,就可以直接跳到指定存储指针
设置好要读取的行,每遇到一个\r,则计数器+1,一直读取完想要的行数后,跳出
获取目前的指针位置,然后将目前的指针位置存储到第6到16之间
当指针移动到文件尾部的时候,或返回false,也可以同时删除缓存。
我已经将读取处理过程写成了一个函数:
//按行读取大文件 function BF($file, $line = 10, $offset = false){ if (is_file($file)) { $fp = fopen($file, "r+"); if ($offset === false) { fseek($fp, 6, SEEK_CUR); $num = ''; for($i=0;$i<10;$i++){ fseek($fp, 0, SEEK_CUR); $num .= fgetc($fp); } $offset = (int)$num; } fseek($fp, $offset, SEEK_CUR); $return = array(); $readyline = 0; while (!feof($fp)){ fseek($fp, 0, SEEK_CUR); $_tmp= fgetc($fp); if ($_tmp == "\r") { $readyline += 1; } if ($readyline >= $line) { break; } if (!isset($return[$readyline])) { $return[$readyline] = ''; } $return[$readyline] .= $_tmp; } $offset = ftell($fp); fseek($fp, 6-$offset, SEEK_CUR); $offset = str_pad($offset-16, 10, 0, STR_PAD_LEFT); for($i=0;$i<10;$i++){ fseek($fp, 0, SEEK_CUR); fwrite($fp, $offset{$i}); } fclose($fp); return $return; } else { throw new Exception($file.'::不存在'); } }
效率测试代码(不要使用你2B的行为来个for循环,完全不符合处理实际需要):
$startTime = microtime(true); $startMem = memory_get_usage(); $print = BF('./file.php', 10); print_r($print); echo '<br />runtime:'.round((microtime(true) - $startTime)*1000, 4).'ms<br />'; $size = memory_get_usage()-$startMem; $unit=array('b','kb','mb','gb','tb','pb'); echo round($size/pow(1024,($i=floor(log($size,1024)))),2).' '.$unit[$i].'<br />';
我将指针移动到263563了,读取效率为:
runtime:5.5821ms memory:2.67 kb
消耗的内存真是惊人,惊人的小
相关文章推荐
- 99 thinkphp ERR_CONTENT_DECODING_FAILED
- error C2664: “CSerialPort::InitPort”: 不能将参数 1 从“CCom_TestDlg *const ”转换为“HWND”
- PHP常用函数
- php操作rabbitmq教程
- PHP引用问题
- PHP常用方法
- thinkphp--标签库
- [php] 定时执行任务
- PHP几个几十个G大文件数据统计并且排序处理
- 如何使用 APM 搞定 PHP 应用的性能优化?
- 如何使用 APM 搞定 PHP 应用的性能优化?
- 4000 PHP函数 -ctype_alnum,
- cron 执行php文件
- 如何修改WAMP中mysql默认空密码&重新登录phpmyadmin
- 解析crontab php自动运行的方法
- ubuntu 安装 phpstorm
- PHP之php_curl.dll错误解决方法
- FileInputStream与FileOutputStream类
- PhpExcel中文帮助手册|PhpExcel使用方法
- 用PHP正则表达式匹配中文