APC允许您将数据存储在 key 中,但不能对这些 key 进行分组。
因此,如果我想有一个名为“articles”的组,并且在此组中,我将拥有采用文章ID形式的键,那么我就很难做到这一点。
articles -> 5 -> cached data
-> 10 -> cached data
-> 17 -> cached data
...
我可以在键的前面加上“组”名称,例如:
article_5 -> cached data
article_10 -> cached data
article_17 -> cached data
...
但这使我无法删除整个组:(
一个可行的解决方案是存储多维数组(这是我现在正在做的事情),但是我认为这不好,因为当我要访问/或删除缓存的数据时,我需要首先获取整个组。因此,如果小组中有不计其数的文章,您可以想象要迭代和搜索的数组类型
您对我如何实现小组目标有更好的想法吗?
编辑:找到了另一个解决方案,不确定是否更好,因为我不知道它的可靠性。我要添加一个名为
__paths
的特殊键,该键基本上是一个多维数组,其中包含缓存中所有其他条目的全前缀键路径。当我请求或删除缓存时,我使用该数组作为引用来快速找出需要删除的键(或键组),因此我不必存储数组并遍历所有键... 最佳答案
根据您的观察,我研究了APC缓存模型(apc_cache.c
)的底层C实现,以期找到可以找到的内容。
源证实了您的观察结果,即后备数据存储中不存在分组结构,因此将需要根据某些 namespace 约束或对缓存层本身的修改来完成对象的任何松散分组集合。我希望找到一些通过链表依靠键链的后门程序,但是不幸的是,似乎可以通过直接重新分配冲突插槽而不是chaining来解决冲突。
进一步困扰这个问题的是,APC似乎为用户条目使用了显式缓存模型,以防止它们老化。因此,不幸的是,依赖于memcached的the solution Emil Vikström provided模型的LRU无法正常工作。
在不修改APC本身的源代码的情况下,我将执行以下操作:
article_
。 5
,10
和17
方案,但是在这种情况下,您可以使用一些数字类型来提高存储效率,而不是存储很多字符串值。 insert
,delete
和clear
。调用clear
时,遍历每个指针,重建在备份数据存储中使用的键,然后从缓存中清除每个键。 我在这里提倡的是一个定义明确的对象,该对象可以有效地执行您寻求的操作。这与子缓存中条目的数量呈线性比例关系,但是由于您为每个元素使用数字类型,因此在受到以下限制的情况下开始经历真实的内存痛苦之前,您将需要超过1亿个条目,例如几百兆字节。
Tamas Imrei击败了我suggesting an alternate strategy我已经在进行文档编制过程中,但这有一些我想讨论的重大缺陷。
如支持C代码中所定义,
APCIterator
是执行搜索(使用其构造函数public __construct ( string $cache [, mixed $search = null ...]] )
)时对整个数据集的线性时间操作。在您要搜索的后备元素仅占总数据的一小部分的情况下,这绝对是不可取的,因为它会遍历缓存中的每个元素以找到所需的元素。引用
apc_cache.c
:/* {{{ apc_cache_user_find */
apc_cache_entry_t* apc_cache_user_find(apc_cache_t* cache, char *strkey, \
int keylen, time_t t TSRMLS_DC)
{
slot_t** slot;
...
slot = &cache->slots[h % cache->num_slots];
while (*slot) {
...
slot = &(*slot)->next;
}
}
因此,正如我在上面概述的那样,我强烈建议您使用一种有效的,基于指针的虚拟分组解决方案来解决您的问题。尽管在内存受到严格限制的情况下,迭代器方法可能最正确,以节省尽可能多的内存为代价。
祝您申请顺利。