线程安全任务批处理

时间:2011-10-31 15:43:38

标签: java google-app-engine thread-safety

我正在使用appengine服务器。我希望得到很多请求(几十个),这会使我的一些数据处于不一致的状态。清理这些数据可以有效地进行批处理 - 例如,最好在几十个请求全部完成后运行我的清理代码一次。我不确切地知道将会有多少请求,或者它们将会有多近。如果清理代码多次运行,则可以,但必须在最后一次请求之后运行。

最小化清理次数的最佳方法是什么?

这是我的想法:

public void handleRequest() {
    manipulateData();
    if (memCacheHasCleanupToken()) {
        return; //yay, a cleanup is already scheduled
    } else {
        scheduleDeferredCleanup(5 seconds from now);
        addCleanupTokenToMemCache();
    }
}

...

public void deferredCleanupMethod() {
    removeCleanupTokenFromMemcache();
    cleanupData();
}

我认为这会崩溃,因为即使在某些请求发现memcache中存在清理令牌(HRD延迟等)后,cleanupData也可能会收到过时的数据,因此清理时可能会遗漏某些数据

所以,我的问题:

  1. 这个一般策略会起作用吗?也许如果我在数据存储区实体上使用事务锁?
  2. 应该使用什么策略?

1 个答案:

答案 0 :(得分:1)

您建议的一般策略将起作用,提供需要清理的数据不会存储在每个实例上(例如,它存储在数据存储区或内存缓存中),并且只要您的schduleDeferredCleanup方法使用任务队列。优化将是使用基于它们运行的​​时间间隔的任务名称,以避免在memcache密钥到期时安排重复清理。

但是,上面描述的程序要注意的一个问题是竞争条件。如上所述,与清理任务同时处理的请求可以检查内存缓存,观察令牌是否存在,并且忽略排队清理任务,同时清理任务已经完成,但尚未删除内存缓存密钥。避免这种情况的最简单方法是使memcache密钥自行过期,但在相关任务执行之前。这样,您可以安排重复的清理任务,但是您永远不应该省略所需的任务。