我试图评估缓存技术的多种选择。最后,我决定在Redis中使用Redis / Elasticache。在了解了Redis的持久性、复制机制、切分/集群、命令和内存管理之后,我最终决定用Redis设计我的缓存引擎。
但一开始我就被一个关键的设计问题困住了
我的应用程序处理森林类型数据结构(即树的树)。来增强我的缓存。我决定设计三个缓存
简单地说,第三个缓存(节点)的元素必须指向第二个缓存(树)的元素,该元素必须指向第一个缓存(森林)的元素。
但问题是Redis并不像Java那样维护对对象的引用。换句话说,如果我在Java或Spring中创建了相同的缓存,那么我的第一个缓存将保存森林,而第二个缓存只会在第一个缓存中维护一个指向当前树的指针,而第三个缓存将保持一个指向第二个缓存所指向的树中节点的指针。
以这种方式使用引用,我会节省大量内存,因为我只是在第一个缓存中加载林的一个实例,而其他缓存元素只是保存指向第一个缓存的指针/引用。
如果在redis中执行相同的操作,那么每个keystore实际上都会存储对象的完整实例,这意味着第一个缓存将存储完整的目录林,而第二个缓存将保存当前树的不同实例,而hold将保存树节点的当前实例。
假设一个大小为10 GB的目录,每棵大小为500 MB的树和平均大小为50 MB的当前节点,那么对于一个遍历树的用户,redis将在任何时候维护10 GB + 500 MB + 50 MB = 100550 MB的平均内存。假设我记录了100个当前用户,并且使用了相同的林,那么我的内存使用量将是10 GB + (500 MB X 10) + (50 MB X 10) = 150500 MB。
但是,如果我使用基于Java的缓存引擎,那么无论有多少用户,我的利用率都将是10 is,因为一旦加载了这个林子,其他缓存将只保存对象引用,占用的空间可以忽略不计。
对此有任何想法。可以使用redis来存储对已经存储的对象的引用,而不是创建新实例吗?
发布于 2019-08-27 23:52:55
在最基本的层次上,Redis存储标量值,所以不,它不会像你想象的那样工作。但是,您可以使用集合和散列(或字符串)组合来伪造它。假设您将每个单独的树项存储为一个散列(或JSON字符串,无论哪种方式更适合您的情况),可以使用缓存键(比如12345 \x{e76f}树(其中12345是树的ID )。然后,您就有了一个存储所有树ID的集合。
sadd TREES 12345 12346 12347 (etc)
hset 12345|TREE node1 node1value
hset 12345|TREE node2 node2value类似地,为当前树为用户和单个项设置一组,并对各个节点执行相同的设置。
sadd USERS mgandhi froosevelt nmandela
set mgandhi|TREEID 12345
set froosevelt|TREEID 12346
set mgandhi|NODEID 1
set froosevelt|NODEID 2然后可以使用排序命令查找每个用户的位置:https://redis.io/commands/sort (即使不需要对结果进行排序):
sort TREES by nosort get *|TREEID get *|NODEID希望这对你有帮助。
https://stackoverflow.com/questions/57639686
复制相似问题