沙尘暴 / optimizedrediscachebackend
Requires
- neos/flow: ~6.3.14 || ~7.0.11 || ~7.1.5 || ^7.2.2 || dev-master
README
已过时自Neos 8.0以来
注意:OptimizedRedisCacheBackend在Neos 8.0及更高版本中已过时,因为其功能已被集成到核心,并进一步改进。感谢Sebastian Helzle以及所有参与此项目的人 :- :-) )
如何从OptimizedRedisCacheBackend迁移到Neos 8.x
Sandstorm\OptimizedRedisCacheBackend\OptimizedRedisCacheBackend的功能已被集成并进一步改进到核心类Neos\Cache\Backend\RedisBackend。
因此,要更新,您需要进入您的Caches.yaml文件,并将所有出现的Sandstorm\OptimizedRedisCacheBackend\OptimizedRedisCacheBackend替换为Neos\Cache\Backend\RedisBackend。
Neos < 8.0的原始README
- 用作内容缓存
- 如果许多元素具有相同的标签,则需要此功能
安装
composer require sandstorm/optimizedrediscachebackend
版本兼容性
-
= 1.1.4: 支持在Settings.yaml中
Neos.Flow.cache.applicationIdentifier
- 这仅支持以下Flow版本,因为我们依赖于此核心错误修复- 6.3.14或更高版本(且小于7.0)
- 7.0.11或更高版本(且小于7.1)
- 7.1.5或更高版本(且小于7.2)
- 7.2.2或更高版本
- 7.3.0或更高版本(以及所有未来版本)
-
<= 1.1.3 - Flow 6和7(所有版本)
使用
在Caches.yaml中,执行以下操作
Neos_Fusion_Content: backend: Sandstorm\OptimizedRedisCacheBackend\OptimizedRedisCacheBackend Neos_Media_ImageSize: backend: Sandstorm\OptimizedRedisCacheBackend\OptimizedRedisCacheBackend Flow_Mvc_Routing_Route: backend: Sandstorm\OptimizedRedisCacheBackend\OptimizedRedisCacheBackend Flow_Mvc_Routing_Resolve: backend: Sandstorm\OptimizedRedisCacheBackend\OptimizedRedisCacheBackend
如果您使用基于符号链接的部署,您应按如下方式设置flushRedisDatabaseCompletely
选项,以删除旧版本中的旧数据(并确保您为每个缓存使用一个redis DB)
Neos_Fusion_Content: backend: Sandstorm\OptimizedRedisCacheBackend\OptimizedRedisCacheBackend backendOptions: flushRedisDatabaseCompletely: true
当前Redis缓存实现的问题
-
当执行flushByTag时,我们执行以下操作(伪代码)
- 迭代此标签的所有条目
- "取消链接"条目从所有此条目额外标记的标签中
- 迭代当前条目的所有标签
- 删除条目
- 删除条目-标签关系
- "取消链接"条目从所有此条目额外标记的标签中
- 删除标签
- 迭代此标签的所有条目
-
您可以看到,我们在这里有一个双层迭代。在一个大客户项目中,有时在单个标签刷新过程中,内部循环被调用超过100,000次;这使得Redis服务器在脚本运行期间无响应。
此缓存后端的优化
优化后的 FlushByTag
在执行 flushByTag 时,我们只需做以下操作
- *iterate* over all entries for this tag
- remove the entry
- remove the entry->tags relation
- remove the tag
这意味着不会删除缓存条目中其他标签.
-
这会在 Redis 缓存中留下一些“冗余”数据;即那些分配的条目已经不存在但标签仍然存在的数据。这不是一个大问题,因为条目可能只是因为超时(因为它们有 TTL)而消失。
-
我唯一能想到的可能会成为问题的情况是
- entry1 插入并带有标签 A,B
- 执行 flushByTag(A) -> entry1 被删除,标签 A 被删除,标签 B 仍然存在,指向(不存在的)entry1
- 带有标签 A 的 entry1 被插入 (标签关联已更改!)
- -> 仍然存在标签 B(尚未被删除)和 entry1 之间的连接。
-
当依赖于 TaggableBackendInterface 的 findIdentifiersByTag() 时,这可能会成为问题 -- 但内容缓存中从未使用过这个功能。
-
除了 findIdentifiersByTag() 之外,标签仅用于 清除 缓存的某些部分。因此,标签 B -> entry1 的过时边缘可能导致 entry1 被频繁刷新。 我们假设这对于内容缓存来说并不重要。
-
如果用户想要完全删除冗余数据,应该调用 flush(),这将完全重置缓存。
-
上述整个场景不太可能发生,因为缓存标签主要受 Fusion 控制;只要这一点没有改变,缓存标签就会保持稳定。
标准缓存后端的条目列表的删除
默认的 Redis 缓存后端有一个 entries
列表,用于存储所有缓存条目(在旧版 Redis 版本上需要用于迭代)。在列表中查找元素的时间复杂度为 O(n),即列表条目数量。
今天,人们可以使用 KEYS 来迭代条目;但我们的内容缓存不依赖于 IterableBackendInterface。因此,我们完全删除了 entries
。
更简单的 flush() 实现
在实现 flush() 时,我们只需遍历键空间的相关部分并删除所有元素。之前,这是通过类似于 FlushByTag 中解释的逻辑来完成的,因为 Redis 后端是可以冻结的(但我们不需要 Neos 内容缓存中的这一点)。