亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        大數據時代Redis緩存的性能分析與優(yōu)化

        2022-09-14 03:25:36張蒙蒙曹成茂
        巢湖學院學報 2022年3期
        關鍵詞:數據庫資源

        張蒙蒙 曹成茂

        (安徽農業(yè)大學 工學院,安徽 合肥 230036)

        0 引言

        隨著與計算機相關的物聯網技術、云計算及大數據技術的發(fā)展擴大[1],業(yè)務系統的數據量越來越龐大。對系統提出了更高的性能要求,傳統的Web技術一般采用關系型數據庫[2],將數據存儲到數據庫中,一旦有數據請求,則從數據庫服務器中獲取數據。但是隨著數據量的不斷增加,用戶對數據訪問的相對集中,就會出現數據庫服務器負擔過重、數據庫服務器的響應效率降低[2]、瀏覽器的響應延遲增加等問題。針對以上問題,計算機可以通過硬件和軟件技術的改進來匹配大數據量、高并發(fā)的需要。硬件的提升在一定范圍內可以達到好的效果。但是更多的則是對軟件技術的改進。在這種背景下,緩存技術應運而生。從第一個緩存框架Memcached誕生以來,緩存技術一直廣泛地存在于互聯網應用中。而Redis也因其高性能分布式純內存緩存技術的優(yōu)勢在現代互聯網信息系統緩存中占據著絕對的優(yōu)勢。Redis是一個基于鍵值對的存儲結構系統,提供了許多實用的功能,如主從復制、RedisMQ消息隊列、Redis集群等[3]。Redis緩存技術的應用使得對服務端的請求很多轉移到緩存上從而大大緩解了服務器的負擔[4]。在Redis的使用中,可以通過許多方式來進一步提升Redis效率。將從Redis的性能分析入手,分析Redis的性能優(yōu)勢強大的原因,然后從使用中對Redis的性能提出一些改進的優(yōu)化方案,進而更好的提升Redis的用戶使用體驗。如圖1所示。

        圖1 加入Redis后的業(yè)務請求

        1 Redis的性能優(yōu)勢

        Redis官網中提到,在局域網環(huán)境下只要傳輸的包不超過一個MTU(以太網下大約1500字節(jié)),那么對于100字節(jié)、1000字節(jié)不同包大小的吞吐處理能力實際結果差不多。針對這種說法,從實驗中進行驗證發(fā)現和官網提的說法有一定的出入,這主要是因為網絡及客戶端的影響導致與理論的結果有偏差。在實驗環(huán)境的測試下,可以從圖2中看到,Redis在處理1000字節(jié)的數據的時候,吞吐量都是穩(wěn)定在10w/s的請求量,當處理的數據不斷增大的時候,吞吐量才慢慢開始下降,而實際的數據量很少能達到這個數量級。單個的Redis實例運行相對穩(wěn)定,計算機單核CPU的有效利用率在75%之間波動。

        圖2 Redis吞吐量與數據包大小關系圖

        對于大多的數據請求,Redis的處理響應效率都會保持在較高的水平。Redis為什么能達到那么快的性能,其主要原因如下。

        1.1 純內存的KV操作

        Redis是一種非關系型保存在內存中的數據庫[4]。計算機的內存速度相對比較快,而Redis的絕大部分請求是在內存中處理的。Redis內部普遍采用HashMap的數據結構,而HashMap數據結構的優(yōu)勢是查找和插入操作的時間復雜度都是O(1),所以Redis能夠獲得很高的響應速度[5](見表1)。

        表1 不同數據結構的時間復雜度

        1.2 單線程操作實現

        Redis的使用并不受計算機CPU的限制,而是受計算機網絡和內存的限制[6]。Redis官網也提到Redis在使用的時候,使用單線程就已經能夠獲取Redis足夠使用的CPU資源,主要的瓶頸還是在于計算機的內存,如果使用多線程就會帶來多余的資源占用。

        1.2.1 上下文切換

        計算機程序中的上下文其實就是某種多線程執(zhí)行狀態(tài)下CPU中寄存器和程序計數器狀態(tài)。主要的作用就是存放沒有被分配到資源的線程。在多線程操作的時候,每個線程同步執(zhí)行,而CPU資源只有一個,不是每一個線程都能夠直接獲取到CPU資源的[7],某一時刻,必然存在運行、掛起和阻塞狀態(tài)下的線程。之所以能夠看到計算機上能夠運行很多的程序,是因為多線程在執(zhí)行的過程中CPU不斷對多線程的切換。每個線程都是按照時間片原則來執(zhí)行的。因此總有線程獲取到資源,也總有線程需要等待獲取資源,這個時候,等待獲取資源的線程就需要被掛起,其現場需要被保存,也就是所說的寄存。這個時候上下文就產生了,當上下文再次被喚起得到資源的時候,就是所說的上下文的切換。單線程則不需要上下文切換,也就減少了這部分的開銷。

        1.2.2 資源競爭

        多線程涉及到資源競爭,而往往線程所需要的資源比計算機實際能提供的資源要多,所以這就涉及到資源的有效分配,而當前沒被分配到資源的線程就要等待全部資源的滿足才能運行。CPU對上下文的切換實質是一種資源分配,許多線程都在對資源進行請求,但是在切換之前,到底切換到哪一個上下文,就是資源競爭的開始。如果資源分配不合理還會出現死鎖的風險。Redis中由于是單線程的,所以所有的操作都不會涉及到資源的競爭,這就減少了等待資源的時間。

        1.2.3 加鎖的消耗

        對于多線程的情況,不能回避的就是鎖的問題。這就涉及到多線程之間的并發(fā)和同步的問題,多線程操作出現并發(fā),有可能導致數據不一致,或者操作達不到預期的效果。為了實現線程同步,這個時候就需要加鎖來解決這些問題。當線程很多的時候,就需要不斷的加鎖,釋放鎖。這就會無形中增加了資源的消耗。Redis的單線程則不會有多線程的并發(fā)和同步的問題也就不存在鎖的情況,所以資源消耗少,效率快。

        1.3 異步非阻塞的I/O

        I/O操作的阻塞是指當用戶線程發(fā)出I/O請求之后,計算機內核會去查看數據是否準備就緒,如果沒有就緒就會等待數據就緒,而用戶線程就會處于阻塞狀態(tài),用戶線程交出CPU資源。當數據就緒之后,內核會將數據拷貝到用戶線程,返回結果給用戶線程,用戶線程才解除阻塞狀態(tài)。Redis采用的多路復用其實是在單個線程中通過記錄跟蹤每一個I/O流的狀態(tài)來管理多個I/O流。Epoll,poll,select都是 I/O 多路復用的具體的實現。Epoll性能比其他幾個要好。Redis中的I/O多路復用的所有功能是通過包裝常見的Epoll,poll,select和kqueue這些I/O多路復用函數庫來實現的。

        2 Redis性能優(yōu)化策略

        Redis是性能比較好的緩存技術,但是在使用中如果不適當的使用也會限制Redis的高效率,不能很好的發(fā)揮Redis的性能優(yōu)勢。所以,針對不同的使用場景如何最大限度地提高Redis的使用效率呢?以下將從幾個方面分別進行分析,并給出相應的解決方案。

        2.1 設置鍵值的過期時間

        在實際使用中,當插入鍵值對的時候,有一個參數可以設置鍵值對的過期時間,當到達過期時間則自動清除該鍵值。可以根據業(yè)務的實際使用情況,對鍵值對設置合理的過期時間,一方面可以及時的清除過期的key值,減少對Redis內存空間的占用,使得更多有用的數據從計算機內存調入Redis內存;另一方面也能在查詢數據的時候避免過多的無用鍵值對堆積,導致Redis中頁面的命中時間增加,同時也避免了頻繁的觸發(fā)Redis內存的頁面淘汰策略以及減少計算機物理內存的頁面置換時間。這也是Redis在設計過期時間的初衷時極力推薦的一種做法。減少了數據的冗余,顯然是能夠很大的提高Redis的使用性能的。如圖3所示。

        圖3 Redis設置鍵值對過期時間

        雖然可以設置每個鍵的過期時間,但是同樣也要注意避免發(fā)生緩存雪崩問題。緩存雪崩是指設置緩存時很多采用了相近的過期時間,當緩存中大批量數據都達到這一過期時間時,會導致請求量全部請求到服務端數據庫,最終導致數據庫瞬時壓力過大而崩潰。造成數據庫宕機,這就是緩存雪崩現象。如圖4所示。

        圖4 緩存雪崩示意圖

        解決此問題的方法就是預防大量的key在同一時刻過期,最簡單的方案就是在原有失效時間的基礎上增加一個隨機時間,例如1~5分鐘,這樣每個緩存過期時間的重復率就會降低,從而減少緩存雪崩的發(fā)生。或者采用雙緩存機制,緩存A和B,比如A的失效時間是20 min,B不失效。比如從A中沒讀到,就去B中讀,然后異步起一個線程同步到A。還可以使用異步重建緩存,在這種方案下構建緩存采取異步策略,會從線程池中獲取線程來異步構建緩存,從而不會讓所有的請求直接到達存儲層,該方案中每個key維護邏輯超時時間,當邏輯超時時間小于當前時間時,則說明當前緩存已經失效,應當進行緩存更新,否則說明當前緩存未失效,直接返回緩存中的值。如在Redis中將key的過期時間設置為100 min,在對應的Value中設置邏輯過期時間為50 min。這樣當key到了50 min的邏輯過期時間,就可以異步更新這個key的緩存,但是在更新緩存的這段時間內,舊的緩存依然可用。這種異步重建緩存的方式可以有效避免大量的key同時失效。還有一種最簡單的方式就是不設置緩存的過期時間,這樣就不會出現大量緩存同時失效的問題,但隨之而來的是Redis需要更多的存儲空間。

        2.2 限制Redis的內存占用大小

        Redis通過設置maxmemory來設置Redis的最大內存。然而在64位操作系統中,因為maxmemory配置項是被注釋掉的,所以Redis的內存大小沒有限制。這樣就會導致在Redis內存不足時會使用磁盤作為其虛擬內存,而當操作系統將Redis所用的內存分配至磁盤時,將會阻塞Redis進程,導致Redis出現延遲,從而影響Redis的整體性能,因此要限制Redis的內存大小為一個固定的值,并且該值不能大于服務器的內存。當Redis的運行達到此值時會觸發(fā)內部的淘汰策略,從而將內存回收。

        如圖5所示,從實驗圖中的趨勢可以看出在實際使用中,Redis內存在一開始是隨著占據內存的增加命中率逐步提高的,但是當達到一定的量級后,其命中率并不會隨著內存的繼續(xù)增加而增加,反而會降低。剛開始Redis內存的增加會使得一些操作都轉移到Redis中完成,許多所需的數據都在Redis中命中,無需訪問數據庫。而隨著Redis內存的逐步增加及數據的增多必然導致頻繁的進行與內存的頁面置換操作,數據量的增多也會導致檢索時間的增加。頻繁的頁面置換往往也導致一些所需的頁面不在Redis內存中而不得不重新到內存中去查找所需的數據,導致命中率逐步降低。所以從圖5的趨勢中建議Redis內存大小設置在物理內存的1/2到1/4為最佳Redis內存大小。

        圖5 Redis內存大小與命中率的關系圖

        如表2所示,頁面淘汰算法主要有LRU和LFU,LRU即最近最少未使用,是淘汰最長時間沒有被使用的頁面,其側重的是最近被訪問的數據不刪除,而LFU即最不經常使用淘汰算法,淘汰一段時間內,使用次數最少的頁面,是保證訪問頻率最高的數據不被刪除,但是LFU有一個缺點,就是如果在某一個時段,某個key的訪問頻率非常高,那么該key就會變?yōu)闊狳c數據,但是實際上該key在其他時間節(jié)點不會被用到,那么會造成這些數據不會被刪除。所以可通過LRU替換算法來限制內存的使用。

        表2 Redis中的8種淘汰策略

        2.3 Redis內存優(yōu)化設計

        要知道Redis中數據的占用內存大小,需要對Redis的內存模型有個全面的了解。假設Redis中有m個鍵值對,且Redis鍵值都不是整數類型,則占用的空間可以分為兩部分,一部分是m個dictEntry占據的字符串,每個dictEntry占據的空間包括:一個key,一個dictEntry結構、一個Object。一個value,另一部分是鍵值對所需要的bucket空間。其空間即為兩部分之和。則由內存模型出發(fā)可對其做如下優(yōu)化(如圖6)。

        圖6 Redis內存存儲結構

        2.3.1 使用內存分布器jemalloc特性優(yōu)化

        由于簡單動態(tài)字符串SDS等于字符串長度加4,jemalloc分配的空間是不連續(xù)的,因此KV字符串變化一個字節(jié),可能會引起占用內存的很大變化,在設計時可以利用這一點。例如如果key的長度是13,則SDS為17個字節(jié),那么jemalloc就會分配32個字節(jié);如果將key的長度縮減為12個字節(jié),則SDS為16個字節(jié),jemalloc會分配16個字節(jié),這樣每個key所占用的空間就可以縮小一半。

        2.3.2 盡量使用整形/長整形

        使用字符串會造成空間的浪費,如果使用整型或長整型,Redis會使用int類型(8個字節(jié))存儲來替代字符串類型,使得其長度都是8的整數倍,這樣計算機在分配空間的時候可以避免一些小的碎片的產生,這樣可以節(jié)省更多資源空間,讓更多的數據存儲到Redis緩存中,減少了數據庫的訪問,從而提升Redis的使用效率。因此在可以使用整型或長整型代替字符串的場景下,我們應該盡量使用整型或長整型。

        2.3.3 共享對象

        利用已經建立的共享對象,則可以大幅度減少Redis中對象的創(chuàng)建和銷毀,同時也相應的減少了RedisObject的創(chuàng)建,對象的創(chuàng)建和銷毀需要時間并且耗費計算機資源,所以使用共享對象從而節(jié)省空間。

        2.3.4 縮短鍵值對的存儲長度

        鍵值對的長度同樣也影響著Redis的性能,鍵值對的長度是和性能成反比的,所以在使用中應盡量縮小鍵值對。由實驗得出如下結論(數據量為100萬)。由表3中可知,在數據量一定key保持不變的情況下,value值越大則操作效率越低,因為Redis對于同一種數據類型會使用不同的內部編碼進行存儲,比如字符串的內部編碼就有三種:int、embstr、raw,這是因為 Redis是想通過不同的編碼實現效率和空間的平衡,然而數據量越大使用的內部編碼就越復雜,而越復雜的內部編碼存儲的性能就越低。同時內容越大,需要的持久化、掛起的時間就越長,網絡上傳輸的內容多,時間就越長,占用的內存就會多,以至于頻繁的觸發(fā)內存淘汰機制。所以在保證業(yè)務完整的同時,盡量縮短鍵值對的存儲長度,也可以在需要的時候對鍵值對進行壓縮存儲或者序列化操作。

        表3 Redis鍵值對長度效率影響

        2.4 緩存穿透優(yōu)化

        緩存穿透是指查詢一個在緩存和數據庫中都不存在數據,這樣當緩存層里面沒有時,就會去訪問后面的存儲層了(如圖7)。

        圖7 緩存穿透示意圖

        如果有大量的這種惡意請求過來,都會轉向后面的存儲層。顯然存儲層是扛不住這樣的壓力。這樣緩存就失去了保護后面存儲的意義了。解決方法如下(如圖8)。

        圖8 布隆過濾器Hash映射方式

        2.4.1 布隆過濾器優(yōu)化

        其原理是對于不存在的數據布隆過濾器一般都能夠過濾掉,不讓請求再往后端發(fā)送。當布隆過濾器說某個值存在時,這個值可能不存在;但是它說不存在時,那就肯定不存在。布隆過濾器是一個大型的位數組和幾個不一樣的無偏Hash函數。所謂無偏就是能夠把元素的Hash值算得比較均勻。向布隆過濾器中添加key時,會使用多個Hash函數對key進行Hash運算分別算得一個整數索引值然后對位數組長度進行取模運算得到一個位置,每個Hash函數都會算得一個不同的位置。再把位數組的這幾個位置都置為1就完成了添加操作。向布隆過濾器詢問key是否存在時跟添加一樣,也會把Hash的幾個位置都算出來,看看位數組中這幾個位置是否都為1,只要有一個位為0,那么說明布隆過濾器中這個key肯定不存在。但是都是1,這并不能說明這個key就一定存在,只是極有可能存在,因為這些位被置為1可能是因為其它的key存在所致。這種方式能很好地提升緩存的利用率[8]。

        如表4所示,從實驗數據中可以得出當只有1個Hash函數的時候,誤判率很高,但是當有4個Hash函數的時候已經縮小接近20多倍,可以動態(tài)根據業(yè)務需求所允許的識別率來調整Hash函數的個數,找出最適合的Hash函數個數,當然Hash函數也不是越多越好,太多的Hash函數所帶來的空間效率和查詢效率也會有所降低。

        表4 不同Hash函數個數對碰撞誤判率影響

        2.4.2 接口層增加校驗

        在接口層增加鑒權校驗,可以設定請求的合格條件,當外在請求不能滿足條件時則禁止其訪問數據庫服務器和緩存,避免了無效數據的頻繁惡意攻擊。

        2.4.3 設置空數據值為null

        當從緩存取不到的數據,在數據庫中也沒有取到,這時也可以將key-value對寫為key-null,直接返回空值。緩存有效時間可以設置短點,如30秒。這樣就能避免短時間內的大量無效請求負擔。

        2.5 緩存擊穿優(yōu)化

        緩存擊穿是指緩存中沒有但數據庫中有的數據,當一個key短期內頻繁訪問,在不停的進行請求,大并發(fā)集中對這一個點進行訪問;當這個key在失效的瞬間,持續(xù)的大并發(fā)就穿破緩存,直接請求數據庫,就像在一個屏障上鑿開了一個洞。針對這種問題一方面可以設置熱點數據永遠不過期解決,另一種可以通過添加互斥鎖代碼實現對數據的訪問(如圖9)。

        圖9 緩存擊穿示意圖

        互斥鎖代碼如下:

        如果緩存中有數據,則直接返回,如果沒有,則第一個進入的線程先去查詢數據庫,并加上鎖,其他線程則等待,這樣就能防止去數據庫查重復數據、重復更新緩存了。

        2.6 使用Redis管道技術

        管道技術是客戶端提供的一種批處理技術,Redis是支持管道的,用于一次處理多個Redis命令,Redis管道技術在服務端未響應時,客戶端可以繼續(xù)向服務端發(fā)送請求,并最終一次性讀取所有服務端的響應。從而提高整個交互的性能(如圖10)。

        圖10 有無管道Redis命令處理圖

        使用Java代碼來測試一下Pipeline和普通操作的性能對比,Pipeline測試代碼如下:

        以上程序執(zhí)行結果:執(zhí)行耗時:18003ms。

        從以上結果可以看出,管道的執(zhí)行時間是302 ms,而普通命令執(zhí)行時間是18003 ms,管道技術要比普通的執(zhí)行大約快了58倍。很明顯利用管道技術可以大幅度提高Redis的使用性能。

        2.7 使用lazy free特性

        2.7.1 什么是lazy free

        Lazy free是Redis最新的技術,它可以理解為惰性刪除或延遲刪除,意思就是在刪除的時候提供異步刪除的功能,它把刪除key的操作放在BIO單獨的子線程處理中,以減少刪除操作對Redis主線程的阻塞,同時可以有效的避免刪除大的key時帶來的性能和可用性問題。

        2.7.2 使用lazy free優(yōu)勢

        Redis除少量的BIO任務外基本上是單線程程序,當運行一個耗時較大的請求時,會導致所有請求排隊等待,Redis不能響應其他請求,從而引起性能問題,甚至集群發(fā)生故障切換。而Redis刪除大的集合鍵時,就屬于這類比較耗時的請求。通過測試來看,刪除一個100萬個元素的集合鍵,耗時約1000ms左右(如表5)。

        表5 Redis不同key類型大集合刪除效率

        以下測試,刪除一個100萬個字段的Hash鍵,耗時1360 ms;處理此DEL請求期間,其他請求完全被阻塞(如圖11、圖12)。

        圖11 Redis大hash鍵刪除測試

        圖12 Redis主動刪除大鍵測試

        引入lazy free后,這類主動或被動的刪除big key時,和一個O(1)指令的耗時一樣,亞毫秒級返回;把真正釋放Redis元素耗時動作交由BIO后臺任務執(zhí)行。示例如下:使用UNLINK命令刪除一個大鍵mylist,它包含200萬個元素,但用時只有0.03ms。顯然比上面沒有引入lazy free技術刪除100萬個元素需要1360ms性能有了很大的提高。

        2.8 其他優(yōu)化策略

        2.8.1 客戶端優(yōu)化

        在客戶端還需要盡量使用Redis連接池,而不是頻繁的創(chuàng)建、銷毀Redis連接。這樣就可以減少網絡傳輸次數和減少非必要的調用命令。

        2.8.2 禁用長耗時的查詢命令

        Redis中大多的讀寫命令都能在時間復雜度為O(1)的情況下完成,因此效率極高,但也不可避免的會遇到復雜度為O(N)的讀寫操作,這時就就需要注意查詢速度慢的問題,因為Redis是單線程的,查詢只有一個線程操作,對于耗時的指令會出現Redis的延遲??梢赃M行以下改進(如表6)。

        表6 Redis長耗時查詢命令改進

        2.8.3 使用slowlog優(yōu)化耗時的命令

        這種方法可以幫助找出哪些命令是比較耗時的指令,從而可以有針對性地進行單獨優(yōu)化從而提高Redis的性能。Redis中存在著許多讀寫命令,他們執(zhí)行的時間不一,那么必然存在一些耗費時間比較多的命令,如果耗費時間比較多的命令大量存在則勢必會降低Redis的效率,所以需要對這些高耗時的命令進行查詢檢測。使用showlog功能就能查詢出最耗時的Redis命令,進而進行優(yōu)化來提高Redis的速度。

        2.8.4 使用分布式架構來增加讀寫速度

        Redis的分布式架構有主從同步、哨兵模式、Redis Cluster集群,主從同步可以將寫操作放在master上處理,可以將讀操作放在slave上處理,因此極大的提高了Redis的處理性能;而Sentinel是對主從同步的一個升級,解決了單點故障以及故障遷移的問題;而RedisCluster集群,在Redis3.0推出,解決了Redis的擴展問題,并且將讀寫操作使用hash分布到了不同的Redis服務器上,極大的提高了Redis命令的操作性能。選擇上首選Redis Cluster集群的實現方案。

        2.8.5 使用物理機而非虛擬機

        在虛擬機中運行Redis服務器,因為和物理機共享一個物理端口,并且一臺物理機可以有多個虛擬機在運行,因此在內存占用上和網絡延遲方面會有很糟糕的表現,可以使用./redis-cli--intrinsic-latency100命令來查看延遲時間,如果對Redis性能要求很高的話,應盡可能在物理機上直接部署Redis服務器。

        3 結語

        在當前Web信息系統的發(fā)展下,面對大數據量、高并發(fā)、高響應比的需求,Redis都很好的解決了以上問題,同時Redis這些年也在根據用戶的需求不斷的更新功能和性能優(yōu)化,使得Redis能更加靈活的使用在多個業(yè)務場景中,同時也需要我們在使用中進行認真的思考,在性能上選擇最適合自己業(yè)務系統的功能,合理的利用Redis的多功能,提升Redis的業(yè)務體驗。

        猜你喜歡
        數據庫資源
        讓有限的“資源”更有效
        基礎教育資源展示
        一樣的資源,不一樣的收獲
        資源回收
        數據庫
        財經(2017年15期)2017-07-03 22:40:49
        資源再生 歡迎訂閱
        資源再生(2017年3期)2017-06-01 12:20:59
        數據庫
        財經(2017年2期)2017-03-10 14:35:35
        數據庫
        財經(2016年15期)2016-06-03 07:38:02
        數據庫
        財經(2016年3期)2016-03-07 07:44:46
        數據庫
        財經(2016年6期)2016-02-24 07:41:51
        亚洲中文字幕在线综合| 久久久AV无码精品免费| 亚洲欧洲美洲无码精品va| 国产我不卡在线观看免费| 日韩精品人妻久久久一二三| 免费视频爱爱太爽了| 久久婷婷色综合一区二区| 亚洲成AV人片无码不卡| 国产精品亚洲一区二区三区在线 | 男女视频网站免费精品播放| 九九久久精品国产免费av| 国产精品无码aⅴ嫩草| 久久免费视频国产| 秀人网嫩模李梓熙大尺度| 邻居人妻的肉欲满足中文字幕| 蜜臀色欲av在线播放国产日韩| 伊人精品在线观看| 久久国产精品一区二区| 亚洲国产美女高潮久久久| 麻豆国产原创视频在线播放| 亚洲AV永久天堂在线观看| 国产免费一区二区三区在线观看| 狠狠色狠狠色综合网| 国产精品成人免费视频网站京东| 国产欧美日本亚洲精品一4区| 国产午夜精品视频在线观看| 国产精品成人免费视频一区 | 国产精品国产三级国产专播| 无码人妻精品一区二区三区蜜桃| 大香伊蕉国产av| 亚洲一区精品中文字幕| 国产极品大奶在线视频| 亚洲精品国产suv一区88| 成人区视频| 日韩视频午夜在线观看| 久久久噜噜噜久久中文福利 | 精品一区二区三区四区少妇| 亚洲精品中文字幕91| 久久99热狠狠色精品一区| 青草热久精品视频在线观看| 麻豆视频在线观看免费在线观看|