亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

擴展spring cache 支持緩存多租戶及其自動過期

hover_lew / 1972人閱讀

摘要:在多租戶下租戶所請求的并不是同一入?yún)㈦m然看起來參數(shù)名參數(shù)值都是一樣的,更不能返回同一個結果。默認的根據(jù)入?yún)韰^(qū)分不能滿足多租戶系統(tǒng)的設計需求不能實現(xiàn)根據(jù)租戶隔離。

spring cache 的概念

Spring 支持基于注釋(annotation)的緩存(cache)技術,它本質(zhì)上不是一個具體的緩存實現(xiàn)方案(例如 EHCache 或者 OSCache),而是一個對緩存使用的抽象,通過在既有代碼中添加少量它定義的各種 annotation,即能夠達到緩存方法的返回對象的效果。

@Cacheable 使用效果 ,更具 cacheName(value) + 請求入?yún)?(key) 組成保存redis中的key

public class PigxClientDetailsService extends JdbcClientDetailsService {
    @Cacheable(value = SecurityConstants.CLIENT_DETAILS_KEY, key = "#clientId")
    public ClientDetails loadClientByClientId(String clientId) {
        return super.loadClientByClientId(clientId);
    }
}}

多租戶下緩存問題分析

默認情況 A租戶入?yún)镵1 請求 應用,spring cache 會自動緩存 K1 的值,如果B租戶 入?yún)⑼瑫r為K1 請求應用時,spring cache 還是會自動關聯(lián)到同一個 Redis K1 上邊查詢數(shù)據(jù)。

在多租戶下 A/B 租戶所請求的K1 并不是同一入?yún)ⅲm然看起來參數(shù)名 參數(shù)值都是一樣的),更不能返回同一個結果。

默認的spring cache 根據(jù)入?yún)韰^(qū)分 不能滿足多租戶系統(tǒng)的設計需求,不能實現(xiàn)根據(jù)租戶隔離。

區(qū)分緩存增加租戶標識

A租戶入?yún)镵1 ,spring cache 維護Redis Key 在拼接一個租戶信息

KEY = cacheName + 入?yún)?+ 租戶標識

這樣A/B 租戶請求參數(shù)相同時,讀取的也是不同的Key 里面的值,避免數(shù)據(jù)臟讀,保證隔離型

重寫Spring Cache 的 cacheManager 緩存管理器

從上下文中獲取租戶ID,重寫@Cacheable value 值即可完成,然后注入這個 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);
    }
}

為什么要用 StrUtil.COLON 即 ":" 分割

在GUI 工具中,會通過":"的分隔符,進行分組,展示效果會更好

增加 spring cache 的主動過期功能

默認的注解里面沒有關于時間的入?yún)?,如下圖

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;

}

還是以value作為入口 value = "menu_details#2000" 通過對vaue 追加一個數(shù)字 并通過特殊字符分割,作為過期時間入?yún)?/p>

@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);
    }
}

重寫cachemanager 另個重要的方法 創(chuàng)建緩存的方法,通過截取 value 中設置的過期時間,賦值給你RedisCacheConfiguration

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);
    }
}

spring cache 操作緩存時 獲取到上步設置的ttl 賦值給key

    @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());
    }
總結

通過對spring cache 的擴展即可實現(xiàn)對緩存 一些透明操作

cachemanager 是springcache 對外提供的API 擴展入口

以上源碼參考個人項目 基于Spring Cloud、OAuth2.0開發(fā)基于Vue前后分離的開發(fā)平臺

QQ: 2270033969 一起來聊聊你們是咋用 spring cloud 的吧。

歡迎關注我們的公眾號獲得更多的好玩JavaEE 實踐

文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://www.ezyhdfw.cn/yun/73932.html

相關文章

  • Spring Data Redis 讓 NoSQL 快如閃電 (1)

    摘要:以遠程緩存服務器見長,對易揮發(fā)數(shù)據(jù)來說是極快型數(shù)據(jù)庫。即使成功寫入數(shù)據(jù)庫,最后也可能會因為網(wǎng)絡故障而使得緩存服務器以失敗告終。 【編者按】本文作者為 Xinyu Liu,詳細介紹了 Redis 的特性,并輔之以豐富的用例。在本文的第一部分,將重點概述 Redis 的方方面面。文章系國內(nèi) ITOM 管理平臺 OneAPM 編譯呈現(xiàn)。 建立在 Java 企業(yè)版之上的多層體系結構是強大的服務...

    JerryC 評論0 收藏0
  • java | Spring Boot 與 Redis 實現(xiàn) Cache 以及 Session 共享

    摘要:完成狀態(tài)編寫中已完成維護中原文是一個使用編寫的開源支持網(wǎng)絡基于內(nèi)存可選持久性的鍵值對存儲數(shù)據(jù)庫維基百科是目前業(yè)界使用廣泛的基于內(nèi)存的數(shù)據(jù)庫。 完成狀態(tài) [ ] 編寫中 [ ] 已完成 [x] 維護中 原文 Redis Redis是一個使用ANSI C編寫的開源、支持網(wǎng)絡、基于內(nèi)存、可選持久性的鍵值對存儲數(shù)據(jù)庫 ------ 維基百科 Redis 是目前業(yè)界使用廣泛的基于內(nèi)存的...

    ssshooter 評論0 收藏0
  • 用友云微服務架構下配置文件管理利器:配置中心

    摘要:而且,用友云配置中心以服務的方式提供統(tǒng)一的管理界面,結合用友云的認證中心可以提供可靠的安全保障。 微服務架構是這幾年IT領域的一個高頻詞匯,越來越多的項目和應用正在以微服務的思想進行重構。相比于單體應用和SOA架構,微服務優(yōu)勢也逐漸凸顯,被廣大架構師和技術人員引入和推崇。當然,單體應用、SOA、微服務等各有優(yōu)勢和不足。單體架構在早期的企業(yè)內(nèi)部信息化或者搭建中小型項目時很常見,簡單說就是...

    jayce 評論0 收藏0
  • Spring Boot 參考指南(通用的應用程序?qū)傩?①)

    摘要:第章附錄附錄通用的應用程序?qū)傩钥梢栽谖募?,文件,或作為命令行開關,中指定各種屬性,本附錄提供了一個通用的屬性列表和對使用它們的底層類的引用。本示例文件僅作為指南,不要將整個內(nèi)容復制粘貼到應用程序中,相反,只選擇你需要的屬性。 第X章. 附錄 附錄A. 通用的應用程序?qū)傩?可以在application.properties文件,application.yml文件,或作為命令行開關,中指定...

    ispring 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<