java - Guava 缓存,如何在删除时阻止访问

标签 java caching synchronization guava

我有线程 A,向 Guava Cache 插入一个新元素,并且由于 Size 策略,缓存将逐出与键 Y 关联的元素。

不幸的是,Y 的移除过程 R 需要很长时间,并且在 Y 被 R 处理的过程中(已经被驱逐但仍在 R 中),有另一个线程 B 试图获取与 key Y 关联的数据。

基本上,R 将尝试为键 Y 更新数据库,而当该值未更新时,线程 B 尝试访问数据库以获取与键 Y 关联的值,该值仍然是旧值。

问题是:当 R 正在工作时,如何阻止线程 B 访问具有键 Y 的元素?

最佳答案

你说的是Guava Cache,但是没有代码示例,所以我给出一个笼统的答案。

对于下面的内容,我假设您有一个“加载缓存”又名“自填充缓存”架构。

解决方案 1: 正确设计您的缓存交互和数据库事务。

一旦在其上启动事务,更新过程就会使缓存条目无效。

  begin transaction
  touch some of the entry data with SQL UPDATE to have it in the transaction
  remove the entry from the cache
  ....
  now you can do more operations on the database regarding the entry data
  if you have the proper isolation level, reads from the database will stall
  until the transaction is committed
  ....
  end transaction

如果您从缓存中删除条目然后启动事务,则会引入竞争条件。

解决方案 2: 使用缓存来阻止对同一键/条目的并发操作。

看看ehcache Blocking Cache .或者看看 cache2k其中阻塞行为是默认的。

但是,但是,您需要自己在加载程序级别上进行额外的锁定。例如。就像下面的例子。

解决方案 3: 自己在缓存之上进行锁定并包装所有缓存操作。例如。像这样:

 Cache cache;
 Lock[] locks = new Lock[16];
 { /* initialize locks */ }

 public Object get(Object key) {
   int idx = key.hashCode() % locks.length;
   locks[idx].lock();
   try { return cache.get(key); 
   } finally { locks[idx].unlock(); }
 }

 public void update(Object key, Object obj) {
   int idx = key.hashCode() % locks.length;
   locks[idx].lock();
   try { return cache.put(key, obj); 
   } finally { locks[idx].unlock(); }
 }

您还可以查看 ehcache 的 BlockingCache 实现并从中获得一些灵感。

玩得开心!

关于java - Guava 缓存,如何在删除时阻止访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25969983/

相关文章:

java - 解析命令行并将其更改为 Char 或 Boolean

http - "forever"和 "never"是唯一有用的缓存持续时间吗?

javascript - module.exports 的 nodejs 缓存问题

c - 在 FreeRTOS 中使用 Mutex 实现两个任务同步

web-services - 用于在 Web 服务和客户端之间同步数据的现代编程标准是什么?

Java进程执行 "tail -f test.log | grep abc"无法得到任何输出

java - 获取本地应用数据目录路径的跨平台方式是什么?

java - 如何使用 Timer 类调用方法,做某事,重置计时器,重复?

javascript - 清除azure中javascript的缓存

SQL在本地和远程服务器之间同步数据库