国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频

Caffeine Cache-高性能Java本地緩存之王

共 28365字,需瀏覽 57分鐘

 ·

2024-04-12 02:00


前面剛說到Guava Cache,他的優(yōu)點(diǎn)是封裝了get,put操作;提供線程安全的緩存操作;提供過期策略;提供回收策略;緩存監(jiān)控。當(dāng)緩存的數(shù)據(jù)超過最大值時(shí),使用LRU算法替換。這一篇我們將要談到一個(gè)新的本地緩存框架:Caffeine Cache。它也是站在巨人的肩膀上-Guava Cache,借著他的思想優(yōu)化了算法發(fā)展而來。

本篇博文主要介紹Caffine Cache 的使用方式,以及Caffine Cache在SpringBoot中的使用。

Caffine Cache 在算法上的優(yōu)點(diǎn)-W-TinyLFU

說到優(yōu)化,Caffine Cache到底優(yōu)化了什么呢?我們剛提到過LRU,常見的緩存淘汰算法還有FIFO,LFU:

  • FIFO:先進(jìn)先出,在這種淘汰算法中,先進(jìn)入緩存的會(huì)先被淘汰,會(huì)導(dǎo)致命中率很低。
  • LRU:最近最少使用算法,每次訪問數(shù)據(jù)都會(huì)將其放在我們的隊(duì)尾,如果需要淘汰數(shù)據(jù),就只需要淘汰隊(duì)首即可。仍然有個(gè)問題,如果有個(gè)數(shù)據(jù)在 1 分鐘訪問了 1000次,再后 1 分鐘沒有訪問這個(gè)數(shù)據(jù),但是有其他的數(shù)據(jù)訪問,就導(dǎo)致了我們這個(gè)熱點(diǎn)數(shù)據(jù)被淘汰。
  • LFU:最近最少頻率使用,利用額外的空間記錄每個(gè)數(shù)據(jù)的使用頻率,然后選出頻率最低進(jìn)行淘汰。這樣就避免了 LRU 不能處理時(shí)間段的問題。

上面三種策略各有利弊,實(shí)現(xiàn)的成本也是一個(gè)比一個(gè)高,同時(shí)命中率也是一個(gè)比一個(gè)好。Guava Cache雖然有這么多的功能,但是本質(zhì)上還是對LRU的封裝,如果有更優(yōu)良的算法,并且也能提供這么多功能,相比之下就相形見絀了。

「LFU的局限性」:在 LFU 中只要數(shù)據(jù)訪問模式的概率分布隨時(shí)間保持不變時(shí),其命中率就能變得非常高。比如有部新劇出來了,我們使用 LFU 給他緩存下來,這部新劇在這幾天大概訪問了幾億次,這個(gè)訪問頻率也在我們的 LFU 中記錄了幾億次。但是新劇總會(huì)過氣的,比如一個(gè)月之后這個(gè)新劇的前幾集其實(shí)已經(jīng)過氣了,但是他的訪問量的確是太高了,其他的電視劇根本無法淘汰這個(gè)新劇,所以在這種模式下是有局限性。

「LRU的優(yōu)點(diǎn)和局限性」:LRU可以很好的應(yīng)對突發(fā)流量的情況,因?yàn)樗恍枰塾?jì)數(shù)據(jù)頻率。但LRU通過歷史數(shù)據(jù)來預(yù)測未來是局限的,它會(huì)認(rèn)為最后到來的數(shù)據(jù)是最可能被再次訪問的,從而給與它最高的優(yōu)先級。

在現(xiàn)有算法的局限性下,會(huì)導(dǎo)致緩存數(shù)據(jù)的命中率或多或少的受損,而命中略又是緩存的重要指標(biāo)。HighScalability網(wǎng)站刊登了一篇文章,由前Google工程師發(fā)明的W-TinyLFU——一種現(xiàn)代的緩存 。Caffine Cache就是基于此算法而研發(fā)。Caffeine 因使用 Window TinyLfu 回收策略,提供了一個(gè)近乎最佳的命中率。

當(dāng)數(shù)據(jù)的訪問模式不隨時(shí)間變化的時(shí)候,LFU的策略能夠帶來最佳的緩存命中率。然而LFU有兩個(gè)缺點(diǎn):

  • 首先,它需要給每個(gè)記錄項(xiàng)維護(hù)頻率信息,每次訪問都需要更新,這是個(gè)巨大的開銷;

  • 其次,如果數(shù)據(jù)訪問模式隨時(shí)間有變,LFU的頻率信息無法隨之變化,因此早先頻繁訪問的記錄可能會(huì)占據(jù)緩存,而后期訪問較多的記錄則無法被命中。

因此,大多數(shù)的緩存設(shè)計(jì)都是基于LRU或者其變種來進(jìn)行的。相比之下,LRU并不需要維護(hù)昂貴的緩存記錄元信息,同時(shí)也能夠反應(yīng)隨時(shí)間變化的數(shù)據(jù)訪問模式。然而,在許多負(fù)載之下,LRU依然需要更多的空間才能做到跟LFU一致的緩存命中率。因此,一個(gè)“現(xiàn)代”的緩存,應(yīng)當(dāng)能夠綜合兩者的長處。

TinyLFU維護(hù)了近期訪問記錄的頻率信息,作為一個(gè)過濾器,當(dāng)新記錄來時(shí),只有滿足TinyLFU要求的記錄才可以被插入緩存。如前所述,作為現(xiàn)代的緩存,它需要解決兩個(gè)挑戰(zhàn):

  • 一個(gè)是如何避免維護(hù)頻率信息的高開銷;

  • 另一個(gè)是如何反應(yīng)隨時(shí)間變化的訪問模式。

首先來看前者,TinyLFU借助了數(shù)據(jù)流Sketching技術(shù),Count-Min Sketch顯然是解決這個(gè)問題的有效手段,它可以用小得多的空間存放頻率信息,而保證很低的False Positive Rate。但考慮到第二個(gè)問題,就要復(fù)雜許多了,因?yàn)槲覀冎溃魏蜸ketching數(shù)據(jù)結(jié)構(gòu)如果要反應(yīng)時(shí)間變化都是一件困難的事情,在Bloom Filter方面,我們可以有Timing Bloom Filter,但對于CMSketch來說,如何做到Timing CMSketch就不那么容易了。TinyLFU采用了一種基于滑動(dòng)窗口的時(shí)間衰減設(shè)計(jì)機(jī)制,借助于一種簡易的reset操作:每次添加一條記錄到Sketch的時(shí)候,都會(huì)給一個(gè)計(jì)數(shù)器上加1,當(dāng)計(jì)數(shù)器達(dá)到一個(gè)尺寸W的時(shí)候,把所有記錄的Sketch數(shù)值都除以2,該reset操作可以起到衰減的作用 。

W-TinyLFU主要用來解決一些稀疏的突發(fā)訪問元素。在一些數(shù)目很少但突發(fā)訪問量很大的場景下,TinyLFU將無法保存這類元素,因?yàn)樗鼈儫o法在給定時(shí)間內(nèi)積累到足夠高的頻率。因此W-TinyLFU就是結(jié)合LFU和LRU,前者用來應(yīng)對大多數(shù)場景,而LRU用來處理突發(fā)流量。

在處理頻率記錄的方案中,你可能會(huì)想到用hashMap去存儲(chǔ),每一個(gè)key對應(yīng)一個(gè)頻率值。那如果數(shù)據(jù)量特別大的時(shí)候,是不是這個(gè)hashMap也會(huì)特別大呢。由此可以聯(lián)想到 Bloom Filter,對于每個(gè)key,用n個(gè)byte每個(gè)存儲(chǔ)一個(gè)標(biāo)志用來判斷key是否在集合中。原理就是使用k個(gè)hash函數(shù)來將key散列成一個(gè)整數(shù)。

在W-TinyLFU中使用Count-Min Sketch記錄我們的訪問頻率,而這個(gè)也是布隆過濾器的一種變種。如下圖所示:

如果需要記錄一個(gè)值,那我們需要通過多種Hash算法對其進(jìn)行處理hash,然后在對應(yīng)的hash算法的記錄中+1,為什么需要多種hash算法呢?由于這是一個(gè)壓縮算法必定會(huì)出現(xiàn)沖突,比如我們建立一個(gè)byte的數(shù)組,通過計(jì)算出每個(gè)數(shù)據(jù)的hash的位置。比如張三和李四,他們兩有可能hash值都是相同,比如都是1那byte[1]這個(gè)位置就會(huì)增加相應(yīng)的頻率,張三訪問1萬次,李四訪問1次那byte[1]這個(gè)位置就是1萬零1,如果取李四的訪問評率的時(shí)候就會(huì)取出是1萬零1,但是李四命名只訪問了1次啊,為了解決這個(gè)問題,所以用了多個(gè)hash算法可以理解為long[][]二維數(shù)組的一個(gè)概念,比如在第一個(gè)算法張三和李四沖突了,但是在第二個(gè),第三個(gè)中很大的概率不沖突,比如一個(gè)算法大概有1%的概率沖突,那四個(gè)算法一起沖突的概率是1%的四次方。通過這個(gè)模式我們?nèi)±钏牡脑L問率的時(shí)候取所有算法中,李四訪問最低頻率的次數(shù)。所以他的名字叫Count-Min Sketch。

使用

Caffeine Cache 的github地址:https://github.com/ben-manes/caffeine

目前的最新版本是:

<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>2.6.2</version>
</dependency>

2.1 緩存填充策略

Caffeine Cache提供了三種緩存填充策略:手動(dòng)、同步加載和異步加載。

「1.手動(dòng)加載」

在每次get key的時(shí)候指定一個(gè)同步的函數(shù),如果key不存在就調(diào)用這個(gè)函數(shù)生成一個(gè)值。

/**
     * 手動(dòng)加載
     * @param key
     * @return
     */

public Object manulOperator(String key) {
    Cache<String, Object> cache = Caffeine.newBuilder()
        .expireAfterWrite(1, TimeUnit.SECONDS)
        .expireAfterAccess(1, TimeUnit.SECONDS)
        .maximumSize(10)
        .build();
    //如果一個(gè)key不存在,那么會(huì)進(jìn)入指定的函數(shù)生成value
    Object value = cache.get(key, t -> setValue(key).apply(key));
    cache.put("hello",value);

    //判斷是否存在如果不存返回null
    Object ifPresent = cache.getIfPresent(key);
    //移除一個(gè)key
    cache.invalidate(key);
    return value;
}

public Function<String, Object> setValue(String key){
    return t -> key + "value";
}

「2. 同步加載」

構(gòu)造Cache時(shí)候,build方法傳入一個(gè)CacheLoader實(shí)現(xiàn)類。實(shí)現(xiàn)load方法,通過key加載value。

/**
     * 同步加載
     * @param key
     * @return
     */

public Object syncOperator(String key){
    LoadingCache<String, Object> cache = Caffeine.newBuilder()
        .maximumSize(100)
        .expireAfterWrite(1, TimeUnit.MINUTES)
        .build(k -> setValue(key).apply(key));
    return cache.get(key);
}

public Function<String, Object> setValue(String key){
    return t -> key + "value";
}

「3. 異步加載」

AsyncLoadingCache是繼承自LoadingCache類的,異步加載使用Executor去調(diào)用方法并返回一個(gè)CompletableFuture。異步加載緩存使用了響應(yīng)式編程模型。

如果要以同步方式調(diào)用時(shí),應(yīng)提供CacheLoader。要以異步表示時(shí),應(yīng)該提供一個(gè)AsyncCacheLoader,并返回一個(gè)CompletableFuture。

 /**
     * 異步加載
     *
     * @param key
     * @return
     */

public Object asyncOperator(String key){
    AsyncLoadingCache<String, Object> cache = Caffeine.newBuilder()
        .maximumSize(100)
        .expireAfterWrite(1, TimeUnit.MINUTES)
        .buildAsync(k -> setAsyncValue(key).get());

    return cache.get(key);
}

public CompletableFuture<Object> setAsyncValue(String key){
    return CompletableFuture.supplyAsync(() -> {
        return key + "value";
    });
}

2.2 回收策略

Caffeine提供了3種回收策略:基于大小回收,基于時(shí)間回收,基于引用回收。

「1. 基于大小的過期方式」

基于大小的回收策略有兩種方式:一種是基于緩存大小,一種是基于權(quán)重。

// 根據(jù)緩存的計(jì)數(shù)進(jìn)行驅(qū)逐
LoadingCache<String, Object> cache = Caffeine.newBuilder()
    .maximumSize(10000)
    .build(key -> function(key));


// 根據(jù)緩存的權(quán)重來進(jìn)行驅(qū)逐(權(quán)重只是用于確定緩存大小,不會(huì)用于決定該緩存是否被驅(qū)逐)
LoadingCache<String, Object> cache1 = Caffeine.newBuilder()
    .maximumWeight(10000)
    .weigher(key -> function1(key))
    .build(key -> function(key));
maximumWeight與maximumSize不可以同時(shí)使用。

「2.基于時(shí)間的過期方式」

// 基于固定的到期策略進(jìn)行退出
LoadingCache<String, Object> cache = Caffeine.newBuilder()
    .expireAfterAccess(5, TimeUnit.MINUTES)
    .build(key -> function(key));
LoadingCache<String, Object> cache1 = Caffeine.newBuilder()
    .expireAfterWrite(10, TimeUnit.MINUTES)
    .build(key -> function(key));

// 基于不同的到期策略進(jìn)行退出
LoadingCache<String, Object> cache2 = Caffeine.newBuilder()
    .expireAfter(new Expiry<String, Object>() {
        @Override
        public long expireAfterCreate(String key, Object value, long currentTime) {
            return TimeUnit.SECONDS.toNanos(seconds);
        }

        @Override
        public long expireAfterUpdate(@Nonnull String s, @Nonnull Object o, long l, long l1) {
            return 0;
        }

        @Override
        public long expireAfterRead(@Nonnull String s, @Nonnull Object o, long l, long l1) {
            return 0;
        }
    }).build(key -> function(key));

Caffeine提供了三種定時(shí)驅(qū)逐策略:

  • expireAfterAccess(long, TimeUnit):在最后一次訪問或者寫入后開始計(jì)時(shí),在指定的時(shí)間后過期。假如一直有請求訪問該key,那么這個(gè)緩存將一直不會(huì)過期。
  • expireAfterWrite(long, TimeUnit): 在最后一次寫入緩存后開始計(jì)時(shí),在指定的時(shí)間后過期。
  • expireAfter(Expiry): 自定義策略,過期時(shí)間由Expiry實(shí)現(xiàn)獨(dú)自計(jì)算。

緩存的刪除策略使用的是惰性刪除和定時(shí)刪除。這兩個(gè)刪除策略的時(shí)間復(fù)雜度都是O(1)。

「3. 基于引用的過期方式」

Java中四種引用類型

// 當(dāng)key和value都沒有引用時(shí)驅(qū)逐緩存
LoadingCache<String, Object> cache = Caffeine.newBuilder()
    .weakKeys()
    .weakValues()
    .build(key -> function(key));

// 當(dāng)垃圾收集器需要釋放內(nèi)存時(shí)驅(qū)逐
LoadingCache<String, Object> cache1 = Caffeine.newBuilder()
    .softValues()
    .build(key -> function(key));

注意:AsyncLoadingCache不支持弱引用和軟引用。

  • Caffeine.weakKeys():使用弱引用存儲(chǔ)key。如果沒有其他地方對該key有強(qiáng)引用,那么該緩存就會(huì)被垃圾回收器回收。由于垃圾回收器只依賴于身份(identity)相等,因此這會(huì)導(dǎo)致整個(gè)緩存使用身份 (==) 相等來比較 key,而不是使用 equals()。

  • Caffeine.weakValues() :使用弱引用存儲(chǔ)value。如果沒有其他地方對該value有強(qiáng)引用,那么該緩存就會(huì)被垃圾回收器回收。由于垃圾回收器只依賴于身份(identity)相等,因此這會(huì)導(dǎo)致整個(gè)緩存使用身份 (==) 相等來比較 key,而不是使用 equals()。

  • Caffeine.softValues() :使用軟引用存儲(chǔ)value。當(dāng)內(nèi)存滿了過后,軟引用的對象以將使用最近最少使用(least-recently-used ) 的方式進(jìn)行垃圾回收。由于使用軟引用是需要等到內(nèi)存滿了才進(jìn)行回收,所以我們通常建議給緩存配置一個(gè)使用內(nèi)存的最大值。softValues() 將使用身份相等(identity) (==) 而不是equals() 來比較值。

Caffeine.weakValues()和Caffeine.softValues()不可以一起使用。

「3. 移除事件監(jiān)聽」

Cache<String, Object> cache = Caffeine.newBuilder()
    .removalListener((String key, Object value, RemovalCause cause) ->
                     System.out.printf("Key %s was removed (%s)%n", key, cause))
    .build();

「4. 寫入外部存儲(chǔ)」

CacheWriter 方法可以將緩存中所有的數(shù)據(jù)寫入到第三方。

LoadingCache<String, Object> cache2 = Caffeine.newBuilder()
    .writer(new CacheWriter<String, Object>() {
        @Override public void write(String key, Object value) {
            // 寫入到外部存儲(chǔ)
        }
        @Override public void delete(String key, Object value, RemovalCause cause) {
            // 刪除外部存儲(chǔ)
        }
    })
    .build(key -> function(key));

如果你有多級緩存的情況下,這個(gè)方法還是很實(shí)用。

注意:CacheWriter不能與弱鍵或AsyncLoadingCache一起使用。

「5. 統(tǒng)計(jì)」

與Guava Cache的統(tǒng)計(jì)一樣。

Cache<String, Object> cache = Caffeine.newBuilder()
    .maximumSize(10_000)
    .recordStats()
    .build();

通過使用Caffeine.recordStats(), 可以轉(zhuǎn)化成一個(gè)統(tǒng)計(jì)的集合. 通過 Cache.stats() 返回一個(gè)CacheStats。CacheStats提供以下統(tǒng)計(jì)方法:

  • hitRate(): 返回緩存命中率

  • evictionCount(): 緩存回收數(shù)量

  • averageLoadPenalty(): 加載新值的平均時(shí)間

SpringBoot 中默認(rèn)Cache-Caffine Cache

SpringBoot 1.x版本中的默認(rèn)本地cache是Guava Cache。在2.x(Spring Boot 2.0(spring 5) )版本中已經(jīng)用Caffine Cache取代了Guava Cache。畢竟有了更優(yōu)的緩存淘汰策略。

下面我們來說在SpringBoot2.x版本中如何使用cache。

引入依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>2.6.2</version>
</dependency>

添加注解開啟緩存支持

添加@EnableCaching注解:

@SpringBootApplication
@EnableCaching
public class SingleDatabaseApplication {

    public static void main(String[] args) {
        SpringApplication.run(SingleDatabaseApplication.class, args);
    }
}

配置文件的方式注入相關(guān)參數(shù)

properties文件

spring.cache.cache-names=cache1
spring.cache.caffeine.spec=initialCapacity=50,maximumSize=500,expireAfterWrite=10s

或Yaml文件

spring:
  cache:
    type: caffeine
    cache-names:
    - userCache
    caffeine:
      spec: maximumSize=1024,refreshAfterWrite=60s

如果使用refreshAfterWrite配置,必須指定一個(gè)CacheLoader.不用該配置則無需這個(gè)bean,如上所述,該CacheLoader將關(guān)聯(lián)被該緩存管理器管理的所有緩存,所以必須定義為CacheLoader<Object, Object>,自動(dòng)配置將忽略所有泛型類型。

import com.github.benmanes.caffeine.cache.CacheLoader;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author: rickiyang
 * @date: 2019/6/15
 * @description:
 */

@Configuration
public class CacheConfig {

    /**
     * 相當(dāng)于在構(gòu)建LoadingCache對象的時(shí)候 build()方法中指定過期之后的加載策略方法
     * 必須要指定這個(gè)Bean,refreshAfterWrite=60s屬性才生效
     * @return
     */

    @Bean
    public CacheLoader<String, Object> cacheLoader() {
        CacheLoader<String, Object> cacheLoader = new CacheLoader<String, Object>() {
            @Override
            public Object load(String key) throws Exception {
                return null;
            }
            // 重寫這個(gè)方法將oldValue值返回回去,進(jìn)而刷新緩存
            @Override
            public Object reload(String key, Object oldValue) throws Exception {
                return oldValue;
            }
        };
        return cacheLoader;
    }
}

Caffeine常用配置說明:

  • initialCapacity=[integer]: 初始的緩存空間大小

  • maximumSize=[long]: 緩存的最大條數(shù)

  • maximumWeight=[long]: 緩存的最大權(quán)重

  • expireAfterAccess=[duration]: 最后一次寫入或訪問后經(jīng)過固定時(shí)間過期

  • expireAfterWrite=[duration]: 最后一次寫入后經(jīng)過固定時(shí)間過期

  • refreshAfterWrite=[duration]: 創(chuàng)建緩存或者最近一次更新緩存后經(jīng)過固定的時(shí)間間隔,刷新緩存

  • weakKeys: 打開key的弱引用

  • weakValues:打開value的弱引用

  • softValues:打開value的軟引用

  • recordStats:開發(fā)統(tǒng)計(jì)功能

注意:

  • expireAfterWrite和expireAfterAccess同時(shí)存在時(shí),以expireAfterWrite為準(zhǔn)。

  • maximumSize和maximumWeight不可以同時(shí)使用

  • weakValues和softValues不可以同時(shí)使用

需要說明的是,使用配置文件的方式來進(jìn)行緩存項(xiàng)配置,一般情況能滿足使用需求,但是靈活性不是很高,如果我們有很多緩存項(xiàng)的情況下寫起來會(huì)導(dǎo)致配置文件很長。所以一般情況下你也可以選擇使用bean的方式來初始化Cache實(shí)例。

下面的演示使用bean的方式來注入:

package com.rickiyang.learn.cache;

import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.apache.commons.compress.utils.Lists;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author: rickiyang
 * @date: 2019/6/15
 * @description:
 */

@Configuration
public class CacheConfig {


    /**
     * 創(chuàng)建基于Caffeine的Cache Manager
     * 初始化一些key存入
     * @return
     */

    @Bean
    @Primary
    public CacheManager caffeineCacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        ArrayList<CaffeineCache> caches = Lists.newArrayList();
        List<CacheBean> list = setCacheBean();
        for(CacheBean cacheBean : list){
            caches.add(new CaffeineCache(cacheBean.getKey(),
                    Caffeine.newBuilder().recordStats()
                            .expireAfterWrite(cacheBean.getTtl(), TimeUnit.SECONDS)
                            .maximumSize(cacheBean.getMaximumSize())
                            .build()));
        }
        cacheManager.setCaches(caches);
        return cacheManager;
    }


    /**
     * 初始化一些緩存的 key
     * @return
     */

    private List<CacheBean> setCacheBean(){
        List<CacheBean> list = Lists.newArrayList();
        CacheBean userCache = new CacheBean();
        userCache.setKey("userCache");
        userCache.setTtl(60);
        userCache.setMaximumSize(10000);

        CacheBean deptCache = new CacheBean();
        deptCache.setKey("userCache");
        deptCache.setTtl(60);
        deptCache.setMaximumSize(10000);

        list.add(userCache);
        list.add(deptCache);

        return list;
    }

    class CacheBean {
        private String key;
        private long ttl;
        private long maximumSize;

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public long getTtl() {
            return ttl;
        }

        public void setTtl(long ttl) {
            this.ttl = ttl;
        }

        public long getMaximumSize() {
            return maximumSize;
        }

        public void setMaximumSize(long maximumSize) {
            this.maximumSize = maximumSize;
        }
    }

}

創(chuàng)建了一個(gè)SimpleCacheManager作為Cache的管理對象,然后初始化了兩個(gè)Cache對象,分別存儲(chǔ)user,dept類型的緩存。當(dāng)然構(gòu)建Cache的參數(shù)設(shè)置我寫的比較簡單,你在使用的時(shí)候酌情根據(jù)需要配置參數(shù)。

使用注解來對 cache 增刪改查

我們可以使用spring提供的 @Cacheable、@CachePut、@CacheEvict等注解來方便的使用caffeine緩存。

如果使用了多個(gè)cahce,比如redis、caffeine等,必須指定某一個(gè)CacheManage為@primary,在@Cacheable注解中沒指定 cacheManager 則使用標(biāo)記為primary的那個(gè)。

cache方面的注解主要有以下5個(gè):

  • @Cacheable 觸發(fā)緩存入口(這里一般放在創(chuàng)建和獲取的方法上,@Cacheable注解會(huì)先查詢是否已經(jīng)有緩存,有會(huì)使用緩存,沒有則會(huì)執(zhí)行方法并緩存)
  • @CacheEvict 觸發(fā)緩存的eviction(用于刪除的方法上)
  • @CachePut 更新緩存且不影響方法執(zhí)行(用于修改的方法上,該注解下的方法始終會(huì)被執(zhí)行)
  • @Caching 將多個(gè)緩存組合在一個(gè)方法上(該注解可以允許一個(gè)方法同時(shí)設(shè)置多個(gè)注解)
  • @CacheConfig 在類級別設(shè)置一些緩存相關(guān)的共同配置(與其它緩存配合使用)

說一下@Cacheable 和 @CachePut的區(qū)別:

  • @Cacheable:它的注解的方法是否被執(zhí)行取決于Cacheable中的條件,方法很多時(shí)候都可能不被執(zhí)行。

  • @CachePut:這個(gè)注解不會(huì)影響方法的執(zhí)行,也就是說無論它配置的條件是什么,方法都會(huì)被執(zhí)行,更多的時(shí)候是被用到修改上。

簡要說一下Cacheable類中各個(gè)方法的使用:

public @interface Cacheable {

    /**
     * 要使用的cache的名字
     */

    @AliasFor("cacheNames")
    String[] value() default {};

    /**
     * 同value(),決定要使用那個(gè)/些緩存
     */

    @AliasFor("value")
    String[] cacheNames() default {};

    /**
     * 使用SpEL表達(dá)式來設(shè)定緩存的key,如果不設(shè)置默認(rèn)方法上所有參數(shù)都會(huì)作為key的一部分
     */

    String key() default "";

    /**
     * 用來生成key,與key()不可以共用
     */

    String keyGenerator() default "";

    /**
     * 設(shè)定要使用的cacheManager,必須先設(shè)置好cacheManager的bean,這是使用該bean的名字
     */

    String cacheManager() default "";

    /**
     * 使用cacheResolver來設(shè)定使用的緩存,用法同cacheManager,但是與cacheManager不可以同時(shí)使用
     */

    String cacheResolver() default "";

    /**
     * 使用SpEL表達(dá)式設(shè)定出發(fā)緩存的條件,在方法執(zhí)行前生效
     */

    String condition() default "";

    /**
     * 使用SpEL設(shè)置出發(fā)緩存的條件,這里是方法執(zhí)行完生效,所以條件中可以有方法執(zhí)行后的value
     */

    String unless() default "";

    /**
     * 用于同步的,在緩存失效(過期不存在等各種原因)的時(shí)候,如果多個(gè)線程同時(shí)訪問被標(biāo)注的方法
     * 則只允許一個(gè)線程通過去執(zhí)行方法
     */

    boolean sync() default false;

}

基于注解的使用方法:

package com.rickiyang.learn.cache;

import com.rickiyang.learn.entity.User;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

/**
 * @author: rickiyang
 * @date: 2019/6/15
 * @description: 本地cache
 */

@Service
public class UserCacheService {


    /**
     * 查找
     * 先查緩存,如果查不到,會(huì)查數(shù)據(jù)庫并存入緩存
     * @param id
     */

    @Cacheable(value = "userCache", key = "#id", sync = true)
    public void getUser(long id){
        //查找數(shù)據(jù)庫
    }

    /**
     * 更新/保存
     * @param user
     */

    @CachePut(value = "userCache", key = "#user.id")
    public void saveUser(User user){
        //todo 保存數(shù)據(jù)庫
    }


    /**
     * 刪除
     * @param user
     */

    @CacheEvict(value = "userCache",key = "#user.id")
    public void delUser(User user){
        //todo 保存數(shù)據(jù)庫
    }
}

如果你不想使用注解的方式去操作緩存,也可以直接使用SimpleCacheManager獲取緩存的key進(jìn)而進(jìn)行操作。

注意到上面的key使用了spEL 表達(dá)式。Spring Cache提供了一些供我們使用的SpEL上下文數(shù)據(jù),下表直接摘自Spring官方文檔:

注意:

1.當(dāng)我們要使用root對象的屬性作為key時(shí)我們也可以將“#root”省略,因?yàn)镾pring默認(rèn)使用的就是root對象的屬性。如

@Cacheable(key = "targetClass + methodName +#p0")

2.使用方法參數(shù)時(shí)我們可以直接使用“#參數(shù)名”或者“#p參數(shù)index”。如:

@Cacheable(value="userCache", key="#id")
@Cacheable(value="userCache", key="#p0")

SpEL提供了多種運(yùn)算符

?

作者:rickiyang
出處:https://www.cnblogs.com/rickiyang/p/11074158.html

?

瀏覽 33
點(diǎn)贊
評論
收藏
分享

手機(jī)掃一掃分享

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

手機(jī)掃一掃分享

分享
舉報(bào)

感谢您访问我们的网站,您可能还对以下资源感兴趣:

国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频 欧美熟妇性爱| 亚洲综合五月天| 国产精品久久久| 天堂中文在线观看| 日韩欧美性爱| 岛国av免费| 人妻超碰| 色香蕉在线| 久久国产高清| 九九午夜| 久热精品在线观看视频| www.日韩一区| 丰满人妻一区二区三区四区53| 成人网站大香蕉| 久久国产高清视频| 成人精品亚洲人成在线| 成年人毛片视频| 国产色婷婷一区二区| 丝袜人妻被操视频| 69av在线| 色欲狠狠躁天天躁无码中文字幕| JUY-579被丈夫的上司侵犯后的第7天,我 | 黄色电影一区二区三区| 影视先锋久久| 老女人操逼网| 亚洲东方在线| 996视频| 韩国中文字幕HD久久精品| 国产三级电影| 日韩女人性爱| 中文字幕一级A片免费看| 亚洲日韩精品秘在线观看| 激情网页| 波多野结衣AV无码| 亚洲人成在线观看| 884aa四虎影成人精品一区| 91在线精品一区二区| 欧美精品一二三| 西西444www无码精品| 国产精品色8| 青春草在线视频观看| 欧美三级毛片| 亚洲国产免费| 久草免费电影| 蝌蚪窝视频在线| 黄色视频久久| 91含羞草www·Com| 国产亚洲精品久久久久动| 国产欧美精品一区二区色综合 | 欧美操B视频| 免费在线观看黄色视频网站| 五月婷婷AV| 91传媒在线观看| 韩国av在线| 91久久爽久久爽爽久久片| 免费黄片视频| 97毛片| 日韩国产在线| 日韩欧美综合| 暗呦罗莉精品一区二区| 黑人vs亚洲人在线播放| 丁香婷婷五月综合影院| 美女网站色| 在线看黄网| 91精品国产一区| 亚洲jizzjizz| 人妻免费在线视频| 五月婷综合| 人人综合网| 日韩精品在线视频观看| 五月天久久久久| 在线色网站| 大鸡巴免费视频| 岛国av免费看| 日韩黄色电影网址| 黄色小视频免费观看| 亚洲中文字幕2025| jiujiuav| 97精品| 深爱激情五月天| 亚洲AV成人片色在线观看麻豆 | 俺去啦在线视频| 强辱丰满人妻HD中文字幕| 69AV在线视频| 日本不卡一区二区| 伊人97| 欧美footjob高跟脚交| 天天色伊人| 六月婷婷五月天| 亚洲码AV波多野| 狠狠干B| a片在线观看免费| 国产精品久久毛片| 在线天堂19| 青青草原网址| 日本性爱无码| 老欧性老太色HD大全| 欧美一级日韩一级| 久久天堂| 91精品国产闺蜜国产在线闺蜜 | 成人网站在线免费看| 少妇大战黑人46厘米| 无码视频在线| 人人干人人操人人爽| 亚洲午夜AV| 黄色视频大全免费看| 亚洲一线视频| 免费黄色欧美| 久久免费视频播放| 久久嫩草精品久久久久| 四川少妇搡bbbbb搡多人| 成人性生活视频| 国产欧美在线综合| 成年人视频在线观看免费| 精品狼友| 婷婷五月成人| 中文字幕你懂的| 色婷婷视频在线播放| 一级免费黄色片| 五月丁香六月| 精品国产乱子伦一区二区三区,小小扐 | 91第一页| 欧美性爱-熊猫成人网| 成人A片一级| 操逼网123| 亚洲国产黄片| 四虎无码视频| 亚洲AV无码久久寂寞少妇多毛| 无码颜射| 日韩伊人| 国产三级片视频| 人妻japanesewoman| 狼人综合影院| 成人小说亚洲一区二区三区| 一级黄影| 福利导航在线| 日韩人妻一区二区| 安徽少妇搡bbw搡bbbb| 热久久在线| 人妻黑人一区二区三区| 99黄片| 亚洲av| 大香蕉伊在线观看| 99re6热在线精品视频功能 | 久久久一区二区三区四曲免费听| 成人国产精品秘欧美高清| 人人妻人人操人人干| 大香蕉尹人在线观看| 黄色一级在线观看| 国产黄片在线免费观看| 国产成人宗合| 色噜噜网站| 超碰97老师| 丁香五月婷婷六月| 成人毛片在线观看| 四虎国产精品成人久久| 一本色道无码人妻精品| 久久黄色的| 国产综合久久久7777777| 日韩中文字幕av| 久久亚洲福利视频| 亚洲AV无码成人精品区h麻豆| 特级西西人体444www高清大胆 | 久久偷看各类wc女厕嘘嘘偷窃| 黄片免费视频观看| 日韩无码中文字幕| 成人在线91| 无码国产99精品久久久久网站 | AV性爱在线| 日韩高清一区二区| 欧洲黑种人日P视频| 91麻豆成人精品国产| 人人cao| 色综合综合色| 强伦轩一区二区三区四区播放方式 | 国产精品色色| 懂色午夜福利一区二区三区| 国产午夜成人视频| 国产伦精品一区二区三区视频女| www.91n| 91综合在线| 91久久久久久久久久久| 不卡成人| 亚洲无码黄片| 欧美第一页| 伊人666| 人人操超碰在线| 翔田千里AV在线| 三级片AAA成人免费| 日韩欧美a片| 久久大鸡巴| 免费AV片| 亚洲无码视频在线观看高清| 亚洲午夜精品久久久久久APP | 国产伦精品一区二区三区妓女下载| 精品中文字幕在线| 亚洲日韩av在线| 精品一区二区三区四区| 青青国产在线观看| 精品尤物| 久久精品三级片| 成人免看一级a一片| 婷婷色中文网| 北条麻妃无码精品AV| 国产欧美日韩| 竹菊av一区二区三区四区五区| 日产精品久久久久| 精品AV| 五月婷婷开心| 熟女人妻在线| 极品无码| 亚洲无码激情在线| a片免费观看视频| 亚洲无码成人在线| 天天影视综合网免费观看电视剧国产 | 成人午夜A片免费看| 中文字幕成人网站| 久久99老妇伦国产熟女| 国产精品乱码毛片在线人与| 日韩一区二区三区无码电影| 青青草原成人| 最新97色黄色精品高清网站| 二区三区视频| 韩日无码视频| 一级a片激情啪啪免费观| 国产精品v欧美精品v日韩| 亚洲无码999| 久久91久久久久麻豆精品| 亚洲AV无码成人片在线| 五月天久久婷婷| 国产在线观看免费成人视频| chinese高潮老女人| 一区二区视频在线| 久草黄色电影在线观看| 中文无码高清视频| 成人AA片| 在线成人亚洲| 日韩第1页| 欧美色图在线播放| 四色五月婷婷| 国产日韩一区二区| 高清无码网站| 好男人一区二区三区在线观看 | 激情婷婷 | 国产精品扒开腿做爽爽爽A片唱戏| 中文字幕一区二区三区人妻在线视频 | 伊人久久五月| 91天天射| 国产精品久久久久久久久A| 乱伦AV片| 色婷婷综合久久久中文字幕| 免费欧美黄片| 青娱乐最新官网| 成人黄色网| 亚洲免费大片| 欧美人妻视频| 天堂在线观看AV| 丁香五月网站| 亚洲日韩在线播放| 无码视频中文字幕| 亚洲国产精品久久久| AV无码不卡| 国产99自拍| 亚洲高清在线视频| PORNY九色视频9l自拍| 99精品无码| 丁香五香天堂| 日韩黄色片网站| 麻豆三级电影| 三级av在线观看| 亚洲精品一区二区三区在线观看| 人人人人干| 99亚洲视频| 久久大香蕉| 国产成人无码一区二区在线观看 | 无码高清免费| 国产特黄级AAAAA片免| 中文字幕乱码中文字幕| 亚洲精品乱码久久久久久按摩观 | 日韩日日夜夜| 天堂一区二区| 韩日av| 亚洲sese| 综合自拍偷拍| 四虎高清无码| 在线高清无码不卡| 日韩成人小说| 欧美特级毛片| 老熟妇搡BBBB搡BBBB| av在线天堂| 骚骚网| 国产av天堂| 青青久久91| 欧美熟妇性爱| AV在线小说| 大香蕉超碰在线| 婷婷综合缴情亚洲另类在线| 国产卡一卡二| 日韩码线观看视频| 国产主播中文字幕| 人人操在线| 少妇精品久久久久久久久久| 亚洲成人AV在线| 狼色视频| 国产中文字幕在线播放| 人人干人妻| 日韩久久网| 天天天做夜夜夜爽无码| 91色噜噜狠狠色婷婷| 3D精品啪啪一区二区三区| 操逼福利| 在线观看免费高清无码| 北条麻妃无码播放| 一区二区三区小视频| 一本色道久久综合狠狠躁的推荐 | 日韩国产成人在线| 亚洲综合视频在线观看| 大学生18一19GAY169| 日韩1页| 午夜无码免费| 大香蕉手机在线视频| 亚洲精品乱码在线| 欧美视频在线一区| 一级免费爱爱视频| 北条麻妃无码视频在线观看| 韩国无码成人电影啊荒| 日韩人妻精品无码制服| 蜜桃精品一区二区| 在线观看的av| 大香蕉伊人色| 欧美成人无码片免费看A片秀色| 国产精品久久久久久久久久久久久久久久 | 污视频网站在线观看| 男女日皮视频| 色欲五月天| 懂色av粉嫩AV蜜臀AV| 国产区欧美去区在线| 人妻japanesewoman| 亚洲在线高清| 欧美特级黄片| 国产A片免费观看| 亚洲jizzjizz| 亚洲丁香五月| 国内自拍欧美| 日韩欧美网站| 日韩色情在线| 俺去也| 翔田千里无码播放| 中国一级黄色A片| 一道本无码一区| 免费观看黄色成人网站| 91亚洲一线产区二线产区| а√天堂中文官网8| 国产精品国产精品国产专区不片 | 亚洲无码专区视频| 五月色婷婷撸| 久久精品视| 懂色一区二区二区在线播放视频 | 日韩操逼视频| 一区二区三区久久久久〖网:.〗| 99精品视频北条麻妃国产版| 91探花视频在线观看| 超碰91人人操| 国产AV一级| 亚洲一区久久| 伊人网站| 国产无遮挡| 120分钟婬片免费看| 亚洲综合免费观看高清| 国产无码电影在线观看| 成人在线视频观看| 欧美久久久久久| 逼特逼视频网站| 99精品无码| 99操逼视频| 五月激情视频| 99久久夜色精品国产亚洲| 国产成人无码区免费视频| 三级片一区二区| 久久免费9| 特级444WWW大胆高清| 亚洲视频大全| 亚洲AV无码久| 热久久中文字幕| 成人性爱视频在线| 天天日综合| 91福利网站| 日本一区二区三区四区| 午夜精品久久久久久久| 97超碰碰碰| 青娱AV| 有码一区二区三区| 一区二区三区国产精品| 8050午夜网| 欧美老女人性爱视频| 四虎激情影院| 在线免费观看毛片| 日韩一级性爱视频| 91夫妻交友视频| www.激情| 欧美日韩肏屄视频| 乱伦自拍| 国产在线视频一区二区三区| 中国熟睡妇BBwBBw| 99久久久成人国产精品| 狠狠色色| 91成人免费在线观看| 日韩无码中文字幕| 中文字幕手机在线视频| 免费观看黄色成人网站| 亚洲成人无码电影| 69av在线观看视频| 另类色| 大鸡吧网站| 黑人AV在线观看| 亚洲综合免费| www.911国产| 777中文字幕| 成人黄网在线观看| 中文字幕在线观看日韩| 十八女人高潮A片免费| 美女久草| 尻屄网站| 欧美三级网站在线观看| 在线观看中文字幕视频| www黄色视频| 初尝人妻滑进去了莹莹视频| 五月丁香天堂| 亚洲高清在线视频| 京东一热本色道久久爱| 人妻中文字幕av| 人人色人人色| www.精品视频| 欧美三级网址| 国产成人女人在线观看| 嫩草在线观看| 日韩一级免费电影| 久久天堂av| 77777色| A片视频免费观看| 日韩A片免费观看| 蜜桃秘一二三区最新| 欧美三级电影在线观看| 18禁一区二区| 安徽妇搡BBBB搡BBBB,另类老妇| 韩国无码免费| 国产操逼免费视频| 国产在线视频第一页| 日韩A| 天天综合网久久综合网| 二区| 成人国产| 欧一美一婬一伦一区二区三区自慰 | 天天看天天摸| 在线观看国产一级片| 人妻精品一二三| 亚洲无码视频一区| 人人天天操| 91人人妻人人做人人爽| 日本无码在线| 天堂操逼| 日韩有码中文字幕在线观看| 十八禁网站在线观看| 国产97视频| 久久久噜噜噜| 青青草小视频| 广西少妇BBwBBwBBw| 三级片大香蕉| 三根一起进菊眼| 色婷婷激情综合网| 成人在线视频一区| 91综合网| 日韩狠狠| h亚洲| 欧美一级A片在免费看| 中文字幕乱伦性爱| 欧美日韩国产成人| 搡女人视频国产一级午夜片| 中国AV网| 欧美大鸡| 人人精品| 91人人妻人人澡人人爽人人| 麻豆精品传媒2021md| 肉色超薄丝袜脚交一区二区| 伊人97| 国产一区二区三区免费视频| 国产精品高潮呻吟久久| 九色丨蝌蚪丨老版熟女| 国产在线在线| 香蕉久久久| 亚洲AV无码成人| 好吊妞视频在线| 97免费在线视频| 日本成人视频在线免费播放| 中文字幕在线观看日韩| 成年女人免费视频| 啊啊啊啊啊靠逼| 日韩极品视频在线| 五月婷婷六月丁香| 天堂中文字幕在线| 91人妻最真实刺激绿帽| 风流老熟女一区二区三区| 欧美成人精品一级| 国产黄色大片| 黑人Av| 亚洲涩情91日韩一区二区| 午夜福利视频3000| 亚洲日日夜夜| a级黄色视频免费观看| 农村A片婬片AAA毛片| 日韩久久综合| 日韩成人无码免费视频| 二区视频在线| 丰满人妻一区二区三区Av猛交 | 91蜜桃婷婷狠狠久久综合9色| 成人国产在线观看| 在线亚洲欧美| 国产成人精品777777| 88AV在线观看| 久久日av| 午夜嘿嘿| 免费A片国产毛无码A片| 亚洲无码在线视频播放| av超碰在线| 久久综合大香蕉| 五月天婷婷色播| 日本操逼视频| 高清国产AV| 99九九久久| 国产女主播在线| 欧美一级一区| 香蕉国产在线| 六月天av| 成人片天天看片欧美一级| 亚洲热视频| 香蕉91视频| 99热在线观看免费| 人人妻人人澡人人爽人人爽| AV资源在线免费观看| 亚洲无码在线高清| 久久中文字幕免费| 樱桃码一区二区三区| 成人在线精品| 视频一区二区三区在线观看| 中文资源在线a中文| 五月网婷婷| 亚洲国产中文字幕在线播放| 牛牛精品一区二区AV| 午夜福利干B在线免费小视频| 欧美日韩精品在线观看| 91香蕉在线观看| 亚洲午夜在线观看| AV福利在线| 黄色大片在线| 99久久网站| 天天欧美| 日逼网站国产| 午夜撸一撸| 欧美A∨| 亚洲成人三级片| 亚洲视频免费完整版在线播放 | 久久国产一区二区| 日韩无码高清网站| 久久久精品影院| 亚洲AAA| 一区不卡| 高清免费无码视频| 天天撸天天干| 午夜久久久久久久久久久久91| 人人鲁人人操| 日韩色情在线| 欧美成人免费在线| 97精品超碰一区二区三区| 青草在线视频| 亚洲中文字幕在线观看免费| 青青操国产乱伦| 在线观看中文字幕| 青娱乐国产在线| 无码一二三区| 人人妻人人爽人人澡人人精品| 先锋影音麻豆| 精品欧美乱码久久久久久| 国产精品theporn| 99视频在线精品| 一级大香蕉| 亚洲婷婷在线观看| 狼人综合视频| 国产欧美精品一区二区三区| 51一区二区三区| 菊花插综合网| 久久中文字幕免费| 国产亚洲视频完整在线观看| 日韩国产欧美| 色久综合| 无码人妻一区二区三区精品不付款 | 亚洲av无码精品| 日本a一级片| 免费的黄色录像| 成人做爰免费网站2023| 无码视频在线播放| 蜜臀在线视频| 日韩在线小视频| 激情六月婷婷| 成人AV天堂| 欧美一页| 高清无码免费观看| 亚洲日韩中文无码| 免费AV片| xxxx国产| 成人午夜无码视频| 国产黄| 91AV| 亚洲视频中文| 精品码一区二在线观看| 欧美一级A片免费看| 亚洲午夜久久久久久久久红桃| 中文字幕2025年最好看电视剧| 可以免费观看的av| 五月丁香六月婷婷综合| 国产精品乱子伦一区二区三区视频 | 国产AV一区二区三区四区| 亚洲三级片在线视频| 殴美A片| 中文字幕日韩人妻在线| 99免费精品视频| 久久国产劲爆∧v内射| 欧美猛交| 东京热视频网| 性爱视频网站| EEUSS| 三级网址在线观看| 高清国产av| 九九色视频| 人妻97| 一级片免费| 日韩欧美一级| 在线播放中文字幕| 中文字幕av久久爽一区| 三级片AAA成人免费| 少妇被躁到高潮无码| 亚洲草比视频网| 蜜桃成人AV| 黄网在线观看视频| 特级西西444WWW高清大视频| 猫咪亚洲AV成人无码电影| 国产婷婷精品| 午夜一区二区三区免费| 超碰91人人操| 黄91在线观看| 操逼免费视频网站| 激情丁香五月婷婷| 就要干就要操| 国产高清无码在线观看视频| 国产精品污www在线观看| 中文字幕人妻系列| 免费在线观看黄视频| Av一区二区三区| 婷婷五月天成人电影| 伊人久久免费视频| 淫香淫色综合网| 日本久久电影| 男女啪啪免费| 先锋影音资源站| 亚洲猛男操逼欧美国产视频| 国产免费一区二区三区免费视频| 天堂在线视频免费| 免费观看成人片| av电影在线免费观看| av一区二区在线观看| 少妇中文字幕| 黑人AV在线观看| 欧美一级在线免费观看| 午夜性爱AV| 日本a片在线观看| 国产区精品| 人妻熟女字幕一区二区| 成人怡红院| 大香蕉国产| 天天干强奸视频在线综合| 三级黄色小视频| 加勒比综合无码| 无码在线专区| 中文字幕免费观看视频| 成人免费黄色视频| 天天色色色| 日韩在线视频免费| 中文字幕亚洲综合| 欧美人人操| 国产精品久久久久久久久免费无码 | 一级片免费| 欧美日逼小视频| 久久久女女女女999久久| 国产a毛一级,a毛一级| 亚洲黄v| 国产精品久久毛片| 国产操b视频| 日批国产| 欧美一级婬片A片免费软件| 久久五月婷| 少妇在线观看| 影音先锋无码AV| 青青草原视频在线免费观看| 色色网的五月天| 俺来俺去www色官网| 天堂俺去俺来也www久久婷婷 | 一级a片激情啪啪免费观| 精品视频久久久久久| 国产精品高清网站| 中文在线A∨在线| 四虎性爱视频| 日韩毛片中文字幕| 日逼大片| 男女日逼视频| 黑人又粗又大XXXXOO| 青春草在线免费观看| 午夜视频成人| 摸BBB搡BBB搡BBBB| 熟妇综合| 在线免费A片| 丰滿老婦BBwBBwBBw| 无码任你躁久久久久| 97超碰色| 五月激情婷婷网| 一本一本久久a久久精品牛牛影视 91无码人妻精品一区二区蜜桃 | 日日干AV| 人人射在线| 国产午夜在线观看| 国产女人在线| 91爱爱| 大鸡巴操小逼视频| 三级成人视频| 亚洲乱伦图片| 国产在线拍揄自揄拍无码网站新闻| 国产乱妇无码毛片A片在线看下载| 亚洲天堂AB| 日韩免费在线观看| 91原创国产内射| 2026国产精品视频| 欧美天堂在线观看| 一道本在线视频| 日韩欧美综合一区| 91精品少妇| 中文字幕av免费在线观看| 99视频精品全部免费看| 国产h在线观看| 免费看操逼| 久久人人网| 中国a一片一级一片| 大香蕉AV在线观看| 91小视频在线观看| 日韩免费av| 国产毛片久久久久久国产毛片| 综合自拍偷拍| 午夜天堂在线观看| 中文字幕无码视频在线观看| 成人精品免费| 欧美国产在线观看综合| 日日操天天| 久久精品免费电影| 一道本一区二区三区| 97在线免费视频| 网站色色免费看| 国产精品免费一区二区三区四区视频| 精品无码一区二区三区蜜桃李宗瑞 | 9l视频自拍九色9l视频成人| 国产精品免费观看视频| 97人妻精品一区二区三区| 激情AV在线观看| 中国老女人日逼| 色欲欲www成人网站| 天天天天天天操| 奇米影视亚洲春色| 亚洲高清视屏| 伊人久久无码| 无套内射学生妹去看片| 无码一区二区三区在线| 撸一撸成人在线做爱视频。| 91麻豆国产视频| 亚洲成人精品一区二区| 国产AV不卡| 色播五月天| 日韩在线大香蕉| 国产v欧美| 91人人妻人人澡人人爽人人| 少妇精品| 男人天堂无码成人| 小明成人免费视频| www.色悠悠| 亚洲A∨| 亚洲日韩网站| 黄色毛片视频| 亚洲免费黄色电影| 爱色五月| 久久精品国产99精品国产亚洲性色| 国产午夜精品一区二区| 青娱乐网| 91人妻视频| 婷婷在线影院| 国产无码三级| 国产剧情在线| 99性爱视频| 天天日天天干天天爽| 欧美成人精品一级| 欧美性猛交XXXXⅩXX| 亚洲午夜久久久久久久久红桃| 操东北老女人| 一道本不卡视频| 无码在线免费播放| 9i看片成人免费视频| 成人国产精品秘在线看| 岛国无码AV在线观看| 日韩AV无码专区亚洲AV| 日韩视频免费| 无码精品一区二区三区在线播放| 青青草网站在线观看| 成人高清无码视频| 国产激情视频在线观看| 一道本不卡视频| 日本AAAA片| 国产欧美精品一区二区| 亚洲天堂女| 黄色一级大片在线免费看国产| 浮力影院欧美| 精品蜜桃一区二区三区| 国产精品一卡二卡三卡| 久草性爱| 日本女人操逼视频| 久操手机在线| 国产熟女露脸普通话对白| 精品在线免费视频| 亚洲AV无码国产精品二区| 精品无码蜜桃| 成人激情综合网| 久久亚洲日韩天天做日日做综合亚洲 | 国产香蕉视频在线播放| 日韩在线精品视频| 伊人成人在线| 天天日AV| 欧美高潮喷水| 欧美精品一区二区三区四区| 一级aa免费视频| 中文有码在线观看| 婷婷天堂| 无码欧美精品一区二区| JlZZJLZZ亚洲美女18| 蜜桃av秘无码一区三区四| 黄片WWW| 成人精品一区二区三区中文字幕| 青草久久久| 一区二区国产视频| 黄色毛片一级| 另类AV| 日韩成人AV电影| 欧美成人性爱网站| 日韩三级| 免费黄网站在线观看| 天天舔天天日| 青草大香蕉| 亚洲无码内射| 骚逼AV| 国产人妻精品一区二区三区不卡| 国产AV播放| 欧美丰满人妻免费视频人| 蜜桃无码一区| 在线内射| 亚洲无码电影在线观看| 欧美亚洲操逼视频| 国产综合久久777777麻豆| 美国操逼片| 亚洲欲色| 免费看黃色AAAAAA片| 色狠狠AV| 999大香蕉| 天天色图| 翔田千里一区二区三区精品播放| 福利导航在线| 波多野结衣无码流出| 色播AV| 美女一区| 91AV在线观看视频| 黄色A片一级| 天天搞天天曰在线观看| 日韩专区中文字幕| 亚洲一级在线观看| 成人三级片视频| 逼特逼视频在线| 成人免费视频在线观看| 天堂网2025| 波多野结衣视频在线| 婷婷欧美色图| 久久99久久99| 丁香五月在线| 午夜偷拍视频| 精品1234| 日韩欧美性爱网站| 国产在线观看免费| 亚洲无码人妻| 中文字幕巨肉乱码中文乱码| 欧美激情五月天| 天天拍夜夜爽|