近段时间在学习缓存相关知识的时候,看到了缓存更新策略,于是就根据自己的理解,写下这篇文章
步骤
优点
缺点
使用场景
代码示例
public class CacheAside<T, K> implements CacheUpdate<T, K>{ private Map<K, T> map; @Override public T getData(K key) { //if cache has data, return return map.get(key); } @Override public boolean updateData(K key, T data) { map.remove(key, data); return true; } @Override public boolean addData(K key, T data) { return Objects.nonNull(map.put(key, data)); } @Override public boolean removeData(K key) { map.remove(key); return true; } public CacheAside() { map = new HashMap<>(); } }
public class CacheAsideClient<T, K> implements CacheUpdateClient<T, K>{ public CacheUpdateFactory<T, K> factory = CacheUpdateFactory.getInstance(); private CacheUpdate<T, K> cacheUpdate; private DatabaseOperation<T, K> databaseOperation; @Override public T getData(K key){ //get data from cache T dataFromCache = cacheUpdate.getData(key); //if cache haven't, get from database and put to cache if(Objects.nonNull(dataFromCache)){ return dataFromCache; } T dataFromDatabase = databaseOperation.getData(key); cacheUpdate.addData(key, dataFromDatabase); return dataFromDatabase; } @Override public boolean updateData(K key, T data){ //update data to database boolean updateToDatabaseRes = databaseOperation.updateData(key, data); if(updateToDatabaseRes){ //invalid cache data return cacheUpdate.removeData(key); } return false; } @Override public boolean addData(K key, T data){ //add data to database return databaseOperation.addData(key, data); } @Override public boolean removeData(K key){ //remove from database boolean removeFromDatabaseRes = databaseOperation.removeData(key); if(removeFromDatabaseRes){ //invalid cache data return cacheUpdate.removeData(key); } return false; } public CacheAsideClient() { cacheUpdate = factory.getObject(CacheUpdateEnum.CACHE_ASIDE); databaseOperation = (DatabaseOperation<T, K>) new MockDatabaseOperation<T>(); } }
步骤
优点
缺点
使用场景
代码示例
public class ReadOrWriteThough<T, K> implements CacheUpdate<T, K>{ private DatabaseOperation<T, K> databaseOperation; private Map<K, T> map; @Override public T getData(K key) { //if cache has data, return if(map.containsKey(key)){ return map.get(key); } //get data from database and write to cache T data = databaseOperation.getData(key); map.put(key, data); return data; } @Override public boolean updateData(K key, T data) { map.put(key, data); return databaseOperation.updateData(key, data); } @Override public boolean addData(K key, T data) { map.put(key, data); return databaseOperation.addData(key, data); } @Override public boolean removeData(K key) { map.remove(key); return databaseOperation.removeData(key); } public ReadOrWriteThough() { databaseOperation = (DatabaseOperation<T, K>) new MockDatabaseOperation<>(); map = new HashMap<>(); } }
public class ReadOrWriteThoughClient<T, K> implements CacheUpdateClient<T, K>{ private CacheUpdateFactory<T, K> factory = CacheUpdateFactory.getInstance(); private CacheUpdate<T, K> cacheUpdate; @Override public T getData(K key) { return cacheUpdate.getData(key); } @Override public boolean updateData(K key, T data) { return cacheUpdate.updateData(key, data); } @Override public boolean addData(K key, T data) { return cacheUpdate.addData(key, data); } @Override public boolean removeData(K key) { return cacheUpdate.removeData(key); } public ReadOrWriteThoughClient() { cacheUpdate = factory.getObject(CacheUpdateEnum.READ_WRITE_THOUGH); } }
步骤
优点
缺点
使用场景
代码示例
public class WriteBehind<T, K> implements CacheUpdate<T, K> { private Map<K, T> map; private DatabaseOperation<T, K> databaseOperation; private ThreadPoolExecutor threadPoolExecutor; @Override public T getData(K key) { if(map.containsKey(key)){ return map.get(key); } T data = databaseOperation.getData(key); map.put(key, data); return data; } @Override public boolean updateData(K key, T data) { map.put(key, data); threadPoolExecutor.execute(() -> databaseOperation.updateData(key, data)); return true; } @Override public boolean addData(K key, T data) { map.put(key, data); threadPoolExecutor.execute(() -> databaseOperation.addData(key, data)); return true; } @Override public boolean removeData(K key) { map.remove(key); threadPoolExecutor.execute(() -> databaseOperation.removeData(key)); return true; } public WriteBehind() { map = new HashMap<>(); databaseOperation = (DatabaseOperation<T, K>) new MockDatabaseOperation<>(); threadPoolExecutor = new ThreadPoolExecutor(5, 10, 1000, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1000), new ThreadPoolExecutor.CallerRunsPolicy()); } }
public class WriteBehindClient<T, K> implements CacheUpdateClient<T, K>{ private CacheUpdateFactory<T, K> cacheUpdateFactory = CacheUpdateFactory.getInstance(); private CacheUpdate<T, K> cacheUpdate; @Override public T getData(K key) { return cacheUpdate.getData(key); } @Override public boolean updateData(K key, T data) { return cacheUpdate.updateData(key, data); } @Override public boolean addData(K key, T data) { return cacheUpdate.addData(key, data); } @Override public boolean removeData(K key) { return cacheUpdate.removeData(key); } public WriteBehindClient() { cacheUpdate = cacheUpdateFactory.getObject(CacheUpdateEnum.WRITE_BEHIND); } }
分类 | 优点 | 缺点 | 使用场景 |
---|---|---|---|
Cache Aside | 1. 实现简单,调用者可控制数据持久化的细节 | 1. 写请求与读请求并发,读请求持续时间比写请求长,可能会覆盖旧数据到缓存中 2. 上层需要同时管理缓存与持久化,调用较复杂 |
1. 允许缓存数据不准确的场景 2. 因为并发情况下,可能造成脏数据的情况,所以 QPS 较低场景也可以适用 |
Read / Write Though | 1. 上层对数据是否持久化/持久化实现无感 | 1. 同步持久化性能较低,但能有效保证数据一致性 | 1. 性能要求不高的场景 |
Write Behind | 1. 上层对数据是否持久化/持久化实现无感 2. 异步持久化,性能较 Read /Write Though 提高 |
1. 异步持久化可能会导致数据丢失 | 1. 性能要求较高的场景 2. 允许持久化数据丢失场景 |
本文首发于cartoon的博客
转载请注明出处:https://cartoonyu.github.io