2016-08-25 55 views
0

我试图实现强一致性。让我们把我的模型PVPPlayerAppEngine实现强一致性

class PVPPlayer(ndb.Model): 
    points = ndb.IntegerProperty() 

为模型中的每个关键是这样创建的:

pvp_player = PVPPlayer(key=ndb.Key(Profile, "test_id", PVPPlayer, "test_id")) 

其中Profile是父模型:

class Profile(ndb.Model): 
    def build_key(cls, some_id): 
     return ndb.Key(cls, some_id) 

我有2个REST API URL:

1) update_points 
2) get_points 

在1)我做的:

# I use transaction because I have to update all the models in single batch 
@ndb.transactional(xg=True, retries=3) 
def some_func(points): 
    pvp_player = ndb.Key(Profile, "test_id", PVPPlayer, "test_id").get() 
    pvp_player.points += points 
    pvp_player.put() 
    # update other models here` 

在2)我做的:

pvp_player = ndb.Key(Profile, "test_id", PVPPlayer, "test_id").get() 
return pvp_player.points` 

我的流程是这样的:

1) update_points() 
2) get_points() 
3) update_points() 
4) get_points()` 
... 

问题

使用get()保证强一致性o我不明白的是为什么有时候由于get_points()的结果,我得到的数据像陈旧的数据根本没有更新。

POST get_points -> 0 
POST sleep 1-3 sec 
POST update_points -> 15 
POST sleep 1-3 sec 
POST get_points -> 15 
POST sleep 1-3 sec 
POST update_points -> 20 
POST sleep 1-3 sec 
POST get_points -> 15 !!!` 
+0

是您的#2功能,还装饰有'@ndb .transactional'?另外,我认为#1中的'update_points'函数名称确实是'update_points',对吗? –

+0

>你的#2功能是否也用@ ndb.transactional装饰过? 我试图为#2添加@ ndb.transactional,但它并不重要 - 它仍然不时给我陈旧的数据 >#1中的update_points函数名称确实是update_points,对不对? 绝对 –

+0

对不起,我的意思是'some_func'是'update_points'? :) –

回答

1

有你超过每实体组的写入限制的情况下,即每秒更新?我认为这可能会破坏文档中提到的实体组的强大一致性。

+0

Physical player是唯一一个更新PVPPlayer模型的人。根据游戏逻辑,有人同时执行2个update_points()请求的情况根本不会发生 –

+0

实际上更奇怪的是,有时两个相继的update_points()之间有15-20秒的间隔,但数据是仍然陈旧,所以它的行为完全一致,但我不明白为什么 –

2

首先检查您的日志,其中一个更新必须失败,错误,因为您的逻辑基本上是正确的。

同时仔细检查您的所有更新是否包含在交易中以避免竞争。 Cloud Datastore: ways to avoid race conditions


这种情况很可能不是一致性问题,但跺脚更新,结帐这个链接一些有趣的案例:

http://engineering.khanacademy.org/posts/transaction-safety.htm http://engineering.khanacademy.org/posts/user-write-lock.htm

+0

我只是明白,我的一个请求与update_points()同时更新我的​​父模型(即配置文件)。这看起来像问题 –

+0

我是否必须分配不同的父键来避免此问题? –

+0

共享包括父项的父项的所有内容都位于同一个实体组中。 –