0

我有一个任务,用户使用第三方的 XML。XML 提要每天仅更新一次。XML 存储在数据库中,并在请求时返回给用户。如果 XML 不在数据库中,则从第三方检索,存储在数据库中并返回给用户。所有后续请求都将简单地从数据库中读取 XML。

现在我的问题。假设对第三方的请求需要 10 秒才能返回。在此期间,有多个服务器调用相同的数据。我不希望这些中的每一个都向第三方发出请求,我不希望用户什么也没有收到或收到错误。他们可能应该等待第一个请求完成,此时 XML 可用。这是一个相对简单的问题,但我想知道最好的解决方法是什么。

我是只使用一个简单的标志来控制请求还是使用信号量之类的东西?是否有基于我打算使用的堆栈的更好的解决方案,即 Play 框架和 cassandra 后端。我可以用回调或触发器做些什么吗?

顺便说一句,当第一个请求进来时,我需要延迟加载数据。因此,在此任务中,不能选择在单独的进程中或在应用程序启动时获取数据......

谢谢

4

1 回答 1

1

您需要做的就是创建一个单独的组件,负责XML从第三方获取数据并将其保存到数据库中。
在您的代码中,各种线程尝试XML从该组件“获取”。如果存在,
此组件会从数据库返回。XML如果它不存在,那么您使用ReentrantLock进行同步。
所以你做了一个trylock,只有一个线程成功了。其余的将被阻止。当锁被释放时,其他线程被解除阻塞,但XML已经从第三方获取并由第一个设法获得锁的线程存储到数据库中。所以其他线程只是XML从数据库返回。

示例代码(这只是一个帮助您入门的“伪代码”。您应该处理异常等,但可以使用主框架。不要忘记输入unlockfinally这样您的代码就不会无限期地阻塞):

public String getXML() {  
  String xml = getXMLFromDatabase();  
  if(xml == null) {  
     if(glocalLock.tryLock()) {  
        try{  
            xml = getXMLFromThirdParty();  
            storeXMLToDatabase(xml);       
        }  
        finally {  
            globalLock.unlock(); //ok! got XML and stored in DB. Wake-up others!  
        }  
     }
    else {  
         try{ //Another thread got the lock and will do the query. Just wait on lock!     
             globalLock.lock();  
         }  
         finally {
             //woken up but the xml is already fetched  
             xml = getXMLFromDatabase();  
             globalLock.unlock();  
         }   
     }    
  return xml;  
}
于 2013-06-09T10:54:38.147 回答