精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Guava Cache全面解析

開發 前端
Guava Cache的架構設計靈感ConcurrentHashMap,在簡單場景中可以通過HashMap實現簡單數據緩存,但如果要實現緩存隨時間改變、存儲的數據空間可控則緩存工具還是很有必要的。

緩存分為本地緩存和遠端緩存。常見的遠端緩存有Redis,MongoDB;本地緩存一般使用map的方式保存在本地內存中。一般我們在業務中操作緩存,都會操作緩存和數據源兩部分。如:put數據時,先插入DB,再刪除原來的緩存;ge數據時,先查緩存,命中則返回,沒有命中時,需要查詢DB,再把查詢結果放入緩存中 。如果訪問量大,我們還得兼顧本地緩存的線程安全問題。必要的時候也要考慮緩存的回收策略。

今天說的 Guava Cache 是google guava中的一個內存緩存模塊,用于將數據緩存到JVM內存中。他很好的解決了上面提到的幾個問題:

  • 很好的封裝了get、put操作,能夠集成數據源 ;
  • 線程安全的緩存,與ConcurrentMap相似,但前者增加了更多的元素失效策略,后者只能顯示的移除元素;
  • Guava Cache提供了三種基本的緩存回收方式:基于容量回收、定時回收和基于引用回收。定時回收有兩種:按照寫入時間,最早寫入的最先回收;按照訪問時間,最早訪問的最早回收;
  • 監控緩存加載/命中情況

Guava Cache的架構設計靈感ConcurrentHashMap,在簡單場景中可以通過HashMap實現簡單數據緩存,但如果要實現緩存隨時間改變、存儲的數據空間可控則緩存工具還是很有必要的。Cache存儲的是鍵值對的集合,不同時是還需要處理緩存過期、動態加載等算法邏輯,需要額外信息實現這些操作,對此根據面向對象的思想,還需要做方法與數據的關聯性封裝,主要實現的緩存功能有:自動將節點加載至緩存結構中,當緩存的數據超過最大值時,使用LRU算法替換;它具備根據節點上一次被訪問或寫入時間計算緩存過期機制,緩存的key被封裝在WeakReference引用中,緩存的value被封裝在WeakReference或SoftReference引用中;還可以統計緩存使用過程中的命中率、異常率和命中率等統計數據。

構建緩存對象

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;


public class GuavaCacheService {

    public void setCache() {
        LoadingCache<Integer, String> cache = CacheBuilder.newBuilder()
                //設置并發級別為8,并發級別是指可以同時寫緩存的線程數
                .concurrencyLevel(8)
                //設置緩存容器的初始容量為10
                .initialCapacity(10)
                //設置緩存最大容量為100,超過100之后就會按照LRU最近雖少使用算法來移除緩存項
                .maximumSize(100)
                //是否需要統計緩存情況,該操作消耗一定的性能,生產環境應該去除
                .recordStats()
                //設置寫緩存后n秒鐘過期
                .expireAfterWrite(60, TimeUnit.SECONDS)
                //設置讀寫緩存后n秒鐘過期,實際很少用到,類似于expireAfterWrite
                //.expireAfterAccess(17, TimeUnit.SECONDS)
                //只阻塞當前數據加載線程,其他線程返回舊值
                //.refreshAfterWrite(13, TimeUnit.SECONDS)
                //設置緩存的移除通知
                .removalListener(notification -> {
                    System.out.println(notification.getKey() + " " + notification.getValue() + " 被移除,原因:" + notification.getCause());
                })
                //build方法中可以指定CacheLoader,在緩存不存在時通過CacheLoader的實現自動加載緩存
                .build(new DemoCacheLoader());

        //模擬線程并發
        new Thread(() -> {
            //非線程安全的時間格式化工具
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
            try {
                for (int i = 0; i < 10; i++) {
                    String value = cache.get(1);
                    System.out.println(Thread.currentThread().getName() + " " + simpleDateFormat.format(new Date()) + " " + value);
                    TimeUnit.SECONDS.sleep(3);
                }
            } catch (Exception ignored) {
            }
        }).start();

        new Thread(() -> {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
            try {
                for (int i = 0; i < 10; i++) {
                    String value = cache.get(1);
                    System.out.println(Thread.currentThread().getName() + " " + simpleDateFormat.format(new Date()) + " " + value);
                    TimeUnit.SECONDS.sleep(5);
                }
            } catch (Exception ignored) {
            }
        }).start();
        //緩存狀態查看
        System.out.println(cache.stats().toString());

    }

    /**
     * 隨機緩存加載,實際使用時應實現業務的緩存加載邏輯,例如從數據庫獲取數據
     */
    public static class DemoCacheLoader extends CacheLoader<Integer, String> {
        @Override
        public String load(Integer key) throws Exception {
            System.out.println(Thread.currentThread().getName() + " 加載數據開始");
            TimeUnit.SECONDS.sleep(8);
            Random random = new Random();
            System.out.println(Thread.currentThread().getName() + " 加載數據結束");
            return "value:" + random.nextInt(10000);
        }
    }
}

LoadingCache是Cache的子接口,相比較于Cache,當從LoadingCache中讀取一個指定key的記錄時,如果該記錄不存在,則LoadingCache可以自動執行加載數據到緩存的操作。

在調用CacheBuilder的build方法時,必須傳遞一個CacheLoader類型的參數,CacheLoader的load方法需要我們提供實現。當調用LoadingCache的get方法時,如果緩存不存在對應key的記錄,則CacheLoader中的load方法會被自動調用從外存加載數據,load方法的返回值會作為key對應的value存儲到LoadingCache中,并從get方法返回。

當然如果你不想指定重建策略,那么你可以使用無參的build()方法,它將返回Cache類型的構建對象。

CacheBuilder 是Guava 提供的一個快速構建緩存對象的工具類。CacheBuilder類采用builder設計模式,它的每個方法都返回CacheBuilder本身,直到build方法被調用。該類中提供了很多的參數設置選項,你可以設置cache的默認大小,并發數,存活時間,過期策略等等。

可選配置分析

緩存的并發級別

Guava提供了設置并發級別的api,使得緩存支持并發的寫入和讀取。同 ConcurrentHashMap 類似Guava cache的并發也是通過分離鎖實現。在一般情況下,將并發級別設置為服務器cpu核心數是一個比較不錯的選擇。

CacheBuilder.newBuilder()
  // 設置并發級別為cpu核心數
  .concurrencyLevel(Runtime.getRuntime().availableProcessors()) 
  .build();

緩存的初始容量設置

在構建緩存時可以為緩存設置一個合理大小初始容量,由于Guava的緩存使用了分離鎖的機制,擴容的代價非常昂貴。所以合理的初始容量能夠減少緩存容器的擴容次數。

CacheBuilder.newBuilder()
  // 設置初始容量為100
  .initialCapacity(100)
  .build();

設置最大存儲

Guava Cache可以在構建緩存對象時指定緩存所能夠存儲的最大記錄數量。當Cache中的記錄數量達到最大值后再調用put方法向其中添加對象,Guava會先從當前緩存的對象記錄中選擇一條刪除掉,騰出空間后再將新的對象存儲到Cache中。

  • 基于容量的清除: 通過CacheBuilder.maximumSize(long)方法可以設置Cache的最大容量數,當緩存數量達到或接近該最大值時,Cache將清除掉那些最近最少使用的緩存;
  • 基于權重的清除: 使用CacheBuilder.weigher(Weigher)指定一個權重函數,并且用CacheBuilder.maximumWeight(long)指定最大總重。比如每一項緩存所占據的內存空間大小都不一樣,可以看作它們有不同的“權重”(weights)。

緩存清除策略

  • 基于存活時間的清除

expireAfterWrite 寫緩存后多久過期

expireAfterAccess 讀寫緩存后多久過期

refreshAfterWrite 寫入數據后多久過期,只阻塞當前數據加載線程,其他線程返回舊值

這幾個策略時間可以單獨設置,也可以組合配置。

  • 上面提到的基于容量的清除
  • 顯式清除

個別清除:Cache.invalidate(key)

批量清除:Cache.invalidateAll(keys)

清除所有緩存項:Cache.invalidateAll()

  • 基于引用的清除

在構建Cache實例過程中,通過設置使用弱引用的鍵、或弱引用的值、或軟引用的值,從而使JVM在GC時順帶實現緩存的清除,不過一般不輕易使用這個特性。

  • CacheBuilder.weakKeys():使用弱引用存儲鍵。當鍵沒有其它(強或軟)引用時,緩存項可以被垃圾回收。因為垃圾回收僅依賴恒等式,使用弱引用鍵的緩存用而不是equals比較鍵。
  • CacheBuilder.weakValues():使用弱引用存儲值。當值沒有其它(強或軟)引用時,緩存項可以被垃圾回收。因為垃圾回收僅依賴恒等式,使用弱引用值的緩存用而不是equals比較值。
  • CacheBuilder.softValues():使用軟引用存儲值。軟引用只有在響應內存需要時,才按照全局最近最少使用的順序回收。考慮到使用軟引用的性能影響,我們通常建議使用更有性能預測性的緩存大小限定(見上文,基于容量回收)。使用軟引用值的緩存同樣用==而不是equals比較值。

清理什么時候發生

也許這個問題有點奇怪,如果設置的存活時間為一分鐘,難道不是一分鐘后這個key就會立即清除掉嗎?我們來分析一下如果要實現這個功能,那Cache中就必須存在線程來進行周期性地檢查、清除等工作,很多cache如redis、ehcache都是這樣實現的。

使用CacheBuilder構建的緩存不會”自動”執行清理和回收工作,也不會在某個緩存項過期后馬上清理,也沒有諸如此類的清理機制。相反,它會在寫操作時順帶做少量的維護工作,或者偶爾在讀操作時做——如果寫操作實在太少的話。

這樣做的原因在于:如果要自動地持續清理緩存,就必須有一個線程,這個線程會和用戶操作競爭共享鎖。此外,某些環境下線程創建可能受限制,這樣CacheBuilder就不可用了。參考如下示例:

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

public class GuavaCacheService {


    static Cache<Integer, String> cache = CacheBuilder.newBuilder()
            .expireAfterWrite(5, TimeUnit.SECONDS)
            .build();

    public static void main(String[] args) throws Exception {
        new Thread(() -> {
            while (true) {
                SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
                System.out.println(sdf.format(new Date()) + " size: " + cache.size());
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {

                }
            }
        }).start();
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        cache.put(1, "a");
        System.out.println("寫入 key:1 ,value:" + cache.getIfPresent(1));
        Thread.sleep(10000);
        cache.put(2, "b");
        System.out.println("寫入 key:2 ,value:" + cache.getIfPresent(2));
        Thread.sleep(10000);
        System.out.println(sdf.format(new Date())
                + " sleep 10s , key:1 ,value:" + cache.getIfPresent(1));
        System.out.println(sdf.format(new Date())
                + " sleep 10s, key:2 ,value:" + cache.getIfPresent(2));
    }
}

部分輸出結果:
23:57:36 size: 0
寫入 key:1 ,value:a
23:57:38 size: 1
23:57:40 size: 1
23:57:42 size: 1
23:57:44 size: 1
23:57:46 size: 1
寫入 key:2 ,value:b
23:57:48 size: 1
23:57:50 size: 1
23:57:52 size: 1
23:57:54 size: 1
23:57:56 size: 1
23:57:56 sleep 10s , key:1 ,value:null
23:57:56 sleep 10s, key:2 ,value:null
23:57:58 size: 0
23:58:00 size: 0
23:58:02 size: 0
    ...
    ...

上面程序設置了緩存過期時間為5S,每打印一次當前的size需要2S,打印了5次size之后寫入key 2,此時的size為1,說明在這個時候才把第一次應該過期的key 1給刪除。

給移除操作添加一個監聽器:

可以為Cache對象添加一個移除監聽器,這樣當有記錄被刪除時可以感知到這個事件:

RemovalListener<String, String> listener = notification -> System.out.println("[" + notification.getKey() + ":" + notification.getValue() + "] is removed!");
        Cache<String,String> cache = CacheBuilder.newBuilder()
                .maximumSize(5)
                .removalListener(listener)
                .build();

但是要注意的是:默認情況下,監聽器方法是在移除緩存時同步調用的。因為緩存的維護和請求響應通常是同時進行的,代價高昂的監聽器方法在同步模式下會拖慢正常的緩存請求。在這種情況下,你可以使用RemovalListeners.asynchronous(RemovalListener, Executor)把監聽器裝飾為異步操作。

自動加載

上面我們說過使用get方法的時候如果key不存在你可以使用指定方法去加載這個key。在Cache構建的時候通過指定CacheLoder的方式。如果你沒有指定,你也可以在get的時候顯式的調用call方法來設置key不存在的補救策略。

Cache的get方法有兩個參數,第一個參數是要從Cache中獲取記錄的key,第二個記錄是一個Callable對象。

當緩存中已經存在key對應的記錄時,get方法直接返回key對應的記錄。如果緩存中不包含key對應的記錄,Guava會啟動一個線程執行Callable對象中的call方法,call方法的返回值會作為key對應的值被存儲到緩存中,并且被get方法返回。

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;

public class GuavaCacheService {


    private static Cache<String, String> cache = CacheBuilder.newBuilder()
            .maximumSize(3)
            .build();

    public static void main(String[] args) {

        new Thread(() -> {
            System.out.println("thread1");
            try {
                String value = cache.get("key", new Callable<String>() {
                    public String call() throws Exception {
                        System.out.println("thread1"); //加載數據線程執行標志
                        Thread.sleep(1000); //模擬加載時間
                        return "thread1";
                    }
                });
                System.out.println("thread1 " + value);
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }).start();
        new Thread(() -> {
            System.out.println("thread2");
            try {
                String value = cache.get("key", new Callable<String>() {
                    public String call() throws Exception {
                        System.out.println("thread2"); //加載數據線程執行標志
                        Thread.sleep(1000); //模擬加載時間
                        return "thread2";
                    }
                });
                System.out.println("thread2 " + value);
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }).start();
    }

}

輸出結果為:
thread1
thread2
thread2
thread1 thread2
thread2 thread2

可以看到輸出結果:兩個線程都啟動,輸出thread1,thread2,接著又輸出了thread2,說明進入了thread2的call方法了,此時thread1正在阻塞,等待key被設置。然后thread1 得到了value是thread2,thread2的結果自然也是thread2。

這段代碼中有兩個線程共享同一個Cache對象,兩個線程同時調用get方法獲取同一個key對應的記錄。由于key對應的記錄不存在,所以兩個線程都在get方法處阻塞。此處在call方法中調用Thread.sleep(1000)模擬程序從外存加載數據的時間消耗。

從結果中可以看出,雖然是兩個線程同時調用get方法,但只有一個get方法中的Callable會被執行(沒有打印出load2)。Guava可以保證當有多個線程同時訪問Cache中的一個key時,如果key對應的記錄不存在,Guava只會啟動一個線程執行get方法中Callable參數對應的任務加載數據存到緩存。當加載完數據后,任何線程中的get方法都會獲取到key對應的值。

統計信息

可以對Cache的命中率、加載數據時間等信息進行統計。在構建Cache對象時,可以通過CacheBuilder的recordStats方法開啟統計信息的開關。開關開啟后Cache會自動對緩存的各種操作進行統計,調用Cache的stats方法可以查看統計后的信息。

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;


public class GuavaCacheService {


    public static void main(String[] args) {
        Cache<String, String> cache = CacheBuilder.newBuilder()
                .maximumSize(3)
                .recordStats() //開啟統計信息開關
                .build();
        cache.put("1", "v1");
        cache.put("2", "v2");
        cache.put("3", "v3");
        cache.put("4", "v4");

        cache.getIfPresent("1");
        cache.getIfPresent("2");
        cache.getIfPresent("3");
        cache.getIfPresent("4");
        cache.getIfPresent("5");
        cache.getIfPresent("6");

        System.out.println(cache.stats()); //獲取統計信息
    }

}

輸出:
CacheStats{hitCount=3, missCount=3, loadSuccessCount=0, loadExceptionCount=0, totalLoadTime=0, evictionCount=1}


責任編輯:武曉燕 來源: 一安未來
相關推薦

2022-09-21 08:16:18

緩存框架

2025-10-29 01:22:00

2023-09-11 07:46:03

Cache2k緩存

2024-01-04 08:33:11

異步JDK數據結構

2025-05-16 08:53:06

2009-09-22 10:50:04

Hibernate c

2017-04-10 18:34:16

AndroidNotificatio

2025-06-27 07:19:48

2018-07-14 21:59:57

緩存數據庫數據

2010-07-22 09:25:09

telnet命令

2010-03-09 17:19:01

Linux時鐘

2010-06-24 15:35:04

IPx協議

2020-12-23 13:14:00

LinuxLinux內存Swap

2021-03-30 10:50:18

Linux內存命令

2009-11-11 17:02:44

MPLS路由協議

2010-10-20 15:11:53

SQL Server作

2024-11-15 10:58:40

2009-01-12 10:27:07

IT職位解析認證

2012-11-15 13:42:29

2009-12-25 16:47:04

Linux Make規
點贊
收藏

51CTO技術棧公眾號

欧美日本一区二区| 久久这里只有精品首页| 欧美久久精品午夜青青大伊人| 国产精品熟女一区二区不卡| 黄页网站在线| 国产日韩综合av| 97视频中文字幕| 综合网在线观看| 亚洲综合色网| 亚洲系列中文字幕| 韩国av中国字幕| 欧美电影免费观看高清完整| 亚洲激情一二三区| 日本成人三级| 国产小视频一区| 美女久久久精品| 国模精品视频一区二区三区| 国产传媒在线看| 卡通动漫精品一区二区三区| 欧美日本免费一区二区三区| 男人天堂999| 在线黄色网页| 国产精品天干天干在观线| 国产视频一区二区不卡| 国产成人av免费看| 卡一卡二国产精品| 国产不卡在线观看| 日韩欧美一区二区一幕| 欧美有码视频| 久久精品一偷一偷国产| 日本精品在线观看视频| 精品综合久久88少妇激情| 制服丝袜一区二区三区| 亚洲福利精品视频| 欧美羞羞视频| 日韩欧美成人区| 精品无码一区二区三区爱欲| 制服丝袜在线播放| 成人欧美一区二区三区黑人麻豆| 日本黑人久久| 国产中文在线| www国产精品av| 俄罗斯精品一区二区| 国产又粗又大又黄| 久久超级碰视频| 国产精品女主播| 日韩精选在线观看| 日韩高清不卡一区二区三区| 日本精品va在线观看| 日本一级黄色大片| 99成人在线| 午夜精品久久久久久久99热 | 一级二级三级视频| 日韩高清一区二区| 国产精品久久久久久av福利软件| 久久久久99精品成人片三人毛片| 亚洲国产精品一区| 久久久亚洲国产| 日韩xxxxxxxxx| 国产日韩欧美一区在线| 欧美又大又硬又粗bbbbb| 国产成人无码精品| 久久综合中文| 国产深夜精品福利| 国产毛片久久久久| 福利电影一区二区| 国产福利久久| 亚洲欧美综合在线观看| 国产偷v国产偷v亚洲高清| 色噜噜狠狠一区二区三区| av在线之家电影网站| 国产精品久久久久久亚洲毛片| 青青草原国产免费| 欧洲黄色一区| 黑人巨大精品欧美一区二区一视频 | 久久一卡二卡| 欧美日韩国产区| 天天爽天天爽夜夜爽| 国产成人精品一区二区三区免费| 欧美日韩高清一区| 天堂va欧美va亚洲va老司机| 青青久久av| 一本色道久久88亚洲综合88| www.av免费| 在线成人av| 国产精国产精品| 99国产揄拍国产精品| 99re这里只有精品视频首页| 欧美一级二级三级| 菠萝蜜视频国产在线播放| 亚洲第一久久影院| 麻豆一区二区三区视频| 亚洲2区在线| 亚洲人成电影在线观看天堂色| 秋霞网一区二区三区| 激情欧美一区二区三区| 国产不卡精品视男人的天堂| 国产三级自拍视频| 久久免费电影网| 男女h黄动漫啪啪无遮挡软件| 少妇视频一区| 欧美丰满少妇xxxbbb| www.日本高清| 亚洲国产精品久久久天堂| 热re91久久精品国99热蜜臀| 精品久久久中文字幕人妻| 久久久天堂av| 欧美乱做爰xxxⅹ久久久| 国产成人精品一区二三区在线观看 | 欧美黑人极品猛少妇色xxxxx| 五月婷婷激情视频| 懂色av一区二区在线播放| 日韩欧美亚洲v片| 黄毛片在线观看| 91精品国产综合久久婷婷香蕉| 欧美熟妇一区二区| 激情丁香综合| 国产美女91呻吟求| 好男人免费精品视频| 亚洲午夜激情av| 亚洲综合伊人久久| 色综合咪咪久久网| 热re99久久精品国产66热| 丰满少妇一级片| 亚洲欧美日韩成人高清在线一区| 成人在线看视频| 欧美一级二级三级视频| 欧美日韩成人在线播放| 亚洲天堂视频网| 国产欧美一区在线| 国产精品网站免费| 中文在线综合| 欧美日本亚洲视频| 国产成人三级在线播放 | 亚洲欧美国产制服动漫| 亚洲国产综合久久| 国产69精品久久99不卡| 超碰超碰超碰超碰超碰| 韩国一区二区三区视频| www.日韩av.com| 在线视频1卡二卡三卡| 欧美激情一区二区三区蜜桃视频| 欧美在线观看成人| 香蕉国产成人午夜av影院| 国内精品一区二区三区| 特黄aaaaaaaaa真人毛片| 亚洲午夜在线电影| 六十路息与子猛烈交尾| 国产精品婷婷| 欧美日韩在线观看一区二区三区| 在线观看网站免费入口在线观看国内| 亚洲国产欧美在线成人app| 国产无遮挡裸体免费视频| 波多野结衣视频一区| 国自产拍偷拍精品啪啪一区二区| 久久视频在线观看| 欧美一级视频一区二区| 九色在线视频蝌蚪| 欧美日韩一区在线| 搜索黄色一级片| 国产suv精品一区二区6| 欧美一级免费播放| 久久91精品| 91精品久久久久久综合乱菊| h网站久久久| 精品免费国产二区三区 | 日本大胆在线观看| 亚洲国产精品久久久| 中文字幕超碰在线| 欧美激情一区二区在线| www激情五月| 精品不卡视频| 欧美日韩免费精品| 欧美三级电影网址| 色综合久久悠悠| 人成在线免费视频| 欧美日韩亚洲综合在线| 欧美日韩免费一区二区| 91丨porny丨最新| 中文字幕在线综合| 国产精品观看| 日产精品一线二线三线芒果| 91p九色成人| 九九热最新视频//这里只有精品| 亚欧洲精品视频| 欧美日韩国产一级片| 精品少妇爆乳无码av无码专区| 91在线播放网址| 精品久久久99| 亚洲少妇诱惑| 在线观看日韩羞羞视频| 国产欧美三级电影| 成人国产亚洲精品a区天堂华泰| 伦理在线一区| xxav国产精品美女主播| 日本精品久久久久久| 欧美日韩国产综合一区二区三区 | 国产精品xxx在线观看www| 国产精品专区免费| 九九热精品在线| 国产最新视频在线观看| 亚洲第一天堂无码专区| 一二三四区在线| 色综合咪咪久久| 九九视频免费看| 中文字幕精品一区二区精品绿巨人| 久久久久久无码精品人妻一区二区| 日韩精品1区2区3区| av女优在线播放| 一区二区日韩欧美| 日韩美女一区| 神马香蕉久久| 国产高清自拍一区| 伊人久久大香| 国产精品一区二区久久| 欧美成人ⅴideosxxxxx| 久久久免费精品| av在线麻豆| 俺也去精品视频在线观看| 欧美另类自拍| 亚洲国模精品一区| www.天堂av.com| 欧美精品亚洲二区| 中文在线观看av| 日韩欧美高清在线视频| 91浏览器在线观看| 亚洲一区二区黄色| 欧美人妻精品一区二区三区| 中文字幕一区在线观看视频| 亚洲精品午夜视频| 91在线视频免费91| 2一3sex性hd| 国产成人免费av在线| 日韩a一级欧美一级| 麻豆精品在线播放| 国产精品视频中文字幕| 免费人成精品欧美精品| 99免费视频观看| 久久亚洲电影| 日本熟妇人妻中出| 久久久精品五月天| 免费日韩中文字幕| 久久激情综合| 国产视频在线视频| 日韩av网站在线观看| 午夜两性免费视频| 久久精品国产精品亚洲红杏 | 成人亚洲一区二区一| www.黄色网| 高清日韩电视剧大全免费| 永久av免费在线观看| 国产精品亚洲视频| 中文字幕制服丝袜| av中文字幕不卡| 国产特黄级aaaaa片免| 欧美国产精品一区二区| 四虎影视一区二区| 亚洲视频狠狠干| 免费在线黄色片| 天天做天天摸天天爽国产一区 | 久草免费在线色站| 国模叶桐国产精品一区| 九色porny自拍视频在线播放| 国产69精品久久久久久| 日本综合视频| 亚洲一区久久久| 国产福利资源一区| 久久综合一区二区三区| 日本黄色精品| 中文字幕黄色大片| 在线精品亚洲| www.日日操| 国产中文字幕精品| 国产真实乱人偷精品| 国产丝袜在线精品| 国精品无码一区二区三区| 午夜精品成人在线| 中文字幕一区二区在线视频| 日韩一级成人av| 视频二区在线| 日韩一区二区福利| √天堂8资源中文在线| 国产精品福利网站| 中文无码日韩欧| 视频一区视频二区视频三区视频四区国产 | 91欧美一区二区| 在线观看黄网址| 欧美午夜性色大片在线观看| 91精东传媒理伦片在线观看| 亚洲电影天堂av| 欧美人xxx| 欧美亚洲伦理www| 国产午夜亚洲精品一级在线| 精品国产乱码久久久久久88av| 成人3d动漫在线观看| 蜜臀av色欲a片无码精品一区| 青青草97国产精品免费观看| 成人在线电影网站| 亚洲欧美综合网| 可以免费在线观看的av| 欧美一级片在线看| 黄色影院在线播放| 午夜精品久久久久久久男人的天堂 | 日本一区美女| 亚洲网站在线| 97超碰成人在线| 久久久久99精品国产片| 国产性70yerg老太| 91麻豆精品91久久久久久清纯 | 国产精品男女| 中文字幕人成一区| 日日摸夜夜添夜夜添精品视频| 中文字幕在线视频播放| 中文字幕在线视频一区| 成年人晚上看的视频| 亚洲国产精品中文| 污影院在线观看| 成人免费淫片视频软件| 欧洲激情综合| 日本一本二本在线观看| 成人激情午夜影院| 青青青在线视频| 91精品国产综合久久久久久久久久 | 91精品国产91久久久久麻豆 主演| 久久精品99国产国产精| 黄色av免费播放| 在线精品亚洲一区二区不卡| 少妇人妻精品一区二区三区| 欧美多人乱p欧美4p久久| 国产精品日本一区二区三区在线| 天堂精品视频| 日韩精品国产精品| 极品蜜桃臀肥臀-x88av| 在线这里只有精品| 免费国产在线视频| 91精品国产高清久久久久久久久 | 国产在线不卡一区| 成人无码精品1区2区3区免费看 | 北条麻妃亚洲一区| 亚洲欧洲另类国产综合| 中文字幕一二三四| 在线免费看av不卡| 欧洲精品一区二区三区| 日韩中文一区二区三区| 免费精品视频在线| 少妇太紧太爽又黄又硬又爽小说| 在线免费观看不卡av| 国产福利第一视频在线播放| 国产精品久久久久久久久久小说| 欧美亚洲国产激情| 四季av一区二区三区| 亚洲欧洲美洲综合色网| av观看在线免费| 久久久久久噜噜噜久久久精品| 超碰精品在线| 日韩在线综合网| 久久久亚洲综合| 中文字幕欧美色图| 精品国产一区二区三区久久狼黑人| 国产999精品在线观看| 福利在线小视频| www.欧美.com| 国产伦精品一区二区三区视频网站| 国产一区二区三区毛片| 日韩成人在线电影| 日本久久久网站| 国产无遮挡一区二区三区毛片日本| 中文字幕精品一区二| 九九热最新视频//这里只有精品| aaa国产精品视频| 黄色a级片免费| 国产精品青草综合久久久久99| 国产高清视频免费| 91精品国产91久久久久久不卡| 国产永久精品大片wwwapp| 亚洲黄色av片| 天天av天天翘天天综合网色鬼国产| 免费a级毛片在线观看| 国产一区视频在线| 亚洲毛片在线| av片在线免费看| 欧美精品一区二区不卡| 外国成人直播| 337p亚洲精品色噜噜狠狠p| 久久综合久久综合亚洲| 国产女人高潮毛片| 欧洲成人免费视频| 99re66热这里只有精品8| 欧产日产国产精品98| 欧美三级资源在线| 华人av在线| 男人天堂成人网| 久久亚洲精华国产精华液| jizz中国少妇| 国产精品国产三级国产aⅴ浪潮| 欧美人成在线| 亚洲一级理论片| 亚洲精品视频在线观看视频| 久久伊人久久| 国产wwwxx|