gpt4 book ai didi

php - 使用标准 php 库使多个 memcache 键无效的最佳方法?

转载 作者:可可西里 更新时间:2023-11-01 13:32:14 27 4
gpt4 key购买 nike

我有一个数据库,其中包含可以搜索、浏览并在多个服务器上有多个副本的文件。

我缓存搜索、浏览页面和服务器位置(网址)。假设我删除了一个文件,什么是使该文件的所有搜索、浏览数据和 url 无效的好方法?或者,如果文件服务器出现故障,我需要使指向该服务器的所有 URL 失效?

本质上,我正在寻找类似于 memcache-tags 的东西,但具有标准的内存缓存和 php 组件。 (无需更改 Web 服务器本身的任何内容)。我需要在键之间建立某种多对多关系(一个服务器有多个文件,一个文件有多个服务器),但似乎无法找到实现此目的的好方法。在某些情况下,过时的缓存是可以接受的(较小的更新等),但在某些情况下(通常是删除和服务器关闭),我需要使所有包含对它的引用的缓存项无效。

我看过的一些方法:

Namespaces :

$ns_key = $memcache->get("foo_namespace_key");
// if not set, initialize it
if($ns_key===false) $memcache->set("foo_namespace_key", rand(1, 10000));
// cleverly use the ns_key
$my_key = "foo_".$ns_key."_12345";
$my_val = $memcache->get($my_key);

//To clear the namespace do:
$memcache->increment("foo_namespace_key");
  • 将缓存键限制在单个命名空间

Item caching approach :

$files = array('file1','file2');
// Cache all files as single entries
foreach ($files as $file) {
$memcache->set($file.'_key');
}
$search = array('file1_key','file2_key');
// Retrieve all items found by search (typically cached as file ids)
foreach ($search as $item) {
$memcache->get($item);
}
  • 如果文件服务器出现故障,所有包含该服务器 url 的 key 都应该无效(例如,需要大量的小缓存项,这反过来又需要对缓存进行大量请求)- 中断任何缓存完整对象和结果集的机会

Tag implemenation :

class KeyEnabled_Memcached extends Zend_Cache_Backend_Memcached
{

private function getTagListId()
{
return "MyTagArrayCacheKey";
}

private function getTags()
{
if(!$tags = $this->_memcache->get($this->getTagListId()))
{
$tags = array();
}
return $tags;
}

private function saveTags($id, $tags)
{
// First get the tags
$siteTags = $this->getTags();

foreach($tags as $tag)
{
$siteTags[$tag][] = $id;
}
$this->_memcache->set($this->getTagListId(), $siteTags);
}

private function getItemsByTag($tag)
{
$siteTags = $this->_memcache->get($this->getTagListId());
return isset($siteTags[$tag]) ? $siteTags[$tag] : false;
}

/**
* 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 int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
* @return boolean True if no problem
*/
public function save($data, $id, $tags = array(), $specificLifetime = false)
{
$lifetime = $this->getLifetime($specificLifetime);
if ($this->_options['compression']) {
$flag = MEMCACHE_COMPRESSED;
} else {
$flag = 0;
}
$result = $this->_memcache->set($id, array($data, time()), $flag, $lifetime);
if (count($tags) > 0) {
$this->saveTags($id, $tags);
}
return $result;
}

/**
* Clean some cache records
*
* Available modes are :
* 'all' (default) => remove all cache entries ($tags is not used)
* 'old' => remove too old cache entries ($tags is not used)
* 'matchingTag' => remove cache entries matching all given tags
* ($tags can be an array of strings or a single string)
* 'notMatchingTag' => remove cache entries not matching one of the given tags
* ($tags can be an array of strings or a single string)
*
* @param string $mode Clean mode
* @param array $tags Array of tags
* @return boolean True if no problem
*/
public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
{
if ($mode==Zend_Cache::CLEANING_MODE_ALL) {
return $this->_memcache->flush();
}
if ($mode==Zend_Cache::CLEANING_MODE_OLD) {
$this->_log("Zend_Cache_Backend_Memcached::clean() : CLEANING_MODE_OLD is unsupported by the Memcached backend");
}
if ($mode==Zend_Cache::CLEANING_MODE_MATCHING_TAG) {
$siteTags = $newTags = $this->getTags();
if(count($siteTags))
{
foreach($tags as $tag)
{
if(isset($siteTags[$tag]))
{
foreach($siteTags[$tag] as $item)
{
// We call delete directly here because the ID in the cache is already specific for this site
$this->_memcache->delete($item);
}
unset($newTags[$tag]);
}
}
$this->_memcache->set($this->getTagListId(),$newTags);
}
}
if ($mode==Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG) {
$siteTags = $newTags = $this->getTags();
if(count($siteTags))
{
foreach($siteTags as $siteTag => $items)
{
if(array_search($siteTag,$tags) === false)
{
foreach($items as $item)
{
$this->_memcache->delete($item);
}
unset($newTags[$siteTag]);
}
}
$this->_memcache->set($this->getTagListId(),$newTags);
}
}
}
}
  • 由于内部内存缓存键丢弃,无法控制哪些键失效,可能会丢弃标记键,这反过来会使大量实际有效键(仍然存在)失效
  • 写并发问题

Two-step cache system :

// Having one slow, and one fast cache mechanism where the slow cache is reliable storage  containing a copy of tag versions 
$cache_using_file['tag1'] = 'version1';
$cache_using_memcache['key'] = array('data' = 'abc', 'tags' => array('tag1' => 'version1');
  • 使用磁盘/mysql 等作为慢速缓存的潜在瓶颈
  • 写并发问题

最佳答案

参见 Organizing memcache keys

除非您可以“掌握关键”项目,否则没有明智的方法可以做到这一点。我的意思是像“user4231-is_valid”之类的东西。您可以检查是否有任何使用该用户数据的内容。否则,除非您正在跟踪所有引用您的相关文件的内容,否则您无法使所有这些文件无效。如果这样做,您仍然必须迭代所有可能性才能成功删除。

记录您的依赖关系,限制您的依赖关系,在您的代码中跟踪您的依赖关系以进行删除事件。

关于php - 使用标准 php 库使多个 memcache 键无效的最佳方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6227482/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com