【发布时间】:2017-11-22 07:17:48
【问题描述】:
我们想要构建一个 Node.js API,将无模式文档存储在 MongoDB 集合中。每个文档都应该有一个键“no”,按顺序排列它们:
[
{ "no": 1, ... },
{ "no": 2, ... },
{ "no": 3, ... },
{ "no": 4, ... },
...
]
我们有以下限制:
- 排序(包括其他参数)需要加密签名。因此,服务器无法设置客户端在签名和发送数据之前不知道的序列号。
-
no必须是唯一的(不允许:1 -> 1 -> 2 -> 3) - 排序中不能有任何间隙(不允许:1 -> 2 -> 4 -> 5)
- API 是复制的,所以会有很多针对 MongoDB 的并发请求。
- API 客户端不是浏览器应用程序,它实际上也是一个 Node.js 应用程序。将有只有一个 API 客户端
我们的出发点是让 API 在每个存储请求上都返回下一个序列号。
POST /collection { "no": 1, ...}
returns {"next": 2}
这行得通吗?
在客户端,可能是这样的伪代码:
let next
module.exports.create = (document, cb) => {
if (!next) next = 1 // here it is probably better to sync the initial no with the db instead always starting with 1
document.no = next
return post('/collection', document, (err, res) => {
if (err) ...
next = res.next
return cb(...)
}
}
如果客户端的create被多个并发调用者调用,会不会出现两个或多个create请求重复no的情况?
【问题讨论】:
-
如果有多个客户端,您返回下一个序列号的方案在竞争条件下是不安全的。通常,客户端只要求在列表末尾添加一个新文档,服务器会以一种不受竞争条件影响的方式分配下一个序列号(只有服务器才能以安全的方式执行此操作)。
-
添加几个粗体字并不能改变这样不安全的事实。如果意图是存储在服务器上,那么排序应该来自那里。我们可以告诉你创建一个本地存储数据库来保持顺序,但这里的用例仍然很不清楚。您是否坚持可能与“重新排序列表”有关的“客户”责任?如果是这样,那么可能会有其他选择。最重要的是,这目前既不清楚又广泛,因为您过于关注证明您的案例的合理性,而不是提出要解决的实际问题。
-
当您不清晰和广泛时,您会得到与刚刚得到的答案一样的答案。所以最好只描述用例并问“如何解决它”。
-
我已经更新了帖子。除其他输入外,该序列将被加密签名。因此,在将序列号保存到数据库之前,客户端需要知道序列号。
标签: javascript node.js mongodb architecture