在 Node.js 中,为什么我应该更喜欢键值存储而不是应用程序变量?

发布于 2024-12-05 15:37:41 字数 336 浏览 0 评论 0原文

我正在 Node.JS 中开发一个由 Socket.IO 支持的实时应用程序,该应用程序将在任何给定时刻同时由数百个用户使用,并且我需要存储有关每个连接的客户端的一些基本详细信息(并在客户端断开连接)。

我读到,使用键值存储(例如 Redis)是存储此类数据的首选。

与将数据存储在 Redis 等键值存储中相比,为什么将数据存储在常规应用内变量(对象,例如 varconnectedClientsData = {})中不好?

它只是为了支持扩展(例如,多个基于 NodeJS 的应用程序服务器可以连接到单个中央键值存储),还是有一些更严重的缺点?

I am developing a Socket.IO-backed real-time application in Node.JS that will be used by couple of hundred users simultaneously at any given moment, and I need to store some basic details about each connected client (and remove those details upon client disconnections).

I have read that using a key-value store (such as Redis) is the preferred choice for storing such data.

Why is storing data in a regular in-app variable (object, e.g. var connectedClientsData = {}) bad compared to storing data in a key-value store such as Redis?

Is it only to support scaling (e.g. multiple NodeJS-based application servers can connect to a single, central key-value store), or are there some more serious drawbacks?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

邮友 2024-12-12 15:37:41

有几个问题在起作用:

1)是的,扩展。不仅可以连接到多个服务器,还可以通过“集群”(您可以在 npm 上找到)之类的方式连接到多个 CPU。

2) V8 目前由于其基于浏览器的传统而存在内存限制。它们在某种程度上是可以调整的,并且在 V8 的下一个版本中会被更彻底地删除,但这仍然是需要考虑的事情。

此外,与重新启动 Redis 相比,您更有可能重新启动节点进程(以更新应用程序),从而丢失所有会话。

There are a couple of issues at play:

1) Yes, scaling. Not just to multiple servers, but also to multiple CPUs via something like "cluster" (which you can find on npm).

2) V8 has memory limitations currently based on its browser-based heritage. They are tweakable to some extent, and being removed more thoroughly in the next version of V8, but it's still something to consider.

Also you're much more likely to restart your node process (to update your application) than you are to restart redis, thus losing all the sessions.

献世佛 2024-12-12 15:37:41
  • 数据持久化 - 您的数据被持久化在更可靠、更持久的存储中,该存储是为处理这些数据而构建的。例如,redis 在磁盘上有数据集的快照,并支持高级数据结构,这为您在操作数据时提供了更多选择。

  • 数据集中 - 您的数据从中心位置存储和获取,不仅您的主应用程序而且其他应用程序都可以访问它并使用这些数据进行操作。例如,如果您需要在两个系统之间共享状态/数据,则使用专用于此目的的 KV 存储会更简单。

  • 卸载主应用程序 - 当您使用 KV 存储时,您正在卸载主应用程序,这可以提高其性能并显着降低其内存消耗。然后扩展您的主应用程序会变得更加简单。

  • KV 存储可扩展性 - 许多 KV 存储具有内置的扩展功能,否则在主应用程序中实现起来会更加复杂(例如在应用程序的多个实例之间共享状态)。此功能也经过了广泛的测试和良好的记录,因此您不必太关心这些事情。

  • Data persistence - your data are persisted in more reliable and durable storage which is built to deal with this stuff. For example redis has snapshots of the dataset on disk and supports advanced data structures which offers you more options when manipulating with your data.

  • Data centralization - your data are stored and available from central place where not only your main application but also other apps can access it and manipulate with these data. For example if you need to share state/data between two systems it's much simpler to do so with KV store dedicated for this purpose.

  • Unloading your main application - when you use KV store you are unloading your main application which can improve it's performance and significantly lower it's memory consumption. Then scaling your main application can be much simpler.

  • KV store scalability - many KV stores has built-in scaling capabilities which would be otherwise more complex to implement in your main application (for example sharing state between multiple instances of your application). This functionality is also extensively tested and well documented so you don't have to care much about these things.

魂ガ小子 2024-12-12 15:37:41

据说,与关系数据库相比,键值存储更适合存储持久数据,而不是与非持久内存对象相比。

但我怀疑,即使不需要持久性,与对象变量相比,键值数据库也具有优势。它们可以在应用程序之间共享,并且可以节省内存消耗。即使是将所有值存储在内存中的 Redis,也可以节省您的应用程序服务器的内存,因为在消耗大量 GB 时可以将其迁移到另一台服务器。

此外,随着时间的推移,内存中的共享对象的维护往往会变得复杂。如果您决定使用它,我建议您抽象其性质。有一个对象,您只需在代码中执行类似的操作:

var storage = new Storage();
storage.registerClientDisconnection("client_id_1");

然后,您的 Storage.registerClientDisconnection() 可以是

Storage.proptotype.registerClientDisconnection = function(clientId) {
    this.info[clientId].connected = false;
};

Storage.proptotype.registerClientDisconnection = function(clientId) {
    var client = redis.createClient();
    client.set("clientId:"+clientId+":connected", false);
};

总结:我建议使用一些键值存储,但我打赌您可以也使用一些对象存储。但是,如果您决定使用内存中对象,只需抽象此实现细节,以便将来可以轻松迁移到键值存储实现。抽象你的决定似乎比你关于实施的决定更重要。

It is said that key-value stores are better for storing persistent data, comparing to relational databases, not comparing to non-persisted in-memory objects.

But I suspect that a key-value database has advantages when compared to object variables, even when persistence is not a need. They can be shared among apps and can spare the memory consumption. Even Redis, which stores all values in memory, can save you memory from your application server because it can be migrated to another server when consuming a lot of gigabytes.

Also, an in-memory, shared object tends to become complex to maintain over time. If you decide to use it, I recommend you to abstract its nature. Have a object where you just do something like this in your code:

var storage = new Storage();
storage.registerClientDisconnection("client_id_1");

Then, your Storage.registerClientDisconnection() can be either

Storage.proptotype.registerClientDisconnection = function(clientId) {
    this.info[clientId].connected = false;
};

or

Storage.proptotype.registerClientDisconnection = function(clientId) {
    var client = redis.createClient();
    client.set("clientId:"+clientId+":connected", false);
};

Summarizing: I would recommend to use some key-value store but I bet you could use some object storage, too. However, if you decide to use an in-memory object, just abstract this implementation detail so you can easily migrate for a key-value store implementation in the future. Abstracting your decision seems more important than your decision about the implementation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文