<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          「性能提升」擴(kuò)展 Spring Cache 支持多級(jí)緩存

          共 3518字,需瀏覽 8分鐘

           ·

          2020-09-28 13:00

          為什么多級(jí)緩存

          緩存的引入是現(xiàn)在大部分系統(tǒng)所必須考慮的

          • redis 作為常用中間件,雖然我們一般業(yè)務(wù)系統(tǒng)(畢竟業(yè)務(wù)量有限)不會(huì)遇到如下圖 在隨著 data-size 的增大和數(shù)據(jù)結(jié)構(gòu)的復(fù)雜的造成性能下降,但網(wǎng)絡(luò) IO 消耗會(huì)成為整個(gè)調(diào)用鏈路中不可忽視的部分。尤其在 微服務(wù)架構(gòu)中,一次調(diào)用往往會(huì)涉及多次調(diào)用 例如pig oauth2.0 的 client 認(rèn)證[1]
          • Caffeine 來(lái)自未來(lái)的本地內(nèi)存緩存,性能比如常見(jiàn)的內(nèi)存緩存實(shí)現(xiàn)性能高出不少詳細(xì)對(duì)比[2]

          綜合所述:我們需要構(gòu)建 L1 Caffeine JVM 級(jí)別緩存 , L2 Redis 緩存。

          設(shè)計(jì)難點(diǎn)

          目前大部分應(yīng)用緩存都是基于 Spring Cache 實(shí)現(xiàn),基于注解(annotation)的緩存(cache)技術(shù),存在的問(wèn)題如下:

          • Spring Cache 僅支持 單一的緩存來(lái)源,即:只能選擇 Redis 實(shí)現(xiàn)或者 Caffeine 實(shí)現(xiàn),并不能同時(shí)使用。
          • 數(shù)據(jù)一致性:各層緩存之間的數(shù)據(jù)一致性問(wèn)題,如應(yīng)用層緩存和分布式緩存之前的數(shù)據(jù)一致性問(wèn)題。
          • 緩存過(guò)期:Spring Cache 不支持主動(dòng)的過(guò)期策略

          業(yè)務(wù)流程

          如何使用


            1. 引入依賴
          <dependency>
          ????<groupId>com.pig4cloud.plugingroupId>
          ????<artifactId>multilevel-cache-spring-boot-starterartifactId>
          ????<version>0.0.1version>
          dependency>

            1. 開(kāi)啟緩存支持
          @EnableCaching
          public?class?App?{
          ?public?static?void?main(String[]?args)?{
          ??SpringApplication.run(App.class,?args);
          ?}
          }

            1. 目標(biāo)接口聲明 Spring Cache 注解
          @Cacheable(value?=?"get",key?=?"#key")
          @GetMapping("/get")
          public?String?get(String?key){
          ????return?"success";
          }

          性能比較

          為保證性能 redis 在 127.0.0.1 環(huán)路安裝

          • OS: macOS Mojave
          • CPU: 2.3 GHz Intel Core i5
          • RAM: 8 GB 2133 MHz LPDDR3
          • JVM: corretto_11.jdk
          BenchmarkModeCntScoreUnits
          多級(jí)實(shí)現(xiàn)thrpt22716.074ops/s
          默認(rèn) redisthrpt21373.476ops/s

          代碼原理

            1. 自定義 CacheManager 多級(jí)緩存實(shí)現(xiàn)
          public?class?RedisCaffeineCacheManager?implements?CacheManager?{

          ?@Override
          ?public?Cache?getCache(String?name)?{
          ??Cache?cache?=?cacheMap.get(name);
          ??if?(cache?!=?null)?{
          ???return?cache;
          ??}
          ??cache?=?new?RedisCaffeineCache(name,?stringKeyRedisTemplate,?caffeineCache(),?cacheConfigProperties);
          ??Cache?oldCache?=?cacheMap.putIfAbsent(name,?cache);
          ??log.debug("create?cache?instance,?the?cache?name?is?:?{}",?name);
          ??return?oldCache?==?null???cache?:?oldCache;
          ?}
          }
          • 多級(jí)讀取、過(guò)期策略實(shí)現(xiàn)


          public?class?RedisCaffeineCache?extends?AbstractValueAdaptingCache?{
          ?protected?Object?lookup(Object?key)?{
          ??Object?cacheKey?=?getKey(key);

          ????//?1.?先調(diào)用?caffeine?查詢是否存在指定的值
          ??Object?value?=?caffeineCache.getIfPresent(key);
          ??if?(value?!=?null)?{
          ???log.debug("get?cache?from?caffeine,?the?key?is?:?{}",?cacheKey);
          ???return?value;
          ??}

          ????//?2.?調(diào)用?redis?查詢?cè)谥付ǖ闹?/span>
          ??value?=?stringKeyRedisTemplate.opsForValue().get(cacheKey);

          ??if?(value?!=?null)?{
          ???log.debug("get?cache?from?redis?and?put?in?caffeine,?the?key?is?:?{}",?cacheKey);
          ???caffeineCache.put(key,?value);
          ??}
          ??return?value;
          ?}
          }

            1. 過(guò)期策略,所有更新操作都基于 redis pub/sub 消息機(jī)制更新
          public?class?RedisCaffeineCache?extends?AbstractValueAdaptingCache?{
          ?@Override
          ?public?void?put(Object?key,?Object?value)?{
          ??push(new?CacheMessage(this.name,?key));
          ?}

          ?@Override
          ?public?ValueWrapper?putIfAbsent(Object?key,?Object?value)?{
          ????push(new?CacheMessage(this.name,?key));
          ?}

          ?@Override
          ?public?void?evict(Object?key)?{
          ??push(new?CacheMessage(this.name,?key));
          ?}

          ?@Override
          ?public?void?clear()?{
          ??push(new?CacheMessage(this.name,?null));
          ?}

          ?private?void?push(CacheMessage?message)?{
          ??stringKeyRedisTemplate.convertAndSend(topic,?message);
          ?}
          }

            1. MessageListener 刪除指定 Caffeine 的指定值
          public?class?CacheMessageListener?implements?MessageListener?{

          ?private?final?RedisTemplate?redisTemplate;

          ?private?final?RedisCaffeineCacheManager?redisCaffeineCacheManager;

          ?@Override
          ?public?void?onMessage(Message?message,?byte[]?pattern)?{
          ??CacheMessage?cacheMessage?=?(CacheMessage)?redisTemplate.getValueSerializer().deserialize(message.getBody());
          ????cacheMessage.getCacheName(),?cacheMessage.getKey());
          ??redisCaffeineCacheManager.clearLocal(cacheMessage.getCacheName(),?cacheMessage.getKey());
          ?}
          }

          源碼地址

          https://github.com/pig-mesh/multilevel-cache-spring-boot-starter

          參考資料

          [1]

          pig oauth2.0 的 client 認(rèn)證: https://gitee.com/log4j/pig

          [2]

          詳細(xì)對(duì)比: https://github.com/ben-manes/caffeine/wiki/Benchmarks


          瀏覽 75
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  艹逼一区| 麻豆成人精品av 麻豆精品无码视频 | 一级电影动态图片 | 色天使av| 激情性爱视频网站 |