Guava Cache, how to block access while doing removal

后端 未结 1 732
Happy的楠姐
Happy的楠姐 2020-12-11 12:30

I have thread A, inserting a new element to Guava Cache, and because of the Size policy, the cache will evict element associated with key Y.

Unfortunately, the remo

1条回答
  •  抹茶落季
    2020-12-11 13:13

    You stated Guava Cache, but there is no code example, so I give a general answer.

    For the below I assume that you have a "loading cache" aka "self populating cache" schema.

    Solution 1: Properly design your cache interactions and database transactions.

    The update process invalidates the cache entry, as soon a transaction is started on it.

      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
    

    If you remove the entry from the cache and then start the transaction you introduce a race condition.

    Solution 2: Use caches that block out concurrent operations on the same key/entry.

    Take a look on ehcache Blocking Cache. Or take a look on cache2k where the blocking behaviour is the default.

    But, however, you need to do additional locking on the loader level by yourself. E.g. like the example below.

    Solution 3: Do the locking by yourself on top of the cache and wrap all cache operations. E.g. with something like:

     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(); }
     }
    

    You can also look at the BlockingCache implementation from ehcache and take some inspiration from there.

    Have fun!

    0 讨论(0)
提交回复
热议问题