nodejs 的单例模式问题

2024-12-18 08:51:43 +08:00
 rizon

想问一下在 nodejs 或 nextjs 里。 prisma mongodb redis lrucache 等等这些需不要做单例模式的处理呢? 哪些做哪些不做? 用 declar global 还是 class 做?

为啥我 lrucache 不用 global 做单例一部署生产就存在缓存删除不掉的问题( class 写单例也不行)开发环境就没事

2881 次点击
所在节点    程序员
13 条回复
zy445566
2024-12-18 09:04:47 +08:00
不需要 new 的,基本就不用做单例,模块引用有缓存,其实也相当于了单例
单例一般也不挂全局吧,我觉得把单例 export 出去就好,只要有引用就存活
缓存删除不了,最好把最简化代码和对应的文件名列一下,光一句话基本没法判断问题
sch1111878
2024-12-18 09:07:06 +08:00
好问题

看 prisma 的官方文档里是推荐的 declare global 的, 而且只需开发环境这样做,
sch1111878
2024-12-18 09:08:33 +08:00
rizon
2024-12-18 09:37:55 +08:00
@sch1111878 这是为了避免开发环境的热加载带来的问题。但我想的是代码写都写了,为什么还要专门只针对开发生效,我上线生产环境也没什么坏处吧
sch1111878
2024-12-18 09:44:36 +08:00
@rizon 是这个道理
zy445566
2024-12-18 10:20:04 +08:00
@sch1111878 #3 所以需要 new 的,那可以加个单例
zhuisui
2024-12-18 10:45:18 +08:00
单例是 nodejs 运行时的对象实例分配的事情,库的功能还要结合对应的中间件或者服务考虑,不能一概而论,这个得结合对应的库的功能实现来考虑。
举个例子,prisma+底层数据库,底层调用有连接池,此时用单例也不会影响并发调用;而 ioredis 单实例的调用内部是单连接,调用 subscribe 或者 block 调用就会阻塞其他调用。
另外,复杂的框架还要针对各种库进行封装,以适应不用的业务需要。
sch1111878
2024-12-18 11:09:39 +08:00
@zy445566 不好意思 你那句话我断句错误了, 理解错了
rizon
2024-12-18 11:50:35 +08:00
@zhuisui 还真是!!!也就是如果 ioredis 我用了单例 会阻塞调用??
但是我在 export 出去的时候,一个模块不也会被缓存吗,实际上我不额外写单例,nodejs 也只会创建一个实例吧?
所以 ioredis 内部是不是做了什么分时优化之类的东西
rizon
2024-12-18 12:00:22 +08:00
@zhuisui #7
const Redis = require("ioredis");
const redis = new Redis();

// Create a shared Redis instance for the entire application.
// Redis is single-thread so you don't need to create multiple instances
// or use a connection pool.
module.exports = redis;
这是 ioredis 官方的 express 案例里的。所以说我创建单实例或者不创建单实例,实际上应该是一样的吧。但是为了代码的可读性和可维护性,我是不是创建单实例更省心一些
zhuisui
2024-12-18 16:29:40 +08:00
关于 ioredis 的阻塞调用,你可以看 https://github.com/redis/ioredis?tab=readme-ov-file#pubsub ,这是 pub sub 相关的。
你上面贴的 redis 代码里几句注释里的 single-thread 是 redis 程序自身的,不是指 node 的。而且这段只适用于普通的非阻塞调用命令。
总之,实例、连接、线程、调用,这是四种概念,还要分开是 node 进程的还是 redis 进程的,不能一概而论。
最后,具体情况具体分析。
zhuisui
2024-12-18 16:32:28 +08:00
你通过代码写单例,和 node 包管理机制导致的单例,那也是两码事。
对于后者的 commonjs ,清除 require cache 重新 require 就会创建一个新实例,旧的还会存在。
Plumbiu
2024-12-18 17:27:10 +08:00
next.js 服务端有两个运行时 https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes ,单例其实很容易出错...

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://ex.noerr.eu.org/t/1098356

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX