我有一个持久连接池(Memcached客户端)。数据正在缓存在memcached服务器中。如果重新启动memcached服务器后,我尝试使用池中的客户端获取缓存数据,我得到以下异常:
java.util.concurrent.ExecutionException: java.lang.RuntimeException: Cancelled
at net.spy.memcached.MemcachedClient$OperationFuture.get(MemcachedClient.java:1662)
at net.spy.memcached.MemcachedClient$GetFuture.get(MemcachedClient.java:1708)
at com.eos.gds.cache.CacheClient.get(CacheClient.java:49)
我尝试获取缓存数据时,仅在重启后第一次获得此异常。我做了很多搜索。但无法找到确切原因。
答案 0 :(得分:2)
Spymemcached有一堆内部队列,在将它们实际发送到memcached之前放置操作。这里发生的是你进行操作,然后在通过线路发送操作之前或者从memcached收到响应之前,Spymemcached意识到连接已经丢失。因此,Spymemcached取消了飞行中的所有操作,然后重新建立连接。
当你在Future上调用get()时,由于Spymemcached取消了操作,因此抛出异常。我建议在这里做的是捕获你使用Spymemcached进行的每个操作的所有异常,然后根据错误重新尝试忘记它的操作。如果它是一个例子,并且你的memcached服务器集群出现故障,那么你可能会忘记它,因为缓存将为空,但你可能想要重试一个集合。
答案 1 :(得分:1)
为每个新客户端运行一次MemcachedClient.getStats(),这将解决取消问题。
答案 2 :(得分:0)
我遇到了完全相同的问题并通过处理异常直到成功来修复它
while(true){
try{
memcacheclient.get(key);
break;
}
catch(java.util.concurrent.CancellationException e ){
log.info("cache cancelled");
}
}
答案 3 :(得分:0)
我有同样的问题。我正在使用Spymemcached客户端连接Memcache服务器。
必须存在连接问题。
答案 4 :(得分:0)
过去几天寻找解决方案。发布以防他人使用。
我们的ServletContextListener实现在contextInitialized上获得了一个新的MemcachedClient(...),然后在contextDestroyed上调用了MemacachedClient方法shutdown()。我将始终在我发送的第一个请求上收到CancellationException或ExecutionException。 (两者都暗示了错误消息,但是我能够捕获到ExecutionException。)
解决方案:从shutdown()切换为shutdown(1,TimeUnit.SECONDS)
现在,get调用第一次运行成功。
我不能确定解释contextDestroyed调用是如何干扰请求的常规处理的。我最好的 guess 是spymemcached的单线程以某种方式在servlet之间共享,因此,当创建servlet来处理构建过程中验证步骤发送的请求时,它将在第一个被销毁之前被销毁。我将发送的请求,然后我的请求的servlet使用的MemcachedClient会尝试使用相同的线程,并从关闭中获取异常。
(当我们了解到我们的Web应用与内存缓存服务器的打开连接过多时,我们的团队已经确定需要关闭电话。)