キャッシュされたCache Assideモード
7163 ワード
シーケンス
ここでは主にキャッシュされたCache Assideモードについて述べる.
Cache Aside
2つのポイントがあります.
public V read(K key) {
V result = cache.getIfPresent(key);
if (result == null) {
result = readFromDatabase(key);
cache.put(key, result);
}
return result;
}
public void write(K key, V value) {
writeToDatabase(key, value);
cache.invalidate(key);
};
汚れたデータ
一つは読み取り操作ですが、キャッシュにヒットしていません.それからデータベースにデータを取りに行きます.この时、書き込み操作が来て、データベースを書き終わったら、キャッシュを失効させます.それから、前の読み取り操作で古いデータを入れます.だから、汚いデータになります.
このcaseは理論的に現れますが、実際に現れる確率は非常に低いかもしれません.この条件は、リードキャッシュ時にキャッシュが失効し、書き込み操作が同時に発生する必要があるからです.実際には、データベースの書き込み操作は読み取り操作よりもずっと遅く、テーブルをロックしますが、読み取り操作は書き込み操作の前にデータベース操作に入る必要があり、書き込み操作よりも遅くキャッシュを更新する必要があります.これらの条件はほとんどありません.
maven
com.github.ben-manes.caffeine
caffeine
2.5.5
com.google.guava
guava
22.0
コード再現
ここではコードを使用してこの汚いデータシーンを再現します.
@Test
public void testCacheDirty() throws InterruptedException, ExecutionException {
AtomicReference db = new AtomicReference<>(1);
LoadingCache cache = CacheBuilder.newBuilder()
.build(
new CacheLoader() {
public Integer load(String key) throws InterruptedException {
LOGGER.info("loading reading from db ...");
Integer v = db.get();
LOGGER.info("loading read from db get:{}",v);
Thread.sleep(1000L); // 1 ,
LOGGER.info("loading Read from db return : {}",v);
return v;
}
}
);
Thread t2 = new Thread(() -> {
try {
Thread.sleep(500L);
} catch (InterruptedException e) {
e.printStackTrace();
}
LOGGER.info("Writing to db ...");
db.set(2);
LOGGER.info("Wrote to db");
cache.invalidate("k");
LOGGER.info("Invalidated cached");
});
t2.start();
// t2 invalidate cache loading
//loading sleep, invalidate ,cache loading
// cache
LOGGER.info("fire loading cache");
LOGGER.info("get from cache: {}",cache.get("k"));
t2.join();
for(int i=0;i<3;i++){
LOGGER.info("get from cache: {}",cache.get("k"));
}
}
しゅつりょく
15:54:05.751 [main] INFO com.example.demo.CacheTest - fire loading cache
15:54:05.772 [main] INFO com.example.demo.CacheTest - loading reading from db ...
15:54:05.772 [main] INFO com.example.demo.CacheTest - loading read from db get:1
15:54:06.253 [Thread-1] INFO com.example.demo.CacheTest - Writing to db ...
15:54:06.253 [Thread-1] INFO com.example.demo.CacheTest - Wrote to db
15:54:06.253 [Thread-1] INFO com.example.demo.CacheTest - Invalidated cached
15:54:06.778 [main] INFO com.example.demo.CacheTest - loading Read from db return : 1
15:54:06.782 [main] INFO com.example.demo.CacheTest - get from cache: 1
15:54:06.782 [main] INFO com.example.demo.CacheTest - get from cache: 1
15:54:06.782 [main] INFO com.example.demo.CacheTest - get from cache: 1
15:54:06.782 [main] INFO com.example.demo.CacheTest - get from cache: 1
caffeineの使用
@Test
public void testCacheDirty() throws InterruptedException, ExecutionException {
AtomicReference db = new AtomicReference<>(1);
com.github.benmanes.caffeine.cache.LoadingCache cache = Caffeine.newBuilder()
.build(key -> {
LOGGER.info("loading reading from db ...");
Integer v = db.get();
LOGGER.info("loading read from db get:{}",v);
Thread.sleep(1000L); // 1 ,
LOGGER.info("loading Read from db return : {}",v);
return v;
});
Thread t2 = new Thread(() -> {
try {
Thread.sleep(500L);
} catch (InterruptedException e) {
e.printStackTrace();
}
LOGGER.info("Writing to db ...");
db.set(2);
LOGGER.info("Wrote to db");
cache.invalidate("k");
LOGGER.info("Invalidated cached");
});
t2.start();
// t2 invalidate cache loading
//loading sleep, invalidate ,cache loading
// cache
LOGGER.info("fire loading cache");
LOGGER.info("get from cache: {}",cache.get("k"));
t2.join();
for(int i=0;i<3;i++){
LOGGER.info("get from cache: {}",cache.get("k"));
}
}
しゅつりょく
16:05:10.141 [main] INFO com.example.demo.CacheTest - fire loading cache
16:05:10.153 [main] INFO com.example.demo.CacheTest - loading reading from db ...
16:05:10.153 [main] INFO com.example.demo.CacheTest - loading read from db get:1
16:05:10.634 [Thread-1] INFO com.example.demo.CacheTest - Writing to db ...
16:05:10.635 [Thread-1] INFO com.example.demo.CacheTest - Wrote to db
16:05:11.172 [main] INFO com.example.demo.CacheTest - loading Read from db return : 1
16:05:11.172 [main] INFO com.example.demo.CacheTest - get from cache: 1
16:05:11.172 [Thread-1] INFO com.example.demo.CacheTest - Invalidated cached
16:05:11.172 [main] INFO com.example.demo.CacheTest - loading reading from db ...
16:05:11.172 [main] INFO com.example.demo.CacheTest - loading read from db get:2
16:05:12.177 [main] INFO com.example.demo.CacheTest - loading Read from db return : 2
16:05:12.177 [main] INFO com.example.demo.CacheTest - get from cache: 2
16:05:12.177 [main] INFO com.example.demo.CacheTest - get from cache: 2
16:05:12.177 [main] INFO com.example.demo.CacheTest - get from cache: 2
ここでinvalidateが見えるとき、loadingは再びトリガーされ、汚れたデータが消去されます.