ModuleCache

Package engine.modules
Inheritance class ModuleCache » Module » LsObject
Since 1.0
Source Code /engine/modules/cache/Cache.class.php
Модуль кеширования. Для реализации кеширования используетс библиотека Zend_Cache с бэкэндами File, Memcache и XCache. Т.к. в memcache нет встроенной поддержки тегирования при кешировании, то для реализации тегов используется враппер от Дмитрия Котерова - Dklab_Cache_Backend_TagEmuWrapper.

Пример использования:
// Получает пользователя по его логину
public function GetUserByLogin($sLogin) {
	// Пытаемся получить значение из кеша
	if (false === ($oUser = $this->Cache_Get("user_login_{$sLogin}"))) {
		// Если значение из кеша получить не удалось, то обращаемся к базе данных
		$oUser = $this->oMapper->GetUserByLogin($sLogin);
		// Записываем значение в кеш
		$this->Cache_Set($oUser, "user_login_{$sLogin}", array(), 60*60*24*5);
	}
	return $oUser;
}

// Обновляет пользовател в БД
public function UpdateUser($oUser) {
	// Удаляем кеш конкретного пользователя
	$this->Cache_Delete("user_login_{$oUser->getLogin()}");
	// Удалем кеш со списком всех пользователей
	$this->Cache_Clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG,array('user_update'));
	// Обновлем пользовател в базе данных
	return $this->oMapper->UpdateUser($oUser);
}

// Получает список всех пользователей
public function GetUsers() {
	// Пытаемся получить значение из кеша
	if (false === ($aUserList = $this->Cache_Get("users"))) {
		// Если значение из кеша получить не удалось, то обращаемся к базе данных
		$aUserList = $this->oMapper->GetUsers();
		// Записываем значение в кеш
		$this->Cache_Set($aUserList, "users", array('user_update'), 60*60*24*5);
	}
	return $aUserList;
}

Protected Properties

Hide inherited properties

PropertyTypeDescriptionDefined By
aStats array Статистика кеширования ModuleCache
aStoreLife array Хранилище для кеша на время сессии ModuleCache
bIsInit bool Указывает на то, была ли проведенна инициализация модуля Module
bUseCache bool Используется кеширование или нет ModuleCache
oBackendCache Zend_Cache_Backend Объект бэкенда кеширования ModuleCache
oEngine Engine Объект ядра Module
sCacheType string Тип кеширования, прописан в глобльном конфиге config.php ModuleCache
sPrefixSmartCache string Префикс для "умного" кеширования ModuleCache

Public Methods

Hide inherited methods

MethodDescriptionDefined By
CalcStats() Подсчет статистики использования кеша ModuleCache
Clean() Чистит кеши ModuleCache
Delete() Удаляет значение из кеша по ключу(имени) ModuleCache
Get() Получить значение из кеша ModuleCache
GetLife() Получает значение из текущего кеша сессии ModuleCache
GetStats() Возвращает статистику использования кеша ModuleCache
Init() Инициализируем нужный тип кеша ModuleCache
Set() Записать значение в кеш ModuleCache
SetInit() Помечает модуль как инициализированный Module
SetLife() Сохраняет значение в кеше на время исполнения скрипта(сессии), некий аналог Registry ModuleCache
Shutdown() Метод срабатывает при завершении работы ядра Module
SmartGet() Получения значения из "умного" кеша для борьбы с конкурирующими запросами ModuleCache
SmartSet() Устанавливаем значение в "умном" кеша для борьбы с конкурирующими запросами ModuleCache
__call() Ставим хук на вызов неизвестного метода и считаем что хотели вызвать метод какого либо модуля Module
__construct() При создании модуля передаем объект ядра Module
isInit() Возвращает значение флага инициализации модуля Module
multiGet() Поддержка мульти-запросов к кешу ModuleCache

Protected Methods

Hide inherited methods

MethodDescriptionDefined By
__clone() Блокируем копирование/клонирование объекта Module

Property Details

aStats property
protected array $aStats;

Статистика кеширования

aStoreLife property
protected array $aStoreLife;

Хранилище для кеша на время сессии

See Also

bUseCache property
protected bool $bUseCache;

Используется кеширование или нет

oBackendCache property
protected Zend_Cache_Backend $oBackendCache;

Объект бэкенда кеширования

sCacheType property
protected string $sCacheType;

Тип кеширования, прописан в глобльном конфиге config.php

sPrefixSmartCache property
protected string $sPrefixSmartCache;

Префикс для "умного" кеширования

See Also

Method Details

CalcStats() method
public void CalcStats(int $iTime, string $sMethod)
$iTime int Время выполнения метода
$sMethod string имя метода
Source Code: /engine/modules/cache/Cache.class.php#336 (show)
public function CalcStats($iTime,$sMethod) {
    
$this->aStats['time']+=$iTime;
    
$this->aStats['count']++;
    if (
$sMethod=='Dklab_Cache_Backend_Profiler::load') {
        
$this->aStats['count_get']++;
    }
    if (
$sMethod=='Dklab_Cache_Backend_Profiler::save') {
        
$this->aStats['count_set']++;
    }
}

Подсчет статистики использования кеша

Clean() method
public bool Clean(int $cMode='all', array $aTags=array ( ))
$cMode int Режим очистки кеша
$aTags array Список тегов, актуально для режима Zend_Cache::CLEANING_MODE_MATCHING_TAG
{return} bool
Source Code: /engine/modules/cache/Cache.class.php#324 (show)
public function Clean($cMode Zend_Cache::CLEANING_MODE_ALL$aTags = array()) {
    if (!
$this->bUseCache) {
        return 
false;
    }
    return 
$this->oBackendCache->clean($cMode,$aTags);
}

Чистит кеши

Delete() method
public bool Delete(string $sName)
$sName string Имя ключа
{return} bool
Source Code: /engine/modules/cache/Cache.class.php#307 (show)
public function Delete($sName) {
    if (!
$this->bUseCache) {
        return 
false;
    }
    
/**
     * Т.к. название кеша может быть любым то предварительно хешируем имя кеша
     */
    
$sName=md5(Config::Get('sys.cache.prefix').$sName);
    return 
$this->oBackendCache->remove($sName);
}

Удаляет значение из кеша по ключу(имени)

Get() method
public mixed|bool Get(string $sName)
$sName string Имя ключа
{return} mixed|bool
Source Code: /engine/modules/cache/Cache.class.php#185 (show)
public function Get($sName) {
    if (!
$this->bUseCache) {
        return 
false;
    }
    
/**
     * Т.к. название кеша может быть любым то предварительно хешируем имя кеша
     */
    
if (!is_array($sName)) {
        
$sName=md5(Config::Get('sys.cache.prefix').$sName);
        
$data=$this->oBackendCache->load($sName);
        if (
$this->sCacheType==SYS_CACHE_TYPE_FILE and $data!==false) {
            return 
unserialize($data);
        } else {
            return 
$data;
        }
    } else {
        return 
$this->multiGet($sName);
    }
}

Получить значение из кеша

GetLife() method
public mixed GetLife(string $sName)
$sName string Имя ключа
{return} mixed
Source Code: /engine/modules/cache/Cache.class.php#370 (show)
public function GetLife($sName) {
    if (
key_exists($sName,$this->aStoreLife)) {
        return 
$this->aStoreLife[$sName];
    }
    return 
false;
}

Получает значение из текущего кеша сессии

GetStats() method
public array GetStats()
{return} array
Source Code: /engine/modules/cache/Cache.class.php#351 (show)
public function GetStats() {
    return 
$this->aStats;
}

Возвращает статистику использования кеша

Init() method
public void Init()
Source Code: /engine/modules/cache/Cache.class.php#128 (show)
public function Init() {
    
$this->bUseCache=Config::Get('sys.cache.use');
    
$this->sCacheType=Config::Get('sys.cache.type');

    if (!
$this->bUseCache) {
        return 
false;
    }
    
/**
     * Файловый кеш
     */
    
if ($this->sCacheType==SYS_CACHE_TYPE_FILE) {
        require_once(
LS_DKCACHE_PATH.'Zend/Cache/Backend/File.php');
        
$oCahe = new Zend_Cache_Backend_File(
            array(
                
'cache_dir' => Config::Get('sys.cache.dir'),
                
'file_name_prefix'    => Config::Get('sys.cache.prefix'),
                
'read_control_type' => 'crc32',
                
'hashed_directory_level' => Config::Get('sys.cache.directory_level'),
                
'read_control' => true,
                
'file_locking' => true,
            )
        );
        
$this->oBackendCache = new Dklab_Cache_Backend_Profiler($oCahe,array($this,'CalcStats'));
        
/**
         * Кеш на основе Memcached
         */
    
} elseif ($this->sCacheType==SYS_CACHE_TYPE_MEMORY) {
        require_once(
LS_DKCACHE_PATH.'Zend/Cache/Backend/Memcached.php');
        
$aConfigMem=Config::Get('memcache');

        
$oCahe = new Dklab_Cache_Backend_MemcachedMultiload($aConfigMem);
        
$this->oBackendCache = new Dklab_Cache_Backend_TagEmuWrapper(new Dklab_Cache_Backend_Profiler($oCahe,array($this,'CalcStats')));
        
/**
         * Кеш на основе XCache
         */
    
} elseif ($this->sCacheType==SYS_CACHE_TYPE_XCACHE) {
        require_once(
LS_DKCACHE_PATH.'Zend/Cache/Backend/Xcache.php');
        
$aConfigMem=Config::Get('xcache');

        
$oCahe = new Zend_Cache_Backend_Xcache(is_array($aConfigMem) ? $aConfigMem : array());
        
$this->oBackendCache = new Dklab_Cache_Backend_TagEmuWrapper(new Dklab_Cache_Backend_Profiler($oCahe,array($this,'CalcStats')));
    } else {
        throw new 
Exception("Wrong type of caching: ".$this->sCacheType." (file, memory, xcache)");
    }
    
/**
     * Дабы не засорять место протухшим кешем, удаляем его в случайном порядке, например 1 из 50 раз
     */
    
if (rand(1,50)==33) {
        
$this->Clean(Zend_Cache::CLEANING_MODE_OLD);
    }
}

Инициализируем нужный тип кеша

Set() method
public bool Set(mixed $data, string $sName, array $aTags=array ( ), int $iTimeLife=false)
$data mixed Данные для хранения в кеше
$sName string Имя ключа
$aTags array Список тегов, для возможности удалять сразу несколько кешей по тегу
$iTimeLife int Время жизни кеша в секундах
{return} bool
Source Code: /engine/modules/cache/Cache.class.php#274 (show)
public function Set($data,$sName,$aTags=array(),$iTimeLife=false) {
    if (!
$this->bUseCache) {
        return 
false;
    }
    
/**
     * Т.к. название кеша может быть любым то предварительно хешируем имя кеша
     */
    
$sName=md5(Config::Get('sys.cache.prefix').$sName);
    if (
$this->sCacheType==SYS_CACHE_TYPE_FILE) {
        
$data=serialize($data);
    }
    return 
$this->oBackendCache->save($data,$sName,$aTags,$iTimeLife);
}

Записать значение в кеш

SetLife() method
public void SetLife(mixed $data, string $sName)
$data mixed Данные для сохранения в кеше
$sName string Имя ключа
Source Code: /engine/modules/cache/Cache.class.php#360 (show)
public function SetLife($data,$sName) {
    
$this->aStoreLife[$sName]=$data;
}

Сохраняет значение в кеше на время исполнения скрипта(сессии), некий аналог Registry

SmartGet() method
public bool|mixed SmartGet($sName $sName)
$sName $sName Имя ключа
{return} bool|mixed
Source Code: /engine/modules/cache/Cache.class.php#211 (show)
public function SmartGet($sName) {
    if (!
$this->bUseCache) {
        return 
false;
    }
    
/**
     * Если данных в основном кеше нет, то перекладываем их из временного
     */
    
if (($data=$this->Get($sName))===false) {
        
$this->Set($this->Get($this->sPrefixSmartCache.$sName),$sName,array(),60); // храним данные из временного в основном не долго
    
}
    return 
$data;
}

Получения значения из "умного" кеша для борьбы с конкурирующими запросами Если кеш "протух", и за ним обращаются много запросов, то только первый запрос вернет FALSE, остальные будут получать чуть устаревшие данные из временного кеша, пока их не обновит первый запрос

SmartSet() method
public bool SmartSet(mixed $data, string $sName, array $aTags=array ( ), int $iTimeLife=false)
$data mixed Данные для хранения в кеше
$sName string Имя ключа
$aTags array Список тегов, для возможности удалять сразу несколько кешей по тегу
$iTimeLife int Время жизни кеша в секундах
{return} bool
Source Code: /engine/modules/cache/Cache.class.php#297 (show)
public function SmartSet($data,$sName,$aTags=array(),$iTimeLife=false) {
    
$this->Set($data,$this->sPrefixSmartCache.$sName,array(),$iTimeLife!==false $iTimeLife+60 false);
    return 
$this->Set($data,$sName,$aTags,$iTimeLife);
}

Устанавливаем значение в "умном" кеша для борьбы с конкурирующими запросами Дополнительно сохраняет значение во временном кеше на чуть большее время

multiGet() method
public bool|array multiGet(array $aName)
$aName array Имя ключа
{return} bool|array
Source Code: /engine/modules/cache/Cache.class.php#230 (show)
public function multiGet($aName) {
    if (
count($aName)==0) {
        return 
false;
    }
    if (
$this->sCacheType==SYS_CACHE_TYPE_MEMORY) {
        
$aKeys=array();
        
$aKv=array();
        foreach (
$aName as $sName) {
            
$aKeys[]=md5(Config::Get('sys.cache.prefix').$sName);
            
$aKv[md5(Config::Get('sys.cache.prefix').$sName)]=$sName;
        }
        
$data=$this->oBackendCache->load($aKeys);
        if (
$data and is_array($data)) {
            
$aData=array();
            foreach (
$data as $key => $value) {
                
$aData[$aKv[$key]]=$value;
            }
            if (
count($aData)>0) {
                return 
$aData;
            }
        }
        return 
false;
    } else {
        
$aData=array();
        foreach (
$aName as $key => $sName) {
            if ((
false !== ($data $this->Get($sName)))) {
                
$aData[$sName]=$data;
            }
        }
        if (
count($aData)>0) {
            return 
$aData;
        }
        return 
false;
    }
}

Поддержка мульти-запросов к кешу Такие запросы поддерживает только memcached, поэтому для остальных типов делаем эмуляцию