激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

香港云服务器
服務(wù)器之家 - 編程語言 - Java教程 - 面試總結(jié):秒殺設(shè)計、AQS 、synchronized相關(guān)問題

面試總結(jié):秒殺設(shè)計、AQS 、synchronized相關(guān)問題

2021-09-16 12:29興趣使然的草帽路飛 Java教程

Java語言的關(guān)鍵字,當(dāng)它用來修飾一個方法或者一個代碼塊的時候,能夠保證在同一時刻最多只有一個線程執(zhí)行該段代碼。本文給大家介紹java中 synchronized的用法,對本文感興趣的朋友一起看看吧

1、面試官:如何設(shè)計一個秒殺系統(tǒng)?請你闡述流程?

這一面試題答案參考自三太子敖丙的文章:阿里面試官問我:如何設(shè)計秒殺系統(tǒng)?我給出接近滿分的回答

秒殺系統(tǒng)要解決的幾個問題?

① 高并發(fā)

秒殺的特點是時間極短、 瞬間用戶量大。在秒殺活動持續(xù)時間內(nèi),Redis 服務(wù)器需要承受大量的用戶請求,在大量請求條件下,緩存雪崩,緩存擊穿,緩存穿透這些問題都是有可能發(fā)生的。

一旦緩存失效,或者緩存無效,每秒上萬甚至十幾萬的QPS(每秒請求數(shù))直接打到數(shù)據(jù)庫,基本上都要把庫打掛掉,而且你的服務(wù)不單單是做秒殺的還涉及其他的業(yè)務(wù),你沒做降級、限流、熔斷啥的,別的一起掛,小公司的話可能全站崩潰404。

為此,在設(shè)計秒殺系統(tǒng)時,首先要考慮并發(fā)安全和用戶訪問效率,二者缺一不可!

② 超賣

但凡設(shè)計到商品購買,秒殺購物問題,最需要注意的就是超賣問題,因為一旦由于程序不安全,導(dǎo)致超賣問題產(chǎn)生,不光需要賠付商家損失,還需要追究秒殺系統(tǒng)的開發(fā)者的責(zé)任!

③ 惡意請求

在秒殺購物時,商品價格比較低,價值較高的商品可能會被一些惡意的第三方,開多臺機器執(zhí)行搶購腳本,機器搶購肯定要比我們?nèi)耸謩狱c擊要快,所以,在設(shè)計秒殺系統(tǒng)時,要防止 不良程序員 的惡意搶購。

④ 鏈接暴露

假如設(shè)置定時秒殺開啟,在未到秒殺開啟時間之前,下單購買按鈕應(yīng)該是禁用的(不可點擊),但是,如果我們請求下單的鏈接沒有經(jīng)過網(wǎng)關(guān)加密封裝,而是直接以原鏈接的方式依附于下單購買按鈕,那么 F12 時,就可以獲取下單購買鏈接 URL,然后直接去請求下單鏈接,跳過點擊方式直接購買商品!

如何解決上面遇到的幾個問題?

① 秒殺模塊微服務(wù)化

對于秒殺搶購系統(tǒng),將其設(shè)計成單獨一個模塊,單獨部署一臺或者多太服務(wù)器,這樣可以避免服務(wù)崩潰時,公司其他項目可以正常運行不受影響。

與此同時,要單獨給秒殺系統(tǒng)建立一個數(shù)據(jù)庫,現(xiàn)在的互聯(lián)網(wǎng)架構(gòu)部署都是分庫的,一樣的就是訂單服務(wù)對應(yīng)訂單庫,秒殺我們也給他建立自己的秒殺數(shù)據(jù)庫,防止服務(wù)崩潰對其他數(shù)據(jù)庫造成影響。

② 秒殺鏈接加鹽

URL動態(tài)化,通過 MD5 之類的加密算法加密隨機的字符串去做 URL,然后通過前端代碼獲取 URL 后臺校驗后才能通過。

③ Redis集群

如果在大請求量下,單機的Redis頂不住,那就多找?guī)讉€兄弟,秒殺本來就是讀多寫少,通過 Redis 集群,主從同步、讀寫分離,再加上 哨兵、開啟 持久化,來保證 Redis 服務(wù)高可用!

面試總結(jié):秒殺設(shè)計、AQS 、synchronized相關(guān)問題

④ 通過 Nginx 做負載均衡

Nginx高性能的web服務(wù)器,并發(fā)隨便頂幾萬不是夢,但是我們的 Tomcat 只能頂幾百的并發(fā),我們可以通過Nginx 負載均衡,平分大并發(fā)量的請求給多臺服務(wù)器的 Tomcat,在秒殺開啟的時候可以多租點流量機

面試總結(jié):秒殺設(shè)計、AQS 、synchronized相關(guān)問題

⑤ 秒殺頁面資源靜態(tài)化

秒殺一般都是特定的商品還有頁面模板,現(xiàn)在一般都是前后端分離的,所以頁面一般都是不會經(jīng)過后端的,但是前端也要自己的服務(wù)器啊,那就把能提前放入**cdn服務(wù)器 **的東西都放進去,反正把所有能提升效率的步驟都做一下,減少真正秒殺時候服務(wù)器的壓力。

⑥ 下單按鈕控制

在沒到秒殺開始時間之前,一般下單按鈕都是置灰的,只有時間到了,才能點擊。這是因為怕大家在時間快到的最后幾秒秒瘋狂請求服務(wù)器,然后還沒到秒殺的時候基本上服務(wù)器就掛了。

這個時候就需要前端的配合,定時去請求你的后端服務(wù)器,獲取最新的北京時間,到時間點再給按鈕可用狀態(tài)。按鈕可以點擊之后也得給他置灰?guī)酌耄蝗凰粯釉陂_始之后一直點的。

⑦ 前后端限流

限流可以分為 前端限流后端限流。

前端限流:這個很簡單,一般秒殺搶購,下單按鈕不會讓你一直點的,一般都是點擊一下或者兩下然后幾秒之后才可以繼續(xù)點擊,這也是保護服務(wù)器的一種手段。

后端限流:秒殺的時候肯定是涉及到后續(xù)的訂單生成和支付等操作,但是都只是成功的幸運兒才會走到那一步,那一旦 100 個產(chǎn)品賣光了,return 了一個 false,前端直接秒殺結(jié)束,然后你后端也關(guān)閉后續(xù)無效請求的介入了。

⑧ 庫存預(yù)熱

秒殺的本質(zhì)就是對庫存的搶奪。如果每個秒殺下單的用戶請求過來,都去數(shù)據(jù)庫查詢庫存校驗庫存,然后扣減庫存,這樣不光效率低下,而且數(shù)據(jù)庫壓力也是巨大的!

既然數(shù)據(jù)庫頂不住,但是他的兄弟非關(guān)系型的數(shù)據(jù)庫 Redis 能頂啊!

超賣問題:

我們要在開始秒殺之前,通過定時任務(wù)提前把商品的庫存加載到 Redis 中去,讓整個庫存校驗流程都在 Redis 里面去做,然后等到秒殺活動結(jié)束了,再異步的去修改數(shù)據(jù)庫中庫存就好了。

但是用了 Redis 就有一個問題了,我們上面說了我們采用 主從 Redis,就是我們會先去讀取庫存,再判斷庫存,當(dāng)有庫存時才會去減庫存,正常情況沒問題,但是高并發(fā)的情況問題就很大了。

就比如現(xiàn)在庫存只剩下 1 個了,我們高并發(fā)嘛,4 個服務(wù)器一起查詢了發(fā)現(xiàn)都是還有 1 個,那大家都覺得是自己搶到了,就都去扣庫存,那結(jié)果就變成了 -3,這種情況下,只有一個請求是真的搶到商品了,其他 3 個都是超賣的。

如何解決?

可以通過使用 Lua 腳本來解決超賣問題。

**Lua 腳本是類似Redis事務(wù),有一定的原子性,不會被其他命令插隊,可以完成一些 Redis 事務(wù)性的操作。**這點是關(guān)鍵!

把判斷庫存、扣減庫存的操作都寫在一個 Lua 腳本中,并將該腳本交給 Redis 去執(zhí)行,當(dāng) Redis 中庫存數(shù)量減到 0 之后,后面扣庫存的請求都直接 return false

⑨ 限流&降級&熔斷&隔離

不怕一萬就怕萬一,萬一秒殺系統(tǒng)真的頂不住了,限流,頂不住就擋一部分出去。但是不能說不行,降級,降級了還是被打掛了,熔斷,至少不要影響別的系統(tǒng),隔離,你本身就獨立的,但是你會調(diào)用其他的系統(tǒng)嘛,你快不行了你別拖累兄弟們啊。

2、面試官:AQS源碼有了解過嗎?請你說一下加鎖和釋放鎖的流程

這一面試題答案參考自三太子敖丙的文章:我畫了35張圖就是為了讓你深入 AQS

① AQS紹

AQS中 維護 基本介了一個volatile int state(代表共享資源)和一個 FIFO 線程等待隊列(多線程爭用資源被阻塞時會進入此隊列)。

這里volatile能夠保證多線程下的可見性,當(dāng)state = 1則代表當(dāng)前對象鎖已經(jīng)被占有,其他線程來加鎖時則會失敗,加鎖失敗的線程會被放入一個 FIFO的等待隊列中,并會被 UNSAFE.park() 操作掛起,等待其他獲取鎖的線程釋放鎖才能夠被喚醒。

另外state的操作都是通過CAS來保證其并發(fā)修改的安全性。

如圖所示:

面試總結(jié):秒殺設(shè)計、AQS 、synchronized相關(guān)問題

AQS 中提供了很多關(guān)于鎖的實現(xiàn)方法:

getState():獲取鎖的標(biāo)志 state 值。

setState():設(shè)置鎖的標(biāo)志 state 值。

tryAcquire(int):獨占方式獲取鎖。嘗試獲取資源,成功則返回 true,失敗則返回 false。

tryRelease(int):獨占方式釋放鎖。嘗試釋放資源,成功則返回 true,失敗則返回 false。

② 加鎖與競爭鎖使用場景分析

如果同時有三個線程并發(fā)搶占鎖,此時線程一搶占鎖成功,線程二和線程三搶占鎖失敗,具體執(zhí)行流程如下:

面試總結(jié):秒殺設(shè)計、AQS 、synchronized相關(guān)問題

此時AQS內(nèi)部數(shù)據(jù)為:

面試總結(jié):秒殺設(shè)計、AQS 、synchronized相關(guān)問題

具體看下?lián)屨兼i代碼實現(xiàn):java.util.concurrent.locks.ReentrantLock .NonfairSync

  1. static final class NonfairSync extends Sync {
  2. // 加鎖
  3. final void lock() {
  4. // CAS 修改 state 的值為 1
  5. if (compareAndSetState(0, 1))
  6. setExclusiveOwnerThread(Thread.currentThread());
  7. else
  8. acquire(1);
  9. }
  10. // 嘗試競爭資源
  11. protected final boolean tryAcquire(int acquires) {
  12. return nonfairTryAcquire(acquires);
  13. }
  14. }

這里使用的 ReentrantLock 非公平鎖,線程進來直接利用CAS嘗試搶占鎖,如果搶占成功state值回被改為 1,且設(shè)置獨占鎖線程對象為當(dāng)前線程。

  1. // CAS 嘗試搶占鎖
  2. protected final boolean compareAndSetState(int expect, int update) {
  3. return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
  4. }
  5. // 設(shè)置獨占鎖線程對象為當(dāng)前線程
  6. protected final void setExclusiveOwnerThread(Thread thread) {
  7. exclusiveOwnerThread = thread;
  8. }

線程一搶占鎖成功后,state變?yōu)?1,線程二通過CAS修改state變量必然會失敗。此時AQSFIFO(First In First Out 先進先出)隊列中。

  1. public final void acquire(int arg) {
  2. if (!tryAcquire(arg) &&
  3. acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
  4. selfInterrupt();
  5. }

tryAcquire() 方法的具體實現(xiàn)是通過內(nèi)部調(diào)用nonfairTryAcquire()方法,這個方法執(zhí)行的邏輯如下:

首先會獲取state的值,如果不為0則說明當(dāng)前對象的鎖已經(jīng)被其他線程所占有。

接著判斷占有鎖的線程是否為當(dāng)前線程,如果是則累加state值,這就是可重入鎖的具體實現(xiàn),累加state值,釋放鎖的時候也要依次遞減state值。

如果state為 0,則執(zhí)行CAS操作,嘗試更新state值為 1,如果更新成功則代表當(dāng)前線程加鎖成功。

③ 釋放鎖使用場景分析

釋放鎖的過程,首先是線程一釋放鎖,釋放鎖后會喚醒head節(jié)點的后置節(jié)點,也就是我們現(xiàn)在的線程二,具體操作流程如下:

面試總結(jié):秒殺設(shè)計、AQS 、synchronized相關(guān)問題

執(zhí)行完后等待隊列數(shù)據(jù)如下:

面試總結(jié):秒殺設(shè)計、AQS 、synchronized相關(guān)問題

此時線程二已經(jīng)被喚醒,繼續(xù)嘗試獲取鎖,如果獲取鎖失敗,則會繼續(xù)被掛起。

線程釋放鎖的代碼:

java.util.concurrent.locks.AbstractQueuedSynchronizer.release():

  1. public final boolean release(int arg) {
  2. if (tryRelease(arg)) {
  3. Node h = head;
  4. if (h != null && h.waitStatus != 0)
  5. unparkSuccessor(h);
  6. return true;
  7. }
  8. return false;
  9. }

這里首先會執(zhí)行tryRelease()方法,這個方法具體實現(xiàn)在ReentrantLock中,如果tryRelease()執(zhí)行成功,則繼續(xù)判斷 head 節(jié)點的 waitStatus 是否為 0,前面我們已經(jīng)看到過,headwaitStatue為SIGNAL(-1),這里就會執(zhí)行 unparkSuccessor() 方法來喚醒 head 的后置節(jié)點,也就是上面圖中線程二對應(yīng)的Node節(jié)點。

ReentrantLock.tryRelease():

  1. protected final boolean tryRelease(int releases) {
  2. int c = getState() - releases;
  3. if (Thread.currentThread() != getExclusiveOwnerThread())
  4. throw new IllegalMonitorStateException();
  5. boolean free = false;
  6. if (c == 0) {
  7. free = true;
  8. setExclusiveOwnerThread(null);
  9. }
  10. setState(c);
  11. return free;
  12. }

執(zhí)行完ReentrantLock.tryRelease()后,state被設(shè)置成 0,Lock 對象的獨占鎖被設(shè)置為 null。

接著執(zhí)行java.util.concurrent.locks.AbstractQueuedSynchronizer.unparkSuccessor()方法,喚醒head的后置節(jié)點:

  1. private void unparkSuccessor(Node node) {
  2. int ws = node.waitStatus;
  3. if (ws < 0)
  4. compareAndSetWaitStatus(node, ws, 0);
  5. Node s = node.next;
  6. if (s == null || s.waitStatus > 0) {
  7. s = null;
  8. for (Node t = tail; t != null && t != node; t = t.prev)
  9. if (t.waitStatus <= 0)
  10. s = t;
  11. }
  12. if (s != null)
  13. LockSupport.unpark(s.thread);
  14. }

這里主要是將head節(jié)點的waitStatus設(shè)置為 0,然后解除head節(jié)點next的指向,使head節(jié)點空置,等待著被垃圾回收。

此時重新將head指針指向線程二對應(yīng)的Node節(jié)點,且使用LockSupport.unpark方法來喚醒線程二

被喚醒的線程二會接著嘗試獲取鎖,用CAS指令修改state數(shù)據(jù)。

3、面試官:請你談一談synchronized的實現(xiàn)原理

這一面試題答案參考文章:死磕 java同步系列之synchronized解析

synchronized 加鎖解鎖原理分析

sychronized 鎖,在Java內(nèi)存模型層面,涉及到 2 個指令(JMM 定義了8 個操作來完成主內(nèi)存工作內(nèi)存的交互操作,參考文章:搜集了這么多資料,不信你還理解不了 JMM 內(nèi)存模型、volatile 關(guān)鍵字保證有序性和可見性實現(xiàn)原理!),lockunlock

  • lock,鎖定,作用于主內(nèi)存的變量,它把主內(nèi)存中的變量標(biāo)識為線程獨占狀態(tài)。
  • unlock,解鎖,作用于主內(nèi)存的變量,它把鎖定的變量釋放出來,釋放出來的變量才可以被其它線程鎖定。

這兩個指令并沒有直接提供給用戶使用,而是提供了兩個更高層次的指令 monitorenter monitorexit 來隱式地使用 lock unlock 指令。而 synchronized 就是使用 monitorenter monitorexit 這兩個指令來實現(xiàn)的。

根據(jù)JVM規(guī)范的要求,在執(zhí)行 monitorenter 指令的時候,首先要去嘗試獲取對象的鎖,如果這個對象沒有被鎖定,或者當(dāng)前線程已經(jīng)擁有了這個對象的鎖,就把鎖的計數(shù)器加1,相應(yīng)地,在執(zhí)行 monitorexit 的時候會把計數(shù)器減 1,當(dāng)計數(shù)器減小為 0 時,鎖就釋放了。

sychronized 鎖是如何保證,原子性、可見性、和一致性呢?

還是回到Java內(nèi)存模型上來,synchronized關(guān)鍵字底層是通過 monitorenter monitorexit 實現(xiàn)的,而這兩個指令又是通過 lockunlock 來實現(xiàn)的。

lock unlock 在Java內(nèi)存模型中是必須滿足下面四條規(guī)則的:

  • ① 一個變量同一時刻只允許一條線程對其進行 lock 操作,但 lock 操作可以被同一個線程執(zhí)行多次,多次執(zhí)行 lock 后,只有執(zhí)行相同次數(shù)的 unlock 操作,變量才能被解鎖。
  • ② 如果對一個變量執(zhí)行 lock 操作,將會清空工作內(nèi)存中此變量的值,在執(zhí)行引擎使用這個變量前,需要重新執(zhí)行 load assign 操作初始化變量的值;
  • ③ 如果一個變量沒有被 lock 操作鎖定,則不允許對其執(zhí)行 unlock 操作,也不允許 unlock 一個其它線程鎖定的變量;
  • ④ 對一個變量執(zhí)行 unlock 操作之前,必須先把此變量同步回主內(nèi)存中,即執(zhí)行 storewrite 操作;

通過規(guī)則 ①,我們知道對于 lock unlock 之間的代碼,同一時刻只允許一個線程訪問,所以,synchronized 是具有原子性的。

通過規(guī)則 ① ② 和 ④,我們知道每次 lockunlock 時都會從主內(nèi)存加載變量或把變量刷新回主內(nèi)存,而 lock 和 unlock 之間的變量(這里是指鎖定的變量)是不會被其它線程修改的,所以,synchronized 是具有可見性的。

通過規(guī)則 ① 和 ③ ,我們知道所有對變量的加鎖都要排隊進行,且其它線程不允許解鎖當(dāng)前線程鎖定的對象,所以,synchronized 是具有有序性的。

綜上所述,synchronized 是可以保證原子性、可見性和有序性的。

synchronized 鎖優(yōu)化

Java在不斷進化,同樣地,Java 中像 synchronized 這種關(guān)鍵字也在不斷優(yōu)化,synchronized 有如下三種狀態(tài):

  • 偏向鎖,是指一段同步代碼一直被一個線程訪問,那么這個線程會自動獲取鎖,降低獲取鎖的代價。
  • 輕量級鎖,是指當(dāng)鎖是偏向鎖時,被另一個線程所訪問,偏向鎖會升級為輕量級鎖,這個線程會通過自旋的方式嘗試獲取鎖,不會阻塞,提高性能。
  • 重量級鎖,是指當(dāng)鎖是輕量級鎖時,當(dāng)自旋的線程自旋了一定的次數(shù)后,還沒有獲取到鎖,就會進入阻塞狀態(tài),該鎖升級為重量級鎖,重量級鎖會使其他線程阻塞,性能降低。

總結(jié)

(1)synchronized 在編譯時會在同步塊前后生成 monitorenter monitorexit 字節(jié)碼指令;

(2)monitorentermonitorexit 字節(jié)碼指令需要一個引用類型的參數(shù),基本類型不可以哦;

(3)monitorentermonitorexit 字節(jié)碼指令更底層是使用Java內(nèi)存模型的 lock 和 unlock 指令;

(4)synchronized 是可重入鎖;

(5)synchronized 是非公平鎖;

(6)synchronized 可以同時保證原子性、可見性、有序性;

(7)synchronized 有三種狀態(tài):偏向鎖、輕量級鎖、重量級鎖;

本篇文章就到這里了,希望能給你帶來幫助,也希望你能夠多多關(guān)注我們的更多內(nèi)容!

原文鏈接:https://csp1999.blog.csdn.net/article/details/118116777

延伸 · 閱讀

精彩推薦
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經(jīng)有好久沒有升過級了。升級完畢重啟之后,突然發(fā)現(xiàn)好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程Java實現(xiàn)搶紅包功能

    Java實現(xiàn)搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現(xiàn)搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關(guān)于小米推送Java代碼,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩(wěn)中求8032021-07-12
  • Java教程Java BufferWriter寫文件寫不進去或缺失數(shù)據(jù)的解決

    Java BufferWriter寫文件寫不進去或缺失數(shù)據(jù)的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數(shù)據(jù)的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發(fā)現(xiàn)了對于集合操作轉(zhuǎn)換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關(guān)于Java8中S...

    阿杜7472021-02-04
  • Java教程xml與Java對象的轉(zhuǎn)換詳解

    xml與Java對象的轉(zhuǎn)換詳解

    這篇文章主要介紹了xml與Java對象的轉(zhuǎn)換詳解的相關(guān)資料,需要的朋友可以參考下...

    Java教程網(wǎng)2942020-09-17
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發(fā)項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
946
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25
主站蜘蛛池模板: 成人毛片100部免费观看 | 欧美aaa| 久久免费视屏 | 免费在线观看成人av | 国产精品成人久久 | 国产欧美精品一区二区三区四区 | 国产精品爱久久久久久久 | 日韩在线观看中文字幕 | 精品一区二区三区中文字幕老牛 | 国产精品刺激对白麻豆99 | 久草视频福利在线观看 | 国产高潮国产高潮久久久91 | 黄色网址在线免费播放 | 91精品国产一区二区三区四区在线 | 久久久久国产成人精品亚洲午夜 | 91久久99热青草国产 | 日韩男女在线 | 成人三级电影网站 | av免费在线观看国产 | 国产精品久久久久久久娇妻 | 本站只有精品 | 欧美一区二区三区中文字幕 | 综合精品一区 | 久久96国产精品久久秘臀 | 国产又白又嫩又紧又爽18p | 国产亚洲美女精品久久久2020 | 国产女做a爱免费视频 | 成人爽a毛片免费啪啪红桃视频 | 国产一区二区视频网站 | 日日狠狠久久偷偷四色综合免费 | 日韩电影网站 | 1000部精品久久久久久久久 | 露脸各种姿势啪啪的清纯美女 | 久久成人综合网 | 国产精品久久久久久久亚洲按摩 | 国产电影精品久久 | 欧美另类综合 | 成年免费观看视频 | 亚洲导航深夜福利涩涩屋 | 国产成人高清成人av片在线看 | 懂色av懂色aⅴ精彩av |