Tags_Container – , .
MemcacheTag1, MemcacheTag2 MemcacheTagN – , Tags_Container , .
class My_Cache_Backend_Memcached extends Zend_Cache_Backend_Memcached { /** * @const string */ const TAGS_CONTAINER_NAME = 'Tags_Container'; /** * @return array */ protected function _getTagsContainer() { $tagsContainer = $this->load(self::TAGS_CONTAINER_NAME); if (false === $tagsContainer) { $tagsContainer = array(); } if (is_string($tagsContainer)) { $tagsContainer = array($tagsContainer); } return $tagsContainer; } /** * @param $tagName * * @return array */ protected function _getIdsByTag($tagName) { $tagIds = $this->load($tagName); if (false === $tagIds) { $tagIds = array(); } if (is_string($tagIds)) { $tagIds = array($tagIds); } return $tagIds; } /** * Save some string datas into a cache record * * Note : $data is always "string" (serialization is done by the * core not by the backend) * * @param string $data Datas to cache * @param string $id Cache id * @param array $tags Array of strings, the cache record will be tagged * by each string entry * @param bool|int $specificLifetime If != false, set a specific lifetime * for this cache record (null => infinite lifetime) * @return bool True if no problem */ public function save($data, $id, $tags = array(), $specificLifetime = false) { $lifetime = $this->getLifetime($specificLifetime); $tagsLifetime = $this->getLifetime(false); if ($lifetime > $tagsLifetime) { $tagsLifetime = $lifetime; } if ($this->_options['compression']) { $flag = MEMCACHE_COMPRESSED; } else { $flag = 0; } $result = true; if (count($tags) > 0) { $tagsContainer = $this->_getTagsContainer(); $containerChanged = false; foreach($tags as $tagName) { if ($tagName == self::TAGS_CONTAINER_NAME) { Zend_Cache::throwException('Incorrect name tag "' . $tagName . '"'); } if (in_array($id, $tagsContainer)) { Zend_Cache::throwException('The key with id = "' . $id . '" already used in the tags'); } if (!in_array($tagName, $tagsContainer)) { $containerChanged = true; $tagsContainer[] = $tagName; } $tagIds = $this->_getIdsByTag($tagName); if (!in_array($id, $tagIds)) { $tagIds[] = $id; } $result = $result && @$this->_memcache->set( $tagName, array($tagIds), $flag, $tagsLifetime ); } if ($containerChanged) { $result = $result && @$this->_memcache->set( self::TAGS_CONTAINER_NAME, array($tagsContainer), $flag, $tagsLifetime ); } } // ZF-8856: using set because add needs a second request if item already exists $result = $result && @$this->_memcache->set( $id, array($data, time(), $lifetime), $flag, $lifetime ); return $result; } /** * @param string $mode * @param array $tags * * @return array */ protected function _get($mode, $tags = array()) { if (is_string($tags)) { $tags = array($tags); } $tagNames = $this->_getTagsContainer(); switch($mode) { case 'ids': break; case 'tags': $tagNames = array_intersect($tagNames, $tags); break; case 'matching': $tagNames = array_intersect($tagNames, $tags); break; case 'notMatching': $tagNames = array_diff($tagNames, $tags); break; default: Zend_Cache::throwException('Invalid mode for _get() method'); break; } $ids = array(); foreach($tagNames as $tagName) { $ids = array_merge($this->_getIdsByTag($tagName), $ids); } return $ids; } /** * Return an array of stored cache ids * * @return array */ public function getIds() { return $this->_get('ids', array()); } /** * Return an array of stored tags * * @return array */ public function getTags() { return $this->_get('tags', array()); } /** * Return an array of stored cache ids which match given tags * * In case of multiple tags, a logical AND is made between tags * * @param array $tags array of tags * * @return array */ public function getIdsMatchingTags($tags = array()) { return $this->_get('matching', $tags); } /** * Return an array of stored cache ids which don't match given tags * * In case of multiple tags, a logical OR is made between tags * * @param array $tags array of tags * * @return array */ public function getIdsNotMatchingTags($tags = array()) { return $this->_get('notMatching', $tags); } /** * Return an associative array of capabilities (booleans) of the backend * * @return array associative of with capabilities */ public function getCapabilities() { $capabilities = parent::getCapabilities(); $capabilities['tags'] = true; return $capabilities; } /** * @param string $mode * @param array $tags * * @return bool */ protected function _clean($mode, $tags) { $result = false; switch ($mode) { case Zend_Cache::CLEANING_MODE_ALL: $result = $this->_memcache->flush(); break; case Zend_Cache::CLEANING_MODE_MATCHING_TAG: $ids = $this->getIdsMatchingTags($tags); $result = true; foreach($ids as $id) { $result = $result && $this->remove($id); } break; case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG: $ids = $this->getIdsNotMatchingTags($tags); $result = true; foreach($ids as $id) { $result = $result && $this->remove($id); } break; case Zend_Cache::CLEANING_MODE_OLD: case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG: $this->_log(self::TAGS_UNSUPPORTED_BY_CLEAN_OF_MEMCACHED_BACKEND); break; default: Zend_Cache::throwException('Invalid mode for clean() method'); break; } return $result; } /** * @param string $mode * @param array $tags * * @return mixed */ public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) { return $this->_clean($mode, $tags); } }
$frontendName = 'Class'; $backendName = 'My_Cache_Backend_Memcached'; $frontendOptions = array(); $memcacheDataObject1 = new Default_Models_MemcacheData1; $memcacheDataObject2 = new Default_Models_MemcacheData2; $backendOptions = array( 'servers' => array( array( 'host' => '127.0.0.1', 'port' => '11211', 'persistent' => 1, 'weight' => 5, 'timeout' => 5, 'retry_interval' => 15 ) ) ); $frontendOptions['cached_entity'] = $memcacheDataObject1; $cachedObject1 = Zend_Cache::factory( $frontendName, $backendName, $frontendOptions, $backendOptions, false, true ); $cachedObject1->setTagsArray(array('Memcached_Tag1')); $frontendOptions['cached_entity'] = $memcacheDataObject2; $cachedObject2 = Zend_Cache::factory( $frontendName, $backendName, $frontendOptions, $backendOptions, false, true ); $cachedObject2->setTagsArray(array('Memcached_Tag2'));
class Default_Models_MemcacheData1 { public function cachedMethod() { return rand(111, 999); } }
for ($i = 0; $i < 3; $i++) { Zend_Debug::dump($memcacheDataObject1->cachedMethod(), 'cached data:'); } for ($i = 0; $i < 3; $i++) { Zend_Debug::dump($memcacheDataObject2->cachedMethod(), 'cached data:'); }
cached data: int(468)
cached data: int(676)
ached data: int(721)
ached data: int(182)
cached data: int(414)
cached data: int(561)
for ($i = 0; $i < 3; $i++) { Zend_Debug::dump($cachedObject1->cachedMethod(), 'cached data:'); } for ($i = 0; $i < 3; $i++) { Zend_Debug::dump($cachedObject2->cachedMethod(), 'cached data:'); }
cached data: int(901)
cached data: int(901)
cached data: int(901)
cached data: int(865)
cached data: int(865)
cached data: int(865)
$cachedClass1->clean( Zend_Cache::CLEANING_MODE_MATCHING_TAG, array('Memcached_Tag1') );
Source: https://habr.com/ru/post/137150/
All Articles