缓存API是一种用于临时存储数据以提高应用程序性能的机制。它通常用于存储频繁访问但不经常变化的数据,减少对原始数据源(如数据库)的访问。
Futures(或Promises)是异步编程中的一种抽象,表示一个可能尚未完成的计算结果。它允许你编写非阻塞代码,可以在结果可用时处理它,而不必等待操作完成。
将缓存API与Futures结合使用有以下优势:
// 使用Map作为简单缓存
const cache = new Map();
async function getDataWithCache(key) {
if (cache.has(key)) {
return cache.get(key); // 立即返回缓存值
}
const promise = fetchDataFromSource(key); // 返回一个Promise
cache.set(key, promise); // 缓存Promise本身
return promise;
}
async function fetchDataFromSource(key) {
// 模拟异步数据获取
return new Promise(resolve => {
setTimeout(() => {
resolve(`Data for ${key}`);
}, 1000);
});
}
const cache = new Map();
async function getDataWithExpiry(key, expiryMs = 5000) {
const cached = cache.get(key);
if (cached) {
if (Date.now() - cached.timestamp < expiryMs) {
return cached.data;
}
cache.delete(key);
}
const data = await fetchDataFromSource(key);
cache.set(key, {
data,
timestamp: Date.now()
});
return data;
}
// Java示例
import java.util.concurrent.*;
public class FutureCache {
private final ConcurrentHashMap<String, Future<String>> cache = new ConcurrentHashMap<>();
private final ExecutorService executor = Executors.newFixedThreadPool(4);
public String getData(String key) throws ExecutionException, InterruptedException {
Future<String> future = cache.get(key);
if (future == null) {
Callable<String> callable = () -> fetchFromSource(key);
FutureTask<String> futureTask = new FutureTask<>(callable);
future = cache.putIfAbsent(key, futureTask);
if (future == null) {
future = futureTask;
executor.execute(futureTask);
}
}
return future.get();
}
private String fetchFromSource(String key) {
// 模拟耗时操作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "Data for " + key;
}
}
问题:当缓存失效时,大量请求同时到达数据库
解决方案:
// 使用互斥锁或单flight模式
const pending = new Map();
async function getDataSafely(key) {
if (cache.has(key)) {
return cache.get(key);
}
if (pending.has(key)) {
return pending.get(key);
}
const promise = fetchDataFromSource(key);
pending.set(key, promise);
try {
const result = await promise;
cache.set(key, result);
return result;
} finally {
pending.delete(key);
}
}
问题:缓存数据与源数据不一致
解决方案:
// 写后失效示例
public void updateData(String key, String newValue) {
// 先更新数据源
updateDataSource(key, newValue);
// 然后使缓存失效
cache.invalidate(key);
}
问题:缓存占用过多内存
解决方案:
// 简单的LRU缓存实现
class LRUCache {
constructor(maxSize = 100) {
this.maxSize = maxSize;
this.cache = new Map();
}
get(key) {
if (!this.cache.has(key)) return undefined;
const value = this.cache.get(key);
this.cache.delete(key);
this.cache.set(key, value);
return value;
}
set(key, value) {
if (this.cache.has(key)) {
this.cache.delete(key);
} else if (this.cache.size >= this.maxSize) {
// 删除最老的条目
const oldestKey = this.cache.keys().next().value;
this.cache.delete(oldestKey);
}
this.cache.set(key, value);
}
}
// Java多级缓存示例
public class MultiLevelCache {
private final Cache<String, String> localCache; // 一级缓存
private final Cache<String, String> distributedCache; // 二级缓存
public String get(String key) {
String value = localCache.get(key);
if (value != null) return value;
value = distributedCache.get(key);
if (value != null) {
localCache.put(key, value);
return value;
}
value = fetchFromSource(key);
distributedCache.put(key, value);
localCache.put(key, value);
return value;
}
}
// 使用RxJS实现响应式缓存
import { from, of } from 'rxjs';
import { shareReplay } from 'rxjs/operators';
const cache = {};
function getDataRx(key) {
if (!cache[key]) {
cache[key] = from(fetchDataFromSource(key)).pipe(
shareReplay(1) // 缓存最后一个值并重放给后续订阅者
);
}
return cache[key];
}
通过合理结合缓存API和Futures,可以显著提高应用程序的性能和响应能力,同时保持代码的简洁和可维护性。
没有搜到相关的文章