如何在Google App Engine(java)的并发过程中立即使删除的实体不可用?

时间:2016-01-19 12:44:18

标签: java google-app-engine google-cloud-datastore objectify

我有一个servlet,它根据请求参数获取实体列表,并在立即删除之前将它们缓存在本地List变量中。删除后使用对象列表执行操作。

有时,如果servlet立即获得并发请求,则两个请求都能够获得相同的实体,并且执行两次不会发生的操作。

我验证了删除时间,大约是100毫秒左右。我需要让其他并发请求不能读取已删除的实体。

如何在Google App Engine实例的并发过程中有效处理此问题?

2 个答案:

答案 0 :(得分:1)

我的建议是使用事务来隔离并发问题并创建 一个幂等的要求。在Java中,类似这样:

DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();

PreparedQuery pq = createYourQuery(datastore); // remember to setKeysOnly()

for (Entity entity : pq.asIterable()) {

    try {
        Transaction tx = datastore.beginTransaction();
        try {
            datastore.get(entity.getKey());
        } catch (EntityNotFoundException e) {
            continue;
        }
        datastore.delete(entity.getKey());
        tx.commit();
    } catch (ConcurrentModificationException e) {
        continue;
    }

    // execute your extra stuff
}

答案 1 :(得分:-1)

在不查看代码的情况下很难分辨,但通常您观察到的行为是对共享数据结构的不同步读/写访问的结果,在您的情况下是一个列表。如果是这种情况,您可能要做的是同步读/写列表的块。这是Java伪代码:

/**
 * Read from the cache.
 */
Data getCache(String key) {
  synchronized (this) {
     // ... Do read
  }
}

/**
 * Delete the cache.
 */
void clearCache() {
  synchronized (this) {
     // ... Do cleanup
  }
}