【发布时间】:2018-04-12 01:27:42
【问题描述】:
这有点难以解释,但我会试一试:
在 node.js 服务器应用程序中,我想处理一次可以在多个地方使用的数据对象。主要问题是,这些对象仅由对象 id 引用,并且是从数据库中加载的。
但是,一旦一个对象已经加载到一个作用域中,它就不应在请求时再次加载,而应返回相同的对象。
这让我想到了垃圾回收的问题:一旦某个对象在任何范围内不再需要,就应该完全释放它,以防止整个数据库一直在服务器的内存中。但问题就从这里开始:
我可以想到两种方法来创建这样的场景:要么使用全局对象引用(这会阻止任何对象被收集),要么真的复制这些对象,但以每次在其中的属性时同步它们的方式一个范围发生更改,通知其他实例有关该更改。
同样,因此每个实例都必须注册一个事件处理程序,该事件处理程序反过来又指向该实例,从而防止它再次被收集。
有没有人为我没有意识到的这种情况提出解决方案?还是我对垃圾收集器的理解有什么误解?
我要避免的是对内存中的每个对象进行手动引用计数。每次从任何集合中删除对象时,我都必须手动调整引用计数(js 中甚至没有析构函数或“引用减少”事件)
【问题讨论】:
-
所以……你想要一个缓存。您可以限制缓存中的项目数量,丢弃最近最少使用的项目。如果您知道不再需要它们,也可以提前删除它们,但这不是可以自动完成的。
-
“缓存”并不是一个完全正确的概念,它应该是没有对象被加载两次,一旦它已经在内存中。在大小有限的高速缓存中,这是无法保证的。从缓存中删除的项目(但可能仍会在其他地方引用),将加载两次。当然,我可以自己跟踪任何删除,但我相信一定有更优雅的方法,因为一旦你在某处删除对象时忘记减少引用计数器,你的内存泄漏就在那里。这正是 GC 应该避免的。
-
是什么决定了你什么时候不再需要引用一个对象呢?当它不存在于任何“集合”中时?什么是集合?
-
一旦一个对象从它所使用的任何作用域中释放出来,它就可以被收集(也包括数据)并在某个地方再次需要它时重新加载。问题是我想避免内存中同一对象的不同版本,因此只有一个实例。第二个优点是每个使用这个数据对象的对象都会知道最新的更新版本(因为它们都使用同一个对象而不是它自己的副本)。在 node.js 中没有真正的并行执行(或更好:调度)之后,竞争条件不再是问题
-
@Psi Redis 最常见的用例之一是作为应用程序和数据库之间的缓存。您将继续按照您目前的方式使用您的数据库。当您需要一个对象时,您可以从 Redis 中获取它。如果不存在,则将对象放入 Redis 中,然后使用它。不确定您要做什么,但 Redis 经常被用作在多个应用程序服务器之间共享状态的一种方式。您的用例听起来很相似。
标签: javascript node.js garbage-collection