拡張spring cacheはキャッシュマルチテナントとその自動期限切れをサポートする
4873 ワード
Spring cacheの概念
Springは、本質的にはEHCacheやOSCacheなどの特定のキャッシュ実装スキームではなく、既存のコードに定義された様々なannotationを少量追加することで、キャッシュメソッドの戻りオブジェクトの効果を達成することができる、アノテーションベースのキャッシュ技術をサポートする.@Cacheableの使用効果により、cacheName+要求インパラメータ(key)からなるredisに保存されたkey
マルチテナントでのキャッシュの問題分析デフォルトAテナントインパラメータはK 1リクエストアプリケーションであり、spring cacheはK 1の値を自動的にキャッシュし、BテナントインパラメータがK 1リクエストアプリケーションである場合、spring cacheは同じRedis K 1上のクエリーデータに自動的に関連付けられます. マルチテナントの下でA/Bテナントが要求するK 1は同じパラメータではなく(パラメータ名パラメータ値は同じように見えるが)、同じ結果を返すことはできない. デフォルトのspring cacheは、パラメータに基づいてマルチテナントシステムの設計要件を満たすことができず、テナントによる隔離を実現できないことを区別します.
区分キャッシュ増加テナントID AテナントはK 1に登録され、spring cacheはRedis Keyがテナント情報 を接続することを維持する. KEY=cacheName+入参+テナントID このようなA/Bテナント要求パラメータとは同時に、読み出したものも異なるKeyの中の値であり、データの汚れた読み取りを回避し、隔離型 を保証する.
Spring CacheのcacheManagerキャッシュを書き換えるコンテキストからテナントIDを取得し、@Cacheable value値を書き換えると完了し、このcacheManager に注入する.なぜStrUtil.COLOONである':'分割 GUIツールでは、':'の区切り文字でグループ化され、より効果的に表示されます.
スプリングcacheのアクティブな期限切れ機能を追加デフォルトの注記には、次の図 のように時間に関するパラメータはありません.またはvalueを入口とするvalue="menu_details#2000"は、vaueに数字を追加して特殊文字で分割することにより、期限切れとして を参照する. cachemanager別の重要なメソッドを書き換えてキャッシュを作成するメソッドです.valueで設定された期限切れを切り取ることで、RedisCacheConfiguration に値を割り当てます. spring cache操作キャッシュ時に前のステップで設定したttl付与をkey に取得する.
まとめ spring cacheの拡張により、キャッシュに対するいくつかの透明な操作 を実現することができる. cachemanagerはspringcacheが対外的に提供するAPI拡張エントリ である.以上のソースコードリファレンス個人プロジェクトSpring Cloud、OAuth 2.0に基づいてVue前後分離に基づく開発プラットフォーム を開発する. QQ:2270033969 spring cloudの使い方について話しましょう. 私たちの公衆番号に注目してもっと面白いJavaEE実践 を獲得することを歓迎します.
Springは、本質的にはEHCacheやOSCacheなどの特定のキャッシュ実装スキームではなく、既存のコードに定義された様々なannotationを少量追加することで、キャッシュメソッドの戻りオブジェクトの効果を達成することができる、アノテーションベースのキャッシュ技術をサポートする.
public class PigxClientDetailsService extends JdbcClientDetailsService {
@Cacheable(value = SecurityConstants.CLIENT_DETAILS_KEY, key = "#clientId")
public ClientDetails loadClientByClientId(String clientId) {
return super.loadClientByClientId(clientId);
}
}}
マルチテナントでのキャッシュの問題分析
区分キャッシュ増加テナントID
Spring CacheのcacheManagerキャッシュを書き換える
@Slf4j
public class RedisAutoCacheManager extends RedisCacheManager {
/**
* ID, @Cacheable value
* @param name
* @return
*/
@Override
public Cache getCache(String name) {
return super.getCache(TenantContextHolder.getTenantId() + StrUtil.COLON + name);
}
}
スプリングcacheのアクティブな期限切れ機能を追加
public @interface Cacheable {
@AliasFor("cacheNames")
String[] value() default {};
@AliasFor("value")
String[] cacheNames() default {};
String key() default "";
String keyGenerator() default "";
String cacheManager() default "";
String cacheResolver() default "";
String condition() default "";
String unless() default "";
boolean sync() default false;
}
@Service
@AllArgsConstructor
public class PigXMenuServiceImpl extends ServiceImpl implements SysMenuService {
private final SysRoleMenuMapper sysRoleMenuMapper;
@Override
@Cacheable(value = "menu_details#2000", key = "#roleId + '_menu'")
public List findMenuByRoleId(Integer roleId) {
return baseMapper.listMenusByRoleId(roleId);
}
}
public class RedisAutoCacheManager extends RedisCacheManager {
private static final String SPLIT_FLAG = "#";
private static final int CACHE_LENGTH = 2;
@Override
protected RedisCache createRedisCache(String name, @Nullable RedisCacheConfiguration cacheConfig) {
if (StrUtil.isBlank(name) || !name.contains(SPLIT_FLAG)) {
return super.createRedisCache(name, cacheConfig);
}
String[] cacheArray = name.split(SPLIT_FLAG);
if (cacheArray.length < CACHE_LENGTH) {
return super.createRedisCache(name, cacheConfig);
}
if (cacheConfig != null) {
long cacheAge = Long.parseLong(cacheArray[1]);
cacheConfig = cacheConfig.entryTtl(Duration.ofSeconds(cacheAge));
}
return super.createRedisCache(name, cacheConfig);
}
}
@Override
public void put(Object key, @Nullable Object value) {
Object cacheValue = preProcessCacheValue(value);
if (!isAllowNullValues() && cacheValue == null) {
throw new IllegalArgumentException(String.format(
"Cache '%s' does not allow 'null' values. Avoid storing null via '@Cacheable(unless=\"#result == null\")' or configure RedisCache to allow 'null' via RedisCacheConfiguration.",
name));
}
cacheWriter.put(name, createAndConvertCacheKey(key), serializeCacheValue(cacheValue), cacheConfig.getTtl());
}
まとめ