1

所以我有需要在我的数据存储中更新的值。我正在使用事务,如下所示。提交更新后,我将结果发送回客户端,让他们知道更新已经完成。然后,客户端发送另一个请求以获取更新的项目列表。据我所知,所有代码都正确执行,没有抛出错误,最终我得到了按预期显示的更新请求。

我的问题是即使在提交之后有时也会在更新显示在返回列表中之前几秒钟。如果只是延迟,那将是糟糕的,但比这更糟糕。该列表在此时间段内返回不正确/未更新的值。我知道这种架构可能会有延迟,但我认为交易的全部意义在于,如果像这样更新某些东西,一旦交易抓住了所需的项目,就没有什么可能读取旧值了?事后长时间查看旧值似乎是不正确的。更不用说等到事务说它已经提交并且有一个完整的 300 毫秒 + RTT 并且在它应该被提交后的几秒钟内仍然得到错误的值。我在这里想念什么?

/*
    We don't actually delete a post, we simply replace it with a [removed]
    version of itself.
*/
router.delete('/', function (req, res) {

    //Check our parameters
    if (req.body == null || req.body["Thread"] == null || typeof req.body["Thread"] !== "string") {
        res.json({ success: false, message: "Thread name was not included as a parameter.", data: null});
        return;
    }

    if (req.body == null || req.body["PostNumber"] == null) {
        res.json({ success: false, message: "Post Number was not included as a parameter.", data: null });
        return;
    }

    if ((parseInt(req.body["PostNumber"]) || 0) < 1) {
        res.json({ success: false, message: "Post Number was not a valid numeric value.", data: null });
        return;
    }

    var transaction = datastore.transaction();
    transaction.get(datastore.key(['Post', PostName(req.body["Thread"], 6, parseInt(req.body["PostNumber"]))]), function (err, value) {

        if (err)
        {
            res.json({ success: false, message: "Transaction failed.", data: null });
            return;
        }

        if (value === null)
        {
            res.json({ success: false, message: "Post and thread combination does not exist.", data: null });
            return;
        }

        value.data.CreatorName = "[removed]";
        value.data.CreatorFooter = "";
        value.data.Contents = "[removed]";
        transaction.save(value);
        transaction.commit(function (err) {
            if (err)
            {
                res.json({ success: false, message: "Transaction failed.", data: null });
            }
            else
            {
                res.json({ success: true, message: "Erased post information from table", data: null });
            }
        });
    });
});
4

1 回答 1

3

您所体验的称为“最终一致性”,它是 Cloud Datastore 架构的重要组成部分。没有它,Datastore 对所有请求都会慢得多。

请注意,所有get操作始终是一致的——只有查询会受到影响,因为更新所有索引需要时间。更新索引可能需要几秒钟。

有几种策略可以实现最终一致性,但它们在您的用例中并不真正适用/不是必需的,因为更新的数据已经可供您的客户端应用程序使用。是您的客户端应用程序发起了保存请求。在几乎所有情况下,这意味着您可以避免重新加载数据。

例如,如果一个应用显示 17 条记录的列表,并且用户添加了一条新记录,您只需在后端响应保存请求后将新记录对象添加到显示的列表中即可。这种响应可能包括正在保存的记录中丢失的数据,例如其数据存储 ID。在某些情况下,如果它有许多在服务器端已更新的属性,则返回整个保存的对象可能会更容易。

在极少数情况下,当保存对象需要客户端加载一组全新的数据(可能包括更新的对象)时,客户端仍然可以用更新的对象替换查询中返回的对象 - 或者添加它,如果它是失踪。同样,当查询结果到达时,您已经从“保存对象”响应中获得了完整的更新对象。

于 2016-12-03T22:11:08.423 回答