За последние 24 часа нас посетили 18270 программистов и 1642 робота. Сейчас ищут 1470 программистов ...

Работа с кешей

Тема в разделе "Решения, алгоритмы", создана пользователем Ensiferum, 6 апр 2012.

  1. Ensiferum

    Ensiferum Активный пользователь

    С нами с:
    11 июл 2010
    Сообщения:
    1.292
    Симпатии:
    0
    Адрес:
    из секты поклонников Нео
    Натакал класс для работы с кешем. Класс использует основные операции (get, set, inc, dec, exists, delete). Плюс класса в том, что использует разные системы кеширования и расширяем (не помню какой паттерн). На данный момент работает с xCache, eAccelerator, APC

    Код (Text):
    1. <?php
    2. /**
    3.  *Класс, реализующий API для доступа к разным видам кэша
    4.  */
    5. class cache {
    6.     /**
    7.      * Используемый кэш
    8.      * @var string
    9.      */
    10.     private $_cache_type = 'auto';
    11.  
    12.     /**
    13.      * Указатель на используемый класс с кэшем
    14.      * @var object
    15.      */
    16.     private $_cache = null;
    17.     /**
    18.      * Префикс для ключей
    19.      * @var string
    20.      */
    21.     private $_prefix = '';
    22.  
    23.     /**
    24.      * Проверка возможности кэширования
    25.      *
    26.      * @return boolean
    27.      */
    28.     public static function isEnable() {
    29.         $cache_systems = array();
    30.         if (function_exists('eaccelerator_get'))
    31.             $cache_systems[] = 'eaccelerator';
    32.  
    33.         if (function_exists('apc_fetch'))
    34.             $cache_systems[] = 'apc';
    35.  
    36.         if (function_exists('xcache_get'))
    37.             $cache_systems[] = 'xcache';
    38.  
    39.         if (class_exists('Memcache'))
    40.             $cache_systems[] = 'memcache';
    41.  
    42.         return (sizeof($cache_systems)) ? $cache_systems : false;
    43.     }
    44.  
    45.     /**
    46.      * Конструктор класса
    47.      *
    48.      * @param array $options - ассоциативный массив с опциями для выбора кеша и настроек
    49.      * @return boolean - результат инициализации кеша
    50.      */
    51.     public function __construct($options = null) {
    52.         $required_cache = isset($options['cache']) ? : $this->_cache_type;
    53.  
    54.         if ($cache_systems = $this->isEnable()) {
    55.             if ($required_cache == 'auto')
    56.                 $this->_cache_type = array_shift($cache_systems); // первое значение в списке
    57.             else if (in_array($required_cache, $cache_systems))
    58.                 $this->_cache_type = $required_cache;
    59.             else
    60.                 return false;
    61.         } else
    62.             return false;
    63.  
    64.         if (!empty($options['prefix']))
    65.             $this->_prefix = $options['prefix'];
    66.        
    67.         $this->_cache = new $this->_cache_type($options);
    68.         return ($this->_cache) ? true : false;
    69.     }
    70.  
    71.     public function __destruct() {
    72.         $this->_cache->__destruct();
    73.     }
    74.  
    75.     /**
    76.      * Получение значения
    77.      *
    78.      * @param string $key
    79.      * @return mixed
    80.      */
    81.     public function get($key) {
    82.         return $this->_cache->get($this->_prefix . $key);
    83.     }
    84.  
    85.     /**
    86.      * Установка значения
    87.      *
    88.      * @param string $key - ключ
    89.      * @param mixed $data - данные
    90.      * @param int $ttl - время жизни
    91.      */
    92.     public function set($key, &$data, $ttl = 3600) {
    93.         return $this->_cache->set($this->_prefix . $key, &$data, $ttl);
    94.     }
    95.  
    96.     /**
    97.      * Удаление ключа
    98.      *
    99.      * @param string $key
    100.      * @return boolean
    101.      */
    102.     public function delete($key) {
    103.         return $this->_cache->delete($this->_prefix . $key);
    104.     }
    105.  
    106.     /**
    107.      * Проверка ключа на существование
    108.      *
    109.      * @param string $key
    110.      * @return boolean
    111.      */
    112.     public function exists($key) {
    113.         return $this->_cache->exists($this->_prefix . $key);
    114.     }
    115.    
    116.     /**
    117.      * Инкремент данных
    118.      *
    119.      * @param string $key
    120.      * @param int $val
    121.      */
    122.     public function inc($key, $val = 1) {
    123.         $this->_cache->inc($this->_prefix . $key, $val);
    124.     }
    125.    
    126.     /**
    127.      * Декремент данных
    128.      *
    129.      * @param string $key
    130.      * @param int $val
    131.      */
    132.     public function dec($key, $val = 1) {
    133.         $this->_cache->dec($this->_prefix . $key, $val);
    134.     }
    135. }
    136.  
    137. /**
    138.  * Обертка для кэшей
    139.  */
    140. class cache_container {
    141.  
    142.     public function __construct() {
    143.        
    144.     }
    145.  
    146.     public function __destruct() {
    147.        
    148.     }
    149.  
    150.     public function exists() {
    151.         return false;
    152.     }
    153.  
    154.     public function get() {
    155.         return false;
    156.     }
    157.  
    158.     public function set() {
    159.         return false;
    160.     }
    161.  
    162.     public function delete() {
    163.         return false;
    164.     }
    165.  
    166.     public function inc() {
    167.         return false;
    168.     }
    169.  
    170.     public function dec() {
    171.         return false;
    172.     }
    173.  
    174. }
    175. /**
    176.  * xCache
    177.  */
    178. class xcache extends cache_container {
    179.  
    180.     public function get($key) {
    181.         return xcache_get($key);
    182.     }
    183.  
    184.     public function set($key, &$data, $ttl) {
    185.         return xcache_set($key, $data, $ttl);
    186.     }
    187.  
    188.     public function delete($key) {
    189.         return xcache_unset($key);
    190.     }
    191.  
    192.     public function exists($key) {
    193.         return xcache_isset($key);
    194.     }
    195.  
    196.     public function inc($key, $val = 1) {
    197.         xcache_inc($key, $val);
    198.     }
    199.  
    200.     public function dec($key, $val = 1) {
    201.         xcache_dec($key, $val);
    202.     }
    203.  
    204. }
    205.  
    206. /**
    207.  * APC
    208.  */
    209. class apc extends cache_container {
    210.  
    211.     public function get($key) {
    212.         return apc_fetch($key);
    213.     }
    214.  
    215.     public function set($key, &$data, $ttl) {
    216.         return apc_store($key, $data, $ttl);
    217.     }
    218.  
    219.     public function delete($key) {
    220.         return apc_delete($key);
    221.     }
    222.  
    223.     public function exists($key) {
    224.         return apc_exists($key);
    225.     }
    226.  
    227.     public function inc($key, $val = 1) {
    228.         apc_inc($key, $val);
    229.     }
    230.  
    231.     public function dec($key, $val = 1) {
    232.         apc_dec($key, $val);
    233.     }
    234.  
    235. }
    236.  
    237. /**
    238.  * eAccelerator
    239.  */
    240. class eaccelerator extends cache_container {
    241.  
    242.     public function get($key) {
    243.         return eaccelerator_get($key);
    244.     }
    245.  
    246.     public function set($key, &$data, $ttl = 0) {
    247.         return eaccelerator_put($key, $data, $ttl);
    248.     }
    249.  
    250.     public function delete($key) {
    251.         return eaccelerator_rm($key);
    252.     }
    253.  
    254.     public function exists($key) {
    255.         return ($this->get($key)) ? true : false;
    256.     }
    257.  
    258.     public function inc($key, $val = 1) {
    259.         $this->set($key, $this->get($key) + $val);
    260.     }
    261.  
    262.     public function dec($key, $val = 1) {
    263.         $this->set($key, $this->get($key) - $val);
    264.     }
    265.  
    266. }
    Потом задумался над хранением сессий в кеше и написал следующий класс:
    Код (Text):
    1. <?php
    2. /**
    3.  * Хранение сессий в кэше
    4.  *
    5.  * Использование:
    6.  * CacheSessionHandler::instance();
    7.  * session_start();
    8.  */
    9. class cacheSessionHandler {
    10.  
    11.     private static $cache;
    12.     private static $ttl;
    13.    
    14.     public static function instance() {
    15.         static $self = false;
    16.         if (false === $self) {
    17.             $self = new cacheSessionHandler();
    18.         }
    19.  
    20.         return $self;
    21.     }
    22.  
    23.     private function __construct() {
    24.         session_set_save_handler(array(__CLASS__, 'open'), array(__CLASS__, 'close'), array(__CLASS__, 'read'), array(__CLASS__, 'write'), array(__CLASS__, 'destroy'), array(__CLASS__, 'gc'));
    25.         self::$cache = new cache();
    26.         self::$ttl = (int) get_cfg_var('session.gc_maxlifetime');
    27.     }
    28.  
    29.     public function __destruct() {
    30.         session_write_close();
    31.     }
    32.  
    33.     public static function open($save_path, $session_name) {
    34.         return true;
    35.     }
    36.  
    37.     public static function close() {
    38.         return true;
    39.     }
    40.  
    41.     public static function read($session_id) {
    42.         return self::$cache->get('session/' . $session_id);
    43.     }
    44.  
    45.     public static function write($session_id, $session_data) {
    46.         return self::$cache->set('session/' . $session_id, $session_data, self::$ttl);
    47.     }
    48.  
    49.     public static function destroy($session_id) {
    50.         self::$cache->delete('session/' . $session_id);
    51.         return true;
    52.     }
    53.  
    54.     public static function gc($max_lifetime) {
    55.         return true;
    56.     }
    57.  
    58. }
    В случае с memcache всё было бы ещё проще - две строки в php.ini сменить. В планах допиливание класса под работу с memcache.

    Интересно Ваше мнение

    Добавлено спустя 26 минут 5 секунд:
    И наконец использование:

    Код (Text):
    1.  
    2. if (cache::isEnable()) {
    3.     $cache = new cache();
    4.     $data = $cache->get('data');
    5.     if (!$data) {
    6.         $data = ''; // Обычный способ получения данных
    7.         $cache->set('data', $data);
    8.     }
    9. } else {
    10.     $data = ''; // Обычный способ получения данных
    11. }
     
  2. Апельсин

    Апельсин Активный пользователь

    С нами с:
    20 мар 2010
    Сообщения:
    3.645
    Симпатии:
    2
    У меня сессии в редисе торчат и зачем их кешировать еще - вообще не понимаю. И так на грани фантастики работать должно.

    И причем тут кеширование байт-кода средствами xCache, eAccelerator и обычное хранение данных (строк, массивов и пр.) в мемкеше? Я мож тут что-то не понял просто.
     
  3. Ensiferum

    Ensiferum Активный пользователь

    С нами с:
    11 июл 2010
    Сообщения:
    1.292
    Симпатии:
    0
    Адрес:
    из секты поклонников Нео
    Обычное хранение данных работает и в APC, и в xCache и в eAccelerator. В ряде тестов мемкеш проигрывает по скорости перечисленным ранее именно при работе с данными.

    Редис использую на другом сервере - там другой бубен =)
     
  4. Апельсин

    Апельсин Активный пользователь

    С нами с:
    20 мар 2010
    Сообщения:
    3.645
    Симпатии:
    2
    Смотри, все данные у меня в редисе висят. Только данные, которые я юзаю - массивы всякие, строки. Типа аналог mysql. Только проще и быстрее.
    Для кеширования у меня заюзан xCache. Он кеширует байт-код пхп-страниц. То есть в самом коде нигде намека о xCache, он просто подключен в качестве либы и отдельно себе там работает. Код под него никак не изменяется.

    В каком месте здесь должен встрять твой класс? Просто хранить результат выполнения отдельного куска пхп-кода с помощью твоего класса, вместо того, что этот кусок будет каждый раз отрабатываться?
     
  5. Ensiferum

    Ensiferum Активный пользователь

    С нами с:
    11 июл 2010
    Сообщения:
    1.292
    Симпатии:
    0
    Адрес:
    из секты поклонников Нео
    Это альтернатива редису. Можно хоть tmpFS сделать кэшем - зависит от религиозных убеждений программиста. Мо класс для тех, у кого нет редиса, но стоит какая-либо кэш-система