成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

擴(kuò)展spring cache 支持緩存多租戶及其自動(dòng)過期

hover_lew / 1908人閱讀

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

spring cache 的概念

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

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

多租戶下緩存問題分析

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

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

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

區(qū)分緩存增加租戶標(biāo)識(shí)

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

KEY = cacheName + 入?yún)?+ 租戶標(biāo)識(shí)

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

重寫Spring Cache 的 cacheManager 緩存管理器

從上下文中獲取租戶ID,重寫@Cacheable value 值即可完成,然后注入這個(gè) 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 工具中,會(huì)通過":"的分隔符,進(jìn)行分組,展示效果會(huì)更好

增加 spring cache 的主動(dòng)過期功能

默認(rèn)的注解里面沒有關(guān)于時(shí)間的入?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 追加一個(gè)數(shù)字 并通過特殊字符分割,作為過期時(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 另個(gè)重要的方法 創(chuàng)建緩存的方法,通過截取 value 中設(shè)置的過期時(shí)間,賦值給你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 操作緩存時(shí) 獲取到上步設(shè)置的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());
    }
總結(jié)

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

cachemanager 是springcache 對外提供的API 擴(kuò)展入口

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

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

歡迎關(guān)注我們的公眾號(hào)獲得更多的好玩JavaEE 實(shí)踐

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/73932.html

相關(guān)文章

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

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

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

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

    ssshooter 評論0 收藏0
  • 用友云微服務(wù)架構(gòu)下配置文件管理利器:配置中心

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

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

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

    ispring 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<