用CountDownLatch和AtomicReference解决cache失效大并发透传DB的思路
程序员文章站
2022-05-06 13:19:24
...
cache失效大并发透传DB,在TimYang的一篇博文Memcache mutex设计模式介绍过。提到了两种方案。其中第一方案的sleep时长不好把握。
if (memcache.get(key) == null) { // 3 min timeout to avoid mutex holder crash if (memcache.add(key_mutex, 3 * 60 * 1000) == true) { value = db.get(key); memcache.set(key, value); memcache.delete(key_mutex); } else { sleep(50); retry(); } }
我们假设在单机cache中解决这个问题,不涉及分布式锁。可不可以做到用notify代替sleep。memcached的add操作可以演绎成java的cas操作,cas成功的线程从db中取数据,失败的线程进入wait状态,当成功的线程设置cache以后,notify所有等待的线程,他们就可以从cache中取数据了。那么如何实现notify呢?首先我们想到了CountDownLatch,基本代码如下:
CountDownLatch latch = new CountDownLatch(1); if(_reference.compareAndSet(null, latch)){ // Fetch from DB //if done System.out.println("Thread:" + Thread.currentThread().getName() +" I'm here Get DB"); cache.put("a", "1"); _reference.get().countDown(); _reference.set(null); }else{ try { CountDownLatch la = _reference.get(); System.out.println("Thread:" + Thread.currentThread().getName() +" I'm here Wait Result" + cache.get("a")); la.await(); System.out.println("Thread:" + Thread.currentThread().getName() +" I'm here Get Result" + cache.get("a")); //something to do } catch (InterruptedException e) { e.printStackTrace(); } }