在多个键之一上缓存逐出
Cache evict on one of multiple keys
在我的应用程序中,我有多个具有多个键的可缓存方法:
@Cacheable(cacheNames = "valueCodes", key = "{#value, #fieldId, #projectId}")
@Cacheable(cacheNames = "fieldNames", key = "{#field, #value, #projectId}")
@Cacheable(cacheNames = "qi", key = "{#langCode, #question, #projectId}")
@Cacheable(cacheNames = "fieldCodes", key = "{#name, #projectId}")
现在我想要一个 cachevict 方法来清除所有缓存,其中 只有 #projectId 键,它是一个 UUID,匹配:
@CacheEvict(value = {"valueCodes", "fieldCodes", "qi"; "fieldCodes"}, key = "#projectId")
我在 this 文章中读到这是不可能的
Only the evict annotation's key regex matching more than one element
in each of the cacheNames
我不太确定他们的意思,但我想这与在 SpEL.
中使用正则表达式有关
所以我开始考虑将我的密钥连接成一个密钥:
@Cacheable(cacheNames="cahceName", key="concat(#projectId).concat(#otherKey)")
并使用正则表达式将所有键与 projectId 后跟通配符相匹配。但是我真的找不到办法做到这一点。
我想要实现的目标可行吗?如果是这样,我该怎么做?
Is what I'm trying to accomplish possible? If so, how do I do this?
你喜欢做的事是不可能的。
一般来说,缓存的作用类似于散列table,您只能对唯一键进行操作。选择属于项目 ID 的所有内容都需要缓存中的索引和查询机制。有些缓存有,但不是全部,并且没有通用标准如何完成。
仔细检查单独缓存属于项目的所有点点滴滴是否真的有意义。如果所有东西都需要一起驱逐,也许它一直都在一起使用。或者,例如,在缓存中保留一个 ConcurrentHashMap
作为值,该缓存包含属于项目的各种组件。
更多信息,请参阅问题:
可能删除注释并直接使用缓存是有意义的。带注解的选项有限
我创建了一个为我管理密钥的 bean,而不是使用注释通过部分密钥查找密钥
- 我删除了所有@CacheEvict 注释。
创建了一个新服务来管理我们所有缓存的逐出
public interface CacheEvictionService {
/**
* Adds the provided key to a global list of keys that we'll need later for eviction
*
* @param key the cached key for any entry
*/
void addKeyToList(String key);
/**
* Find keys that contain the partial key
*
* @param partialKey the cached partial key for an entry
* @return List of matching keys
*/
List<String> findKeyByPartialKey(String partialKey);
/**
* Evicts the cache and key for an entry matching the provided key
*
* @param key the key of the entry you want to evict
*/
void evict(String key);
}
@Service
public class CacheEvictionServiceImpl implements CacheEvictionService {
LinkedHashSet<String> cachedKeys = new LinkedHashSet<>();
@Override
public void addKeyToList(String key) {
this.cachedKeys.add(key);
}
@Override
public List<String> findKeyByPartialKey(String partialKey) {
List<String> foundKeys = new ArrayList<>();
for (String cachedKey : this.cachedKeys) {
if (cachedKey.contains(partialKey)) {
foundKeys.add(cachedKey);
}
}
return foundKeys;
}
@Override
@CacheEvict(value = {"valueCodes", "fieldCodes", "qi", "fieldNames", "fieldsByType"}, key = "#key")
public void evict(String key) {
this.cachedKeys.remove(key);
}
}
不要使用多个键,而是将不同的键连接成一个字符串
@Cacheable(cacheNames = "valueCodes", key = "#value.concat(#fieldId).concat(#projectId)")
每次缓存内容时将密钥发送到服务
cacheEvictionService.addKeyToList(StringUtils.join(value, fieldId, projectId));
遍历每个包含项目 ID(或任何其他键)的现有键
for (String cachedKey : cacheEvictionService.findKeyByPartialKey(projectId)) {
cacheEvictionService.evict(cachedKey);
}
在我的应用程序中,我有多个具有多个键的可缓存方法:
@Cacheable(cacheNames = "valueCodes", key = "{#value, #fieldId, #projectId}")
@Cacheable(cacheNames = "fieldNames", key = "{#field, #value, #projectId}")
@Cacheable(cacheNames = "qi", key = "{#langCode, #question, #projectId}")
@Cacheable(cacheNames = "fieldCodes", key = "{#name, #projectId}")
现在我想要一个 cachevict 方法来清除所有缓存,其中 只有 #projectId 键,它是一个 UUID,匹配:
@CacheEvict(value = {"valueCodes", "fieldCodes", "qi"; "fieldCodes"}, key = "#projectId")
我在 this 文章中读到这是不可能的
Only the evict annotation's key regex matching more than one element in each of the cacheNames
我不太确定他们的意思,但我想这与在 SpEL.
中使用正则表达式有关所以我开始考虑将我的密钥连接成一个密钥:
@Cacheable(cacheNames="cahceName", key="concat(#projectId).concat(#otherKey)")
并使用正则表达式将所有键与 projectId 后跟通配符相匹配。但是我真的找不到办法做到这一点。
我想要实现的目标可行吗?如果是这样,我该怎么做?
Is what I'm trying to accomplish possible? If so, how do I do this?
你喜欢做的事是不可能的。
一般来说,缓存的作用类似于散列table,您只能对唯一键进行操作。选择属于项目 ID 的所有内容都需要缓存中的索引和查询机制。有些缓存有,但不是全部,并且没有通用标准如何完成。
仔细检查单独缓存属于项目的所有点点滴滴是否真的有意义。如果所有东西都需要一起驱逐,也许它一直都在一起使用。或者,例如,在缓存中保留一个 ConcurrentHashMap
作为值,该缓存包含属于项目的各种组件。
更多信息,请参阅问题:
可能删除注释并直接使用缓存是有意义的。带注解的选项有限
我创建了一个为我管理密钥的 bean,而不是使用注释通过部分密钥查找密钥
- 我删除了所有@CacheEvict 注释。
创建了一个新服务来管理我们所有缓存的逐出
public interface CacheEvictionService { /** * Adds the provided key to a global list of keys that we'll need later for eviction * * @param key the cached key for any entry */ void addKeyToList(String key); /** * Find keys that contain the partial key * * @param partialKey the cached partial key for an entry * @return List of matching keys */ List<String> findKeyByPartialKey(String partialKey); /** * Evicts the cache and key for an entry matching the provided key * * @param key the key of the entry you want to evict */ void evict(String key); } @Service public class CacheEvictionServiceImpl implements CacheEvictionService { LinkedHashSet<String> cachedKeys = new LinkedHashSet<>(); @Override public void addKeyToList(String key) { this.cachedKeys.add(key); } @Override public List<String> findKeyByPartialKey(String partialKey) { List<String> foundKeys = new ArrayList<>(); for (String cachedKey : this.cachedKeys) { if (cachedKey.contains(partialKey)) { foundKeys.add(cachedKey); } } return foundKeys; } @Override @CacheEvict(value = {"valueCodes", "fieldCodes", "qi", "fieldNames", "fieldsByType"}, key = "#key") public void evict(String key) { this.cachedKeys.remove(key); } }
不要使用多个键,而是将不同的键连接成一个字符串
@Cacheable(cacheNames = "valueCodes", key = "#value.concat(#fieldId).concat(#projectId)")
每次缓存内容时将密钥发送到服务
cacheEvictionService.addKeyToList(StringUtils.join(value, fieldId, projectId));
遍历每个包含项目 ID(或任何其他键)的现有键
for (String cachedKey : cacheEvictionService.findKeyByPartialKey(projectId)) { cacheEvictionService.evict(cachedKey); }