问题描述
所以我的数据存储区中有需要更新的值.我正在使用事务,如下所示.提交更新后,我将结果发送回客户端,让他们知道更新已经完成.然后,客户端发送另一个请求以获取更新的项目列表.据我所知,所有代码都正确执行,没有抛出任何错误,最终我得到了按预期显示的更新请求.
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.
我的问题是即使在提交之后有时也会在更新显示在返回列表中之前几秒钟.如果只是延迟,那将是糟糕的,但比这更糟糕.该列表在此时间段内返回不正确/未更新的值.我知道这种架构可能会有延迟,但我认为交易的全部意义在于,如果像这样更新某些东西,一旦交易抓住了所需的项目,就没有什么可能读取旧值了?事后长时间查看旧值似乎是不正确的.更不用说等到事务说它已经提交并且有一个完整的 300 毫秒 + RTT 并且在它应该被提交后的几秒钟内仍然得到错误的值.我在这里错过了什么?
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 });
}
});
});
});
推荐答案
你所体验到的称为最终一致性",它是 Cloud Datastore 架构的重要组成部分.没有它,Datastore 对所有请求都会慢得多.
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.
请注意,所有 get
操作始终是一致的 - 只有查询会受到影响,因为更新所有索引需要时间.更新索引可能需要几秒钟时间.
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.
例如,如果应用显示 17 条记录的列表,并且用户添加了一条新记录,您只需在后端响应保存请求后将新记录对象添加到显示的列表中即可.此类响应可能包括正在保存的记录中缺少的数据,例如其数据存储 ID.在某些情况下,如果它有许多在服务器端更新的属性,则返回整个保存的对象可能会更容易.
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 Datastore,在更新几秒钟之前返回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!