缓冲更新策略
2022/6/6 23:20:04
本文主要是介绍缓冲更新策略,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
近段时间在学习缓存相关知识的时候,看到了缓存更新策略,于是就根据自己的理解,写下这篇文章
分类
- Cache Aside
- Read / Write Though
- Write Behind
Cache Aside
-
步骤
- 读请求未命中缓存,取数据库数据,并回写缓存
- 写请求先更新数据库,再让缓存失效
-
优点
- 实现简单,调用者可控制数据持久化的细节
-
缺点
- 上层需要同时管理缓存与持久化,调用较复杂
- 写请求与读请求并发,读请求持续时间比写请求长,可能会覆盖旧数据到缓存中
-
使用场景
- 允许缓存数据不准确的场景
- 因为并发情况下,可能造成脏数据的情况,所以 QPS 较低场景也可以适用
-
代码示例
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>(); } }
Read / Write Though
-
步骤
- 读/写请求都只依赖缓存
- 缓存数据同步持久化
-
优点
- 上层对数据是否持久化/持久化实现无感
-
缺点
- 同步持久化性能较低,但能有效保证数据一致性
-
使用场景
- 性能要求不高的场景
-
代码示例
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); } }
Write Behind
-
步骤
- 读/写请求都只依赖缓存
- 缓存数据异步批量持久化
-
优点
- 上层对数据是否持久化/持久化实现无感
- 异步持久化,性能较 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
这篇关于缓冲更新策略的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南