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

搞懂“分布式鎖”,看這篇文章就對了

開發 后端 開發工具 分布式
對于鎖大家肯定不會陌生,在 Java 中 synchronized 關鍵字和 ReentrantLock 可重入鎖在我們的代碼中是經常見的,一般我們用其在多線程環境中控制對資源的并發訪問。

但是隨著分布式的快速發展,本地的加鎖往往不能滿足我們的需要,在我們的分布式環境中上面加鎖的方法就會失去作用。

于是人們為了在分布式環境中也能實現本地鎖的效果,也是紛紛各出其招,今天讓我們來聊一聊一般分布式鎖實現的套路。

為何需要分布式鎖

Martin Kleppmann 是英國劍橋大學的分布式系統的研究員,之前和 Redis 之父 Antirez 進行過關于 RedLock(紅鎖,后續有講到)是否安全的激烈討論。

Martin 認為一般我們使用分布式鎖有兩個場景:

  • 效率:使用分布式鎖可以避免不同節點重復相同的工作,這些工作會浪費資源。比如用戶付了錢之后有可能不同節點會發出多封短信。
  • 正確性:加分布式鎖同樣可以避免破壞正確性的發生,如果兩個節點在同一條數據上面操作,比如多個節點機器對同一個訂單操作不同的流程有可能會導致該筆訂單最后狀態出現錯誤,造成損失。

分布式鎖的一些特點

當我們確定了在不同節點上需要分布式鎖,那么我們需要了解分布式鎖到底應該有哪些特點?

分布式鎖的特點如下:

  • 互斥性:和我們本地鎖一樣互斥性是最基本,但是分布式鎖需要保證在不同節點的不同線程的互斥。
  • 可重入性:同一個節點上的同一個線程如果獲取了鎖之后那么也可以再次獲取這個鎖。
  • 鎖超時:和本地鎖一樣支持鎖超時,防止死鎖。
  • 高效,高可用:加鎖和解鎖需要高效,同時也需要保證高可用防止分布式鎖失效,可以增加降級。
  • 支持阻塞和非阻塞:和 ReentrantLock 一樣支持 lock 和 trylock 以及 tryLock(long timeOut)。
  • 支持公平鎖和非公平鎖(可選):公平鎖的意思是按照請求加鎖的順序獲得鎖,非公平鎖就相反是無序的。這個一般來說實現的比較少。

常見的分布式鎖

我們了解了一些特點之后,我們一般實現分布式鎖有以下幾個方式:

  • MySQL
  • ZK
  • Redis
  • 自研分布式鎖:如谷歌的 Chubby。

下面分開介紹一下這些分布式鎖的實現原理。

MySQL

首先來說一下 MySQL 分布式鎖的實現原理,相對來說這個比較容易理解,畢竟數據庫和我們開發人員在平時的開發中息息相關。

對于分布式鎖我們可以創建一個鎖表:

 

前面我們所說的 lock(),trylock(long timeout),trylock() 這幾個方法可以用下面的偽代碼實現。

lock()

lock 一般是阻塞式的獲取鎖,意思就是不獲取到鎖誓不罷休,那么我們可以寫一個死循環來執行其操作:

 

mysqlLock.lcok 內部是一個 sql,為了達到可重入鎖的效果,我們應該先進行查詢,如果有值,需要比較 node_info 是否一致。

這里的 node_info 可以用機器 IP 和線程名字來表示,如果一致就加可重入鎖 count 的值,如果不一致就返回 false。如果沒有值就直接插入一條數據。

偽代碼如下:

 

需要注意的是這一段代碼需要加事務,必須要保證這一系列操作的原子性。

tryLock() 和 tryLock(long timeout)

tryLock() 是非阻塞獲取鎖,如果獲取不到就會馬上返回,代碼如下:

 

tryLock(long timeout) 實現如下:

 

mysqlLock.lock 和上面一樣,但是要注意的是 select … for update 這個是阻塞的獲取行鎖,如果同一個資源并發量較大還是有可能會退化成阻塞的獲取鎖。

unlock()

unlock 的話如果這里的 count 為 1 那么可以刪除,如果大于 1 那么需要減去 1。

 

鎖超時

我們有可能會遇到我們的機器節點掛了,那么這個鎖就不會得到釋放,我們可以啟動一個定時任務,通過計算一般我們處理任務的時間。

比如是 5ms,那么我們可以稍微擴大一點,當這個鎖超過 20ms 沒有被釋放我們就可以認定是節點掛了然后將其直接釋放。

MySQL 小結:

  • 適用場景:MySQL 分布式鎖一般適用于資源不存在數據庫,如果數據庫存在比如訂單,可以直接對這條數據加行鎖,不需要我們上面多的繁瑣的步驟。

比如一個訂單,我們可以用 select * from order_table where id = 'xxx' for update 進行加行鎖,那么其他的事務就不能對其進行修改。

  • 優點:理解起來簡單,不需要維護額外的第三方中間件(比如 Redis,ZK)。
  • 缺點:雖然容易理解但是實現起來較為繁瑣,需要自己考慮鎖超時,加事務等等。性能局限于數據庫,一般對比緩存來說性能較低。對于高并發的場景并不是很適合。

樂觀鎖

前面我們介紹的都是悲觀鎖,這里想額外提一下樂觀鎖,在我們實際項目中也是經常實現樂觀鎖,因為我們加行鎖的性能消耗比較大,通常我們對于一些競爭不是那么激烈。

但是其又需要保證我們并發的順序執行使用樂觀鎖進行處理,我們可以對我們的表加一個版本號字段。

那么我們查詢出來一個版本號之后,update 或者 delete 的時候需要依賴我們查詢出來的版本號,判斷當前數據庫和查詢出來的版本號是否相等,如果相等那么就可以執行,如果不等那么就不能執行。

這樣的一個策略很像我們的 CAS(Compare And Swap),比較并交換是一個原子操作。這樣我們就能避免加 select * for update 行鎖的開銷。

ZooKeeper

ZooKeeper 也是我們常見的實現分布式鎖方法,相比于數據庫如果沒了解過 ZooKeeper 可能上手比較難一些。

ZooKeeper 是以 Paxos 算法為基礎的分布式應用程序協調服務。ZK 的數據節點和文件目錄類似,所以我們可以用此特性實現分布式鎖。

我們以某個資源為目錄,然后這個目錄下面的節點就是我們需要獲取鎖的客戶端,未獲取到鎖的客戶端注冊需要注冊 Watcher 到上一個客戶端,可以用下圖表示:

 

/lock 是我們用于加鎖的目錄,/resource_name 是我們鎖定的資源,其下面的節點按照我們加鎖的順序排列。

Curator

Curator 封裝了 ZooKeeper 底層的 API,使我們更加容易方便的對 ZooKeeper 進行操作,并且它封裝了分布式鎖的功能,這樣我們就不需要在自己實現了。

Curator 實現了可重入鎖(InterProcessMutex),也實現了不可重入鎖(InterProcessSemaphoreMutex)。在可重入鎖中還實現了讀寫鎖。

InterProcessMutex

InterProcessMutex 是 Curator 實現的可重入鎖,我們可以通過下面的一段代碼實現我們的可重入鎖:

 

我們利用 acuire 進行加鎖,release 進行解鎖。

加鎖的流程具體如下:

  • 首先進行可重入的判定:這里的可重入鎖記錄在 ConcurrentMap

如果 threadData.get(currentThread)是有值的那么就證明是可重入鎖,然后記錄就會加 1。

我們之前的 MySQL 其實也可以通過這種方法去優化,可以不需要 count 字段的值,將這個維護在本地可以提高性能。

  • 然后在我們的資源目錄下創建一個節點:比如這里創建一個 /0000000002 這個節點,這個節點需要設置為 EPHEMERAL_SEQUENTIAL 也就是臨時節點并且有序。
  • 獲取當前目錄下所有子節點,判斷自己的節點是否位于子節點第一個。
  • 如果是第一個,則獲取到鎖,那么可以返回。
  • 如果不是第一個,則證明前面已經有人獲取到鎖了,那么需要獲取自己節點的前一個節點。

/0000000002 的前一個節點是 /0000000001,我們獲取到這個節點之后,再上面注冊 Watcher(這里的 Watcher 其實調用的是 object.notifyAll(),用來解除阻塞)。

  • object.wait(timeout) 或 object.wait():進行阻塞等待,這里和我們第 5 步的 Watcher 相對應。

解鎖的具體流程:

  • 首先進行可重入鎖的判定:如果有可重入鎖只需要次數減 1 即可,減 1 之后加鎖次數為 0 的話繼續下面步驟,不為 0 直接返回。
  • 刪除當前節點。
  • 刪除 threadDataMap 里面的可重入鎖的數據。

讀寫鎖

Curator 提供了讀寫鎖,其實現類是 InterProcessReadWriteLock,這里的每個節點都會加上前綴:

  1. private static final String READ_LOCK_NAME  = "__READ__"
  2. private static final String WRITE_LOCK_NAME = "__WRIT__"

根據不同的前綴區分是讀鎖還是寫鎖,對于讀鎖,如果發現前面有寫鎖,那么需要將 Watcher 注冊到和自己最近的寫鎖。寫鎖的邏輯和我們之前 4.2 分析的依然保持不變。

鎖超時

ZooKeeper 不需要配置鎖超時,由于我們設置節點是臨時節點,我們的每個機器維護著一個 ZK 的 Session,通過這個 Session,ZK 可以判斷機器是否宕機。

如果我們的機器掛掉的話,那么這個臨時節點對應的就會被刪除,所以我們不需要關心鎖超時。

ZK 小結:

  • 優點:ZK 可以不需要關心鎖超時時間,實現起來有現成的第三方包,比較方便,并且支持讀寫鎖,ZK 獲取鎖會按照加鎖的順序,所以其是公平鎖。對于高可用利用 ZK 集群進行保證。
  • 缺點:ZK 需要額外維護,增加維護成本,性能和 MySQL 相差不大,依然比較差。并且需要開發人員了解 ZK 是什么。

Redis

大家在網上搜索分布式鎖,恐怕最多的實現就是 Redis 了,Redis 因為其性能好,實現起來簡單所以讓很多人都對其十分青睞。

Redis 分布式鎖簡單實現

熟悉 Redis 的同學那么肯定對 setNx(set if not exist) 方法不陌生,如果不存在則更新,其可以很好的用來實現我們的分布式鎖。

對于某個資源加鎖我們只需要:

  1. setNx resourceName value 

這里有個問題,加鎖了之后如果機器宕機那么這個鎖就不會得到釋放所以會加入過期時間,加入過期時間需要和 setNx 同一個原子操作。

在 Redis 2.8 之前我們需要使用 Lua 腳本達到我們的目的,但是 Redis 2.8 之后 Redis 支持 nx 和 ex 操作是同一原子操作。

  1. set resourceName value ex 5 nx 

Redission

Javaer 都知道 Jedis,Jedis 是 Redis 的 Java 實現的客戶端,其 API 提供了比較全面的 Redis 命令的支持。

Redission 也是 Redis 的客戶端,相比于 Jedis 功能簡單。Jedis 簡單使用阻塞的 I/O 和 Redis 交互,Redission 通過 Netty 支持非阻塞 I/O。

Jedis 最新版本 2.9.0 是 2016 年的快 3 年了沒有更新,而 Redission 最新版本是 2018 年 10 月更新。

Redission 封裝了鎖的實現,其繼承了 java.util.concurrent.locks.Lock 的接口,讓我們像操作我們的本地 Lock 一樣去操作 Redission 的 Lock。

下面介紹一下其如何實現分布式鎖:

 

 

 

Redission 不僅提供了 Java 自帶的一些方法(lock,tryLock),還提供了異步加鎖,對于異步編程更加方便。

由于內部源碼較多,就不貼源碼了,這里用文字敘述來分析它是如何加鎖的,這里分析一下 tryLock 方法:

①嘗試加鎖:首先會嘗試進行加鎖,由于需要兼容老版本的 Redis,所以不能直接使用 ex,nx 原子操作的 API,那么就只能使用 Lua 腳本,相關的 Lua 腳本如下:

 

可以看見它并沒有使用我們的 sexNx 來進行操作,而是使用的 hash 結構,我們的每一個需要鎖定的資源都可以看做是一個 HashMap,鎖定資源的節點信息是 Key,鎖定次數是 Value。

通過這種方式可以很好的實現可重入的效果,只需要對 Value 進行加 1 操作,就能進行可重入鎖。當然這里也可以用之前我們說的本地計數進行優化。

②如果嘗試加鎖失敗,判斷是否超時,如果超時則返回 false。

③如果加鎖失敗之后,沒有超時,那么需要在名字為 redisson_lock__channel+lockName 的 channel 上進行訂閱,用于訂閱解鎖消息,然后一直阻塞直到超時,或者有解鎖消息。

④重試步驟 1,2,3,直到最后獲取到鎖,或者某一步獲取鎖超時。

對于我們的 unlock 方法比較簡單也是通過 lua 腳本進行解鎖,如果是可重入鎖,只是減 1。如果是非加鎖線程解鎖,那么解鎖失敗。

 

Redission 還有公平鎖的實現,對于公平鎖其利用了 list 結構和 hashset 結構分別用來保存我們排隊的節點,和我們節點的過期時間,用這兩個數據結構幫助我們實現公平鎖,這里就不展開介紹了,有興趣可以參考源碼。

RedLock

我們想象一個這樣的場景當機器 A 申請到一把鎖之后,如果 Redis 主宕機了,這個時候從機并沒有同步到這一把鎖,那么機器 B 再次申請的時候就會再次申請到這把鎖。

為了解決這個問題 Redis 作者提出了 RedLock 紅鎖的算法,在 Redission 中也對 RedLock 進行了實現。

 

通過上面的代碼,我們需要實現多個 Redis 集群,然后進行紅鎖的加鎖,解鎖。

具體的步驟如下:

①首先生成多個 Redis 集群的 Rlock,并將其構造成 RedLock。

②依次循環對三個集群進行加鎖,加鎖的過程和 5.2 里面一致。

③如果循環加鎖的過程中加鎖失敗,那么需要判斷加鎖失敗的次數是否超出了最大值,這里的最大值是根據集群的個數,比如三個那么只允許失敗一個,五個的話只允許失敗兩個,要保證多數成功。

④加鎖的過程中需要判斷是否加鎖超時,有可能我們設置加鎖只能用 3ms,第一個集群加鎖已經消耗了 3ms 了。那么也算加鎖失敗。

⑤3,4 步里面加鎖失敗的話,那么就會進行解鎖操作,解鎖會對所有的集群在請求一次解鎖。

可以看見 RedLock 基本原理是利用多個 Redis 集群,用多數的集群加鎖成功,減少 Redis 某個集群出故障,造成分布式鎖出現問題的概率。

Redis 小結:

  • 優點:對于 Redis 實現簡單,性能對比 ZK 和 MySQL 較好。如果不需要特別復雜的要求,自己就可以利用 setNx 進行實現,如果自己需要復雜的需求的話,可以利用或者借鑒 Redission。對于一些要求比較嚴格的場景可以使用 RedLock。
  • 缺點:需要維護 Redis 集群,如果要實現 RedLock 需要維護更多的集群。

分布式鎖的安全問題

上面我們介紹過紅鎖,但是 Martin Kleppmann 認為其依然不安全。

有關于 Martin 反駁的幾點,我認為其實不僅僅局限于 RedLock,前面說的算法基本都有這個問題,下面我們來討論一下這些問題。

長時間的 GC pause

熟悉 Java 的同學肯定對 GC 不陌生,在 GC 的時候會發生 STW(stop-the-world)。

例如 CMS 垃圾回收器,它會有兩個階段進行 STW 防止引用繼續進行變化。那么有可能會出現下面圖(引用至 Martin 反駁 Redlock 的文章)中這個情況:

 

client1 獲取了鎖并且設置了鎖的超時時間,但是 client1 之后出現了 STW,這個 STW 時間比較長,導致分布式鎖進行了釋放。

client2 獲取到了鎖,這個時候 client1 恢復了鎖,那么就會出現 client1,2 同時獲取到鎖,這個時候分布式鎖不安全問題就出現了。

這個不僅僅局限于 RedLock,對于我們的 ZK,MySQL 一樣的有同樣的問題。

時鐘發生跳躍

對于 Redis 服務器如果其時間發生了跳躍,肯定會影響我們鎖的過期時間。

那么我們的鎖過期時間就不是我們預期的了,也會出現 client1 和 client2 獲取到同一把鎖,也會出現不安全,這個對于 MySQL 也會出現。但是 ZK 由于沒有設置過期時間,那么發生跳躍也不會受影響。

長時間的網絡 I/O

這個問題和我們的 GC 的 STW 很像,也就是我們這個獲取了鎖之后我們進行網絡調用,其調用時間由可能比我們鎖的過期時間都還長,那么也會出現不安全的問題,這個 MySQL 也會有,ZK 也不會出現這個問題。

對于這三個問題,在網上包括 Redis 作者在內發起了很多討論。

GC 的 STW

對于這個問題可以看見基本所有的都會出現問題,Martin 給出了一個解法,對于 ZK 這種他會生成一個自增的序列,那么我們真正進行對資源操作的時候,需要判斷當前序列是否是最新,有點類似于樂觀鎖。

當然這個解法 Redis 作者進行了反駁,你既然都能生成一個自增的序列了那么你完全不需要加鎖了,也就是可以按照類似于 MySQL 樂觀鎖的解法去做。

我自己認為這種解法增加了復雜性,當我們對資源操作的時候需要增加判斷序列號是否是最新,無論用什么判斷方法都會增加復雜度,后面會介紹谷歌的 Chubby 提出了一個更好的方案。

時鐘發生跳躍

Martin 覺得 RedLock 不安全很大的原因也是因為時鐘的跳躍,因為鎖過期強依賴于時間,但是 ZK 不需要依賴時間,依賴每個節點的 Session。

Redis 作者也給出了解答,對于時間跳躍分為人為調整和 NTP 自動調整:

  • 人為調整:人為調整影響的完全可以人為不調整,這個是處于可控的。
  • NTP 自動調整:這個可以通過一定的優化,把跳躍時間控制在可控范圍內,雖然會跳躍,但是是完全可以接受的。

長時間的網絡 I/O

這一塊不是他們討論的重點,我自己覺得,對于這個問題的優化可以控制網絡調用的超時時間,把所有網絡調用的超時時間相加。

那么我們鎖過期時間其實應該大于這個時間,當然也可以通過優化網絡調用比如串行改成并行,異步化等。

Chubby 的一些優化

大家搜索 ZK 的時候,會發現他們都寫了 ZK 是 Chubby 的開源實現,Chubby 內部工作原理和 ZK 類似。但是 Chubby 的定位是分布式鎖和 ZK 有點不同。

Chubby 也是使用上面自增序列的方案用來解決分布式不安全的問題,但是它提供了多種校驗方法:

  • CheckSequencer():調用 Chubby 的 API 檢查此時這個序列號是否有效。
  • 訪問資源服務器檢查,判斷當前資源服務器最新的序列號和我們的序列號的大小。
  • lock-delay:為了防止我們校驗的邏輯入侵我們的資源服務器,其提供了一種方法當客戶端失聯的時候,并不會立即釋放鎖,而是在一定的時間內(默認 1min)阻止其他客戶端拿去這個鎖。

那么也就是給予了一定的 buffer 等待 STW 恢復,而我們的 GC 的 STW 時間如果比 1min 還長那么你應該檢查你的程序,而不是懷疑你的分布式鎖了。

小結

本文主要講了多種分布式鎖的實現方法,以及它們的一些優缺點。最后也說了一下關于分布式鎖的安全的問題。

對于不同的業務需要的安全程度完全不同,我們需要根據自己的業務場景,通過不同的維度分析,選取最適合自己的方案。

 

責任編輯:武曉燕 來源: 咖啡拿鐵
相關推薦

2021-10-21 06:52:17

ZooKeeper分布式配置

2017-03-30 22:41:55

虛擬化操作系統軟件

2021-11-10 07:47:48

Traefik邊緣網關

2018-12-07 09:31:52

分布式鎖服務框架分布式系統

2022-05-27 08:18:00

HashMapHash哈希表

2024-03-26 00:00:06

RedisZSet排行榜

2019-09-25 09:17:43

物聯網技術信息安全

2024-07-05 11:01:13

2018-10-31 17:22:25

AI人工智能芯片

2023-12-01 08:39:29

分布式鎖系統

2019-10-08 10:37:46

設計技術程序員

2019-10-31 09:48:53

MySQL數據庫事務

2020-10-13 07:44:40

緩存雪崩 穿透

2024-02-28 08:59:47

2018-08-17 09:14:43

餓了么容器演進

2021-07-13 12:21:34

PythonRPC通信

2025-11-10 01:35:00

2021-04-09 10:03:12

大數據exactly-onc

2022-08-26 05:22:21

RabbitMQ架構

2017-03-10 21:04:04

Android適配
點贊
收藏

51CTO技術棧公眾號

国产专区第一页| 四季av综合网站| 成人在线免费看片| 国产精品一二三区| 欧美一级视频一区二区| 人妻熟人中文字幕一区二区| 清纯唯美激情亚洲| 色综合天天综合色综合av| 在线播放豆国产99亚洲| 欧美77777| 美女视频一区二区| 97超碰国产精品女人人人爽| 91狠狠综合久久久久久| 在线精品视频一区| 欧美日韩情趣电影| 波多野结衣乳巨码无在线| 日本韩国在线视频爽| av电影天堂一区二区在线观看| 国产精品久久久久999| 高h视频免费观看| 国产精品美女久久久久久不卡 | 国产特级黄色大片| 麻豆传媒在线观看| 久久久久久久久久看片| 91麻豆国产精品| 日韩精品一区不卡| 国产一区亚洲| 精品国产一区二区三区在线观看| 艳妇乳肉亭妇荡乳av| 美女日韩一区| 欧美综合亚洲图片综合区| 日韩xxxx视频| 曰本三级在线| 国产精品国产三级国产| 热舞福利精品大尺度视频| 亚洲国产精品二区| 国产在线精品一区二区夜色| 国产精品高潮粉嫩av| 色婷婷在线观看视频| 好看的亚洲午夜视频在线| 色多多国产成人永久免费网站 | 国产精品人成在线观看免费| 久久精品中文字幕一区二区三区 | 国产亚洲精品av| 婷婷亚洲最大| 日韩在线观看你懂的| 欧美色图亚洲激情| 亚洲日产av中文字幕| 亚洲国产91精品在线观看| 黄色av电影网站| 中文字幕一区二区三区四区久久| 日韩午夜电影在线观看| 性生活在线视频| 日本精品在线观看| 日韩一级欧美一级| 日本女人性视频| 亚洲**毛片| 日韩精品一区二| 大尺度在线观看| 成人直播在线观看| 亚洲国产精品人人爽夜夜爽| 麻豆精品国产传媒av| 欧美色图五月天| 日韩电影大全免费观看2023年上| 好吊色视频一区二区三区| 极品国产人妖chinesets亚洲人妖| 精品免费国产二区三区 | 成人一级免费视频| 人人精品人人爱| 成人免费在线视频网站| 国产偷拍一区二区| fc2成人免费人成在线观看播放| 精品国产一区二区三区免费| 男人的天堂在线免费视频| 久久久久国产成人精品亚洲午夜| 日本不卡在线播放| 在线a人片免费观看视频| ...xxx性欧美| 99久久99久久精品| 午夜激情电影在线播放| 欧美午夜精品久久久| 免费精品99久久国产综合精品应用| 国产一区二区三区国产精品| 欧美sm极限捆绑bd| 日本japanese极品少妇| 成人久久久久| 欧美黑人巨大精品一区二区| 午夜婷婷在线观看| 麻豆精品在线观看| 国产精品国产亚洲精品看不卡15| 青青操视频在线| 成人欧美一区二区三区1314| 美女一区二区三区视频| 国产精品视频第一页| 国产成人精品综合在线观看 | 国产精伦一区二区三区| 亚洲精品小视频在线观看| 69精品无码成人久久久久久| 亚洲国产老妈| 45www国产精品网站| 国产口爆吞精一区二区| 99久久精品国产毛片| 亚洲国产日韩欧美| av色在线观看| 欧美三级中文字| 成年女人免费视频| 91嫩草亚洲精品| 91精品国产成人| 亚洲天堂网在线观看视频| 成人白浆超碰人人人人| 视频在线精品一区| heyzo一区| 制服丝袜日韩国产| 亚洲黄色免费视频| 亚洲日韩视频| 91麻豆国产语对白在线观看| 欧美套图亚洲一区| 一区二区欧美精品| 538任你躁在线精品免费| 久久99精品国产自在现线| 久久久精品久久久久| 久久精品久久久久久久| 丁香亚洲综合激情啪啪综合| 一区二区三区四区| 蜜臀国产一区| 亚洲国产精品久久| 亚洲人做受高潮| 琪琪一区二区三区| 欧美一区二区三区四区夜夜大片| 久草成色在线| 67194成人在线观看| 手机毛片在线观看| 久久一二三四| 成人资源视频网站免费| 免费在线观看av| 欧美一a一片一级一片| 国产精品亚洲无码| 亚洲永久免费精品| 精品视频免费观看| 性国裸体高清亚洲| 亚洲激情视频在线播放| 日韩av一二三区| 成人久久18免费网站麻豆| 9l视频自拍9l视频自拍| 国产成人视屏| 大胆人体色综合| 国产一区二区麻豆| 最新日韩在线视频| 亚洲一级片免费观看| 亚洲天堂免费| 99国产超薄肉色丝袜交足的后果| 性欧美1819sex性高清大胸| 91精品国产色综合久久不卡蜜臀| 中国特黄一级片| 欧美aaaaaa午夜精品| 亚洲五月六月| 成人精品在线| 欧美精品免费播放| 亚洲成人一级片| 亚洲一区在线视频观看| 无码人妻一区二区三区精品视频| 亚洲午夜激情在线| 韩国一区二区三区美女美女秀| 乱馆动漫1~6集在线观看| 日韩av在线网| 日韩精品成人免费观看视频| 久久久久久免费网| 亚洲综合av在线播放| 婷婷综合社区| 国产精品污www一区二区三区| 福利成人导航| 亚洲人成啪啪网站| 国产乱码在线观看| 亚洲人成人一区二区在线观看 | 青青草免费观看视频| 久久综合色播五月| 亚洲精品自拍网| 亚洲女同另类| 国产精品亚洲综合| 欧美日韩在线精品一区二区三区激情综合 | 亚洲av无码国产综合专区| 五月天一区二区三区| 波多野吉衣中文字幕| 久久精品999| 欧美视频在线第一页| 欧美人妖视频| 国产精品欧美风情| 亚洲资源一区| 亚洲精品中文字| 一级特黄aaa| 亚洲国产你懂的| 日本美女xxx| 国产电影一区在线| 日韩一级免费在线观看| 亚洲成人日韩| 欧美在线3区| 日本精品视频| 国产精品久久久久免费a∨ | 夜夜揉揉日日人人青青一国产精品 | 国产无遮挡又黄又爽在线观看| 久久精品视频一区二区三区| 欧美日韩精品区别| 性色一区二区| bt天堂新版中文在线地址| 精品成人影院| 国产精品我不卡| 亚洲精品一区av| 欧美综合一区第一页| a视频在线观看免费| 亚洲全黄一级网站| 欧美视频在线观看一区二区三区| 欧美三级欧美一级| 在线免费黄色av| 一区二区三区中文字幕| 久久视频精品在线观看| 成人性生交大合| 亚洲免费av一区| 日日夜夜精品视频免费| 免费观看国产精品视频| 亚洲一级淫片| 亚洲一区二区免费视频软件合集| 香蕉一区二区| 国产伦理久久久| 欧美日本三级| 国产精品稀缺呦系列在线| 蜜桃视频动漫在线播放| 欧美黑人巨大xxx极品| 老司机精品影院| 中文字幕国内精品| 欧美日本网站| 日韩精品日韩在线观看| 国模无码一区二区三区| 日韩一级片在线观看| 97久久人国产精品婷婷| 欧美三级电影在线看| 国产无遮挡又黄又爽又色视频| 狠狠色狠狠色综合日日小说| 国产精品6666| 亚洲午夜视频在线观看| 久久成人国产精品入口| 亚洲精品写真福利| 91视频免费在线看| 亚洲精品欧美激情| 手机av在线看| 自拍视频在线观看一区二区| av免费播放网站| 国产精品久久久久影院| 国产三级精品三级观看| 中文字幕欧美一区| 我要看一级黄色录像| 综合婷婷亚洲小说| 中文字幕电影av| 亚洲男女一区二区三区| 欧美三级日本三级| 午夜精品久久久久久久蜜桃app | 精品福利av| av无码久久久久久不卡网站| 亚洲美女黄网| 午夜精品久久久久久久无码| 亚洲另类黄色| 777米奇影视第四色| 丝袜美腿亚洲一区| 在线观看的毛片| 韩国精品久久久| 中文字幕无码毛片免费看| 成人精品免费看| 久久久久9999| 国产欧美一区二区在线观看| 性色国产成人久久久精品 | 国产手机在线视频| 色8久久人人97超碰香蕉987| 怡春院在线视频| 日韩欧美亚洲国产精品字幕久久久| 亚洲第一视频在线播放| 亚洲精品按摩视频| 国产免费视频在线| 日韩专区中文字幕| 女子免费在线观看视频www| 欧美在线免费视频| 国产精品久久久久久久久久齐齐| 成人av在线天堂| 国产人妖ts一区二区| 欧美精品一区二区三区在线四季 | 国产资源在线视频| 日韩av电影免费观看高清完整版| 久久久久久久高清| 99在线视频精品| wwwww黄色| 亚洲一二三四区| 姑娘第5集在线观看免费好剧| 欧美一二三区在线观看| 青草久久伊人| 欧美成人免费全部观看天天性色| 午夜不卡影院| 91免费国产网站| 香蕉久久夜色精品国产更新时间 | 亚洲视频精品| 男人搞女人网站| 国产69精品一区二区亚洲孕妇| 在线免费观看麻豆| 亚洲自拍偷拍综合| 在线视频精品免费| 精品欧美一区二区三区精品久久| 国产高清视频在线观看| 久久久久久久影院| 四虎国产精品免费久久5151| 精品一区在线播放| 欧美国产先锋| 精品综合久久久久| 国产日韩欧美一区二区三区综合| 日本少妇吞精囗交| 91精品久久久久久久91蜜桃| 青青草视频在线免费观看| 欧美精品在线免费| 日本在线中文字幕一区二区三区| 国产日韩欧美综合精品| 忘忧草精品久久久久久久高清| av五月天在线| 91在线视频网址| 精品无码一区二区三区电影桃花| 欧美高清视频一二三区| 国产三级视频在线| 欧美亚洲一级片| 国产精品宾馆| av日韩在线看| 国产v日产∨综合v精品视频| 色欲人妻综合网| 欧美情侣在线播放| www.亚洲免费| 国产97在线播放| 亚洲区小说区图片区qvod按摩| 国产av人人夜夜澡人人爽麻豆| 国产在线乱码一区二区三区| 婷婷国产成人精品视频| 欧美日韩精品一区二区三区蜜桃 | 欧美大片va欧美在线播放| 日韩黄色三级在线观看| 亚洲精品日韩在线观看| 日韩电影在线观看一区| 日本激情小视频| 色婷婷亚洲综合| 欧洲亚洲在线| 国产精品福利在线观看网址| 国产一区毛片| www黄色在线| 国产欧美1区2区3区| 国产成人精品一区二区色戒| 亚洲人成网站色ww在线| 久久野战av| 日韩福利一区二区三区| 日本欧美大码aⅴ在线播放| 国产三级在线观看完整版| 欧美三级视频在线观看| 老司机在线看片网av| 亚洲自拍偷拍色图| 亚洲精选91| 亚洲日本精品视频| 欧美日韩一区二区三区不卡| 黄色av网站在线播放| 亚洲淫片在线视频| 国内自拍一区| 日本黄色网址大全| 欧美日韩一区二区三区四区五区| 欧美18hd| 国产 高清 精品 在线 a| 亚洲国产精品第一区二区| 熟女少妇一区二区三区| 欧美日韩精品二区第二页| 丝袜在线视频| 精品在线不卡| 秋霞成人午夜伦在线观看| 国产中文av在线| 日韩精品一区二区三区四区| 黄视频网站在线观看| 先锋影音亚洲资源| 国产成人精品网址| 欧美超碰在线观看| 免费不卡在线观看av| 风间由美性色一区二区三区四区| 大肉大捧一进一出好爽视频| 欧美激情一区三区| 性欧美18一19性猛交| 欧美在线亚洲一区| 香蕉国产精品| 麻豆av免费观看| 91超碰这里只有精品国产| f2c人成在线观看免费视频| 视频一区二区三区在线观看| 国产精品18久久久久久久久 | 丝袜亚洲精品中文字幕一区| 中文字幕在线2021| 亚洲美女激情视频| 日韩精品一级| 免费大片在线观看| 一区二区三区中文字幕电影| 国产系列在线观看| 国产精品v欧美精品∨日韩| 麻豆一区二区三| 久草手机在线观看| 九九热这里只有精品免费看|