六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 971|回复: 0

PHP文件缓存实现

[复制链接]
 楼主| 发表于 2015-12-28 17:53:27 | 显示全部楼层 |阅读模式
PHP文件缓存实现
        有些时候,我们不希望使用redis等第三方缓存,使得系统依赖于IT论坛服务。这时候,文件缓存会是一个不错的选择。
        我们需要文件缓存实现哪些共更能:
        功能实现:get、set、has、increment、decrement、delete、flush
        能够在较短的时间内返回数据
        支持key过期

        原理:
        为了避免一个文件内的数据过大,造成读取文件的时候延迟较高,我们采用一个key-value一个文件的方式实现存储结构。
        为了支持key过期,我们需要把expire数据写入到文件中,所以需要对写入的数据进行序列化处理
        为了能够快速的定位到文件路径,我们采用hash算法一次计算出文件位置
        实现:
  1. <?php

  2. /**
  3. * Created by PhpStorm.
  4. * User: Jenner
  5. * Date: 2015/5/15
  6. * Time: 15:40
  7. */
  8. class LeoFileCache implements LeoCacheInterface
  9. {

  10.     /**
  11.      * 缓存目录
  12.      * @var
  13.      */
  14.     private $cache_dir;

  15.     /**
  16.      * @param $cache_dir
  17.      * @throws Exception
  18.      */
  19.     public function __construct($cache_dir)
  20.     {
  21.         $this->cache_dir = $cache_dir;
  22.         if (!is_dir($cache_dir)) {
  23.             $make_dir_result = mkdir($cache_dir, 0755, true);
  24.             if ($make_dir_result === false) throw new Exception('Cannot create the cache directory');
  25.         }
  26.     }


  27.     /**
  28.      * 根据key获取值,会判断是否过期
  29.      * @param $key
  30.      * @return mixed
  31.      */
  32.     public function get($key)
  33.     {
  34.         $cache_data = $this->getItem($key);
  35.         if ($cache_data === false || !is_array($cache_data)) return false;

  36.         return $cache_data['data'];
  37.     }

  38.     /**
  39.      * 添加或覆盖一个key
  40.      * @param $key
  41.      * @param $value
  42.      * @param $expire
  43.      * @return mixed
  44.      */
  45.     public function set($key, $value, $expire = 0)
  46.     {
  47.         return $this->setItem($key, $value, time(), $expire);
  48.     }

  49.     /**
  50.      * 设置包含元数据的信息
  51.      * @param $key
  52.      * @param $value
  53.      * @param $time
  54.      * @param $expire
  55.      * @return bool
  56.      */
  57.     private function setItem($key, $value, $time, $expire)
  58.     {
  59.         $cache_file = $this->createCacheFile($key);
  60.         if ($cache_file === false) return false;

  61.         $cache_data = array('data' => $value, 'time' => $time, 'expire' => $expire);
  62.         $cache_data = json_encode($cache_data);

  63.         $put_result = file_put_contents($cache_file, $cache_data);
  64.         if ($put_result === false) return false;

  65.         return true;
  66.     }

  67.     /**
  68.      * 创建缓存文件
  69.      * @param $key
  70.      * @return bool|string
  71.      */
  72.     private function createCacheFile($key)
  73.     {
  74.         $cache_file = $this->path($key);
  75.         if (!file_exists($cache_file)) {
  76.             $directory = dirname($cache_file);
  77.             if (!is_dir($directory)) {
  78.                 $make_dir_result = mkdir($directory, 0755, true);
  79.                 if ($make_dir_result === false) return false;
  80.             }
  81.             $create_result = touch($cache_file);
  82.             if ($create_result === false) return false;
  83.         }

  84.         return $cache_file;
  85.     }

  86.     /**
  87.      * 判断Key是否存在
  88.      * @param $key
  89.      * @return mixed
  90.      */
  91.     public function has($key)
  92.     {
  93.         $value = $this->get($key);
  94.         if ($value === false) return false;

  95.         return true;
  96.     }

  97.     /**
  98.      * 加法递增
  99.      * @param $key
  100.      * @param int $value
  101.      * @return mixed
  102.      */
  103.     public function increment($key, $value = 1)
  104.     {
  105.         $item = $this->getItem($key);
  106.         if ($item === false) {
  107.             $set_result = $this->set($key, $value);
  108.             if ($set_result === false) return false;
  109.             return $value;
  110.         }

  111.         $check_expire = $this->checkExpire($item);
  112.         if ($check_expire === false) return false;

  113.         $item['data'] += $value;

  114.         $result = $this->setItem($key, $item['data'], $item['time'], $item['expire']);
  115.         if ($result === false) return false;

  116.         return $item['data'];
  117.     }

  118.     /**
  119.      * 减法递增
  120.      * @param $key
  121.      * @param int $value
  122.      * @return mixed
  123.      */
  124.     public function decrement($key, $value = 1)
  125.     {
  126.         $item = $this->getItem($key);
  127.         if ($item === false) {
  128.             $value = 0 - $value;
  129.             $set_result = $this->set($key, $value);
  130.             if ($set_result === false) return false;
  131.             return $value;
  132.         }

  133.         $check_expire = $this->checkExpire($item);
  134.         if ($check_expire === false) return false;

  135.         $item['data'] -= $value;

  136.         $result = $this->setItem($key, $item['data'], $item['time'], $item['expire']);
  137.         if ($result === false) return false;

  138.         return $item['data'];
  139.     }

  140.     /**
  141.      * 删除一个key,同事会删除缓存文件
  142.      * @param $key
  143.      * @return mixed
  144.      */
  145.     public function delete($key)
  146.     {
  147.         $cache_file = $this->path($key);
  148.         if (file_exists($cache_file)) {
  149.             $unlink_result = unlink($cache_file);
  150.             if ($unlink_result === false) return false;
  151.         }

  152.         return true;
  153.     }

  154.     /**
  155.      * 清楚所有缓存
  156.      * @return mixed
  157.      */
  158.     public function flush()
  159.     {
  160.         return $this->delTree($this->cache_dir);
  161.     }

  162.     /**
  163.      * 递归删除目录
  164.      * @param $dir
  165.      * @return bool
  166.      */
  167.     function delTree($dir)
  168.     {
  169.         $files = array_diff(scandir($dir), array('.', '..'));
  170.         foreach ($files as $file) {
  171.             (is_dir("$dir/$file")) ? $this->delTree("$dir/$file") : unlink("$dir/$file");
  172.         }
  173.         return rmdir($dir);
  174.     }

  175.     /**
  176.      * 根据key获取缓存文件路径
  177.      *
  178.      * @param  string $key
  179.      * @return string
  180.      */
  181.     protected function path($key)
  182.     {
  183.         $parts = array_slice(str_split($hash = md5($key), 2), 0, 2);
  184.         return $this->cache_dir . '/' . implode('/', $parts) . '/' . $hash;
  185.     }

  186.     /**
  187.      * 获取含有元数据的信息
  188.      * @param $key
  189.      * @return bool|mixed|string
  190.      */
  191.     protected function getItem($key)
  192.     {
  193.         $cache_file = $this->path($key);
  194.         if (!file_exists($cache_file) || !is_readable($cache_file)) {
  195.             return false;
  196.         }

  197.         $cache_data = file_get_contents($cache_file);
  198.         if (empty($cache_data)) return false;
  199.         $cache_data = json_decode($cache_data, true);
  200.         if ($cache_data) {
  201.             $check_expire = $this->checkExpire($cache_data);
  202.             if ($check_expire === false) {
  203.                 $this->delete($key);
  204.                 return false;
  205.             }
  206.         }

  207.         return $cache_data;
  208.     }

  209.     /**
  210.      * 检查key是否过期
  211.      * @param $cache_data
  212.      * @return bool
  213.      */
  214.     protected function checkExpire($cache_data)
  215.     {
  216.         $time = time();
  217.         $is_expire = intval($cache_data['expire']) !== 0 && (intval($cache_data['time']) + intval($cache_data['expire']) < $time);
  218.         if ($is_expire) return false;

  219.         return true;
  220.     }
  221. }
复制代码
http://www.huyanping.cn/php%E6%96%87%E4%BB%B6%E7%BC%93%E5%AD%98%E5%AE%9E%E7%8E%B0/


PHP文件缓存实现

该会员没有填写今日想说内容.
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表