Google App Engine数据存储在更新数秒之前返回 [英] Google App Engine Datastore, returning before it was updated for several seconds

查看:106
本文介绍了Google App Engine数据存储在更新数秒之前返回的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我的问题甚至在提交后有时它在更新显示在返回列表中之前有时会有几秒钟。如果这只是一个蹩脚的延迟,但它比这更糟糕。该列表在此期间返回不正确/未更新的值。我知道这个架构可能会有延迟,但我认为整个交易点是这样的,如果这样更新了一些东西,那么一旦交易抓住所需的物品,什么都不可能读取旧值?长时间以后看旧的价值似乎是不正确的。等到交易表明它已经提交并且具有整个300ms + RTT并且在它被认为承诺后的几秒钟内仍然变坏的值之前,等待的时间更少。我在这里错过了什么?

  / * 
我们并没有真正删除一篇文章,只是简单地用一个[删除]
版本本身。
* /
router.delete('/',function(req,res){

//检查参数
if(req.body == null || req.body [Thread] == null || typeof req.body [Thread]!==string){
res.json({success:false,message:Thread name ,data:null});
return;
}

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

var transaction = datastore.transaction();
transaction.get (datastore.key(['Post',PostName(req.body [Thread],6,parseInt(req.body [PostNumber]))]),function(err,value){
$ (呃r)
{
res.json({success:false,message:Transaction failed。,data:null});
return;

$ b $ 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:从表格中删除发布信息,data:null});
}
});
});
});


解决方案

所谓的最终一致性它是云数据存储体系结构的重要组成部分。如果没有它,数据存储对于所有请求来说会慢得多。

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

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

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



在极少数情况下,对象需要客户端加载一组全新的数据,这些数据可能包含更新的对象,客户端可能仍然会将查询中返回的对象替换为更新后的对象,或者在缺失的情况下添加它。同样,当查询结果到达时,您已经从保存对象响应中获得了完整的更新对象。


So I have values I need to update in my datastore. I am using a transaction do so as seen below. After the update has been committed I send a result back to the client letting them know the update has went through. The client then sends another request for an updated list of items. All code executes correctly as far as I can tell, no errors thrown and eventually I do get the update requested showing as expected.

My issue is even after the commit sometimes it is several seconds sometimes before the update shows in the returned list. If it was just a delay that would be crappy, but it is worse than that. The list returns incorrect / non-updated values during this time period. I understand that there can be delays with this architecture, but I thought the entire point of transactions was so that if something was updated like this nothing could possibly read the old value once the transaction grabbed the desired item? To see the old value for a long, long time afterwards seems incorrect. Much less waiting until after the transaction says it has been committed and having an entire 300ms+ RTT and still getting bad values for several seconds after it was supposedly committed. What am I missing here?

/*
    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 });
            }
        });
    });
});

解决方案

What you experience is called "eventual consistency", and it is an important part of Cloud Datastore architecture. Without it the Datastore would be much slower for all requests.

Note that all get operations are always consistent - only queries are affected as it takes time to update all indexes. Updates to indexes may take up to a few seconds.

There are several strategies to work with eventual consistency, but they are not really applicable/necessary in your use case, because the updated data is already available to your client app. It was your client app that initiated the save request. In almost all situations it means that you can avoid reloading the data.

For example, if an app displays a list of 17 records and a user added a new record, you can simply add the new record object to the displayed list after the backend responds to the save request. Such response may include data that is missing from the record being saved, e.g. its datastore ID. In some situations it may be easier to return the entire saved object if it has many properties that have been updated on the server side.

In a very rare case when saving an object requires the client to load a totally new set of data, which may include the updated object, the client may still replace the object returned in a query with an updated object - or add it if it is missing. Again, by the time the query results arrive you already have a complete updated object from your "save object" response.

这篇关于Google App Engine数据存储在更新数秒之前返回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆