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

Redis 分布式鎖沒這么簡單,網(wǎng)上大多數(shù)都有 bug

存儲 存儲軟件 分布式 Redis
分布式鎖就是用來控制同一時刻,只有一個 JVM 進程中的一個線程「精子」可以訪問被保護的資源「卵子」。

[[434468]]

Redis 分布式鎖這個話題似乎爛大街了,不管你是面試還是工作,隨處可見,「碼哥」為啥還要寫呢?

因為網(wǎng)上 99.99% 的文章都沒有真正的把分布式鎖說清楚,存在很多 bug。

今日,「碼哥」就跟大家深入分布式鎖的 G 點,系統(tǒng)的做一個寫好代碼掌握技巧的真男人。

在進入「高潮」之前,以下問題就當做「前戲」去思考,你能回答多少?

  • 什么時候需要分布式鎖?
  • 加、解鎖的代碼位置有講究么?
  • 如何避免出現(xiàn)死鎖
  • 超時時間設置多少合適呢?
  • 如何避免鎖被其他線程釋放
  • 如何實現(xiàn)重入鎖?
  • 主從架構會帶來什么安全問題?
  • 什么是 Redlock
  • ……

為何需要分布式鎖?

碼哥,說個通俗的例子講解下什么時候需要分布式鎖呢?

精子噴射那一刻,億級流量沖向卵子,只有一個精子能獲得與卵子結(jié)合的幸運。

造物主為了保證只有一個「精子」能獲得「卵子」的寵幸,當有一個精子進入后,卵子的外殼就會發(fā)生變化,將通道關閉把其余的精子阻擋在外。

億級別的精子就好比「并發(fā)」流量;

卵子就好比是共享資源;

卵子外殼只允許一個精子進入的特殊蛋白就是一把鎖。

而多節(jié)點構成的集群,就會有多個 JVM 進程,我們獲得同樣的效果就需要有一個中間人協(xié)調(diào),只允許一個 JVM 中的一個線程獲得操作共享資源的資格。

分布式鎖就是用來控制同一時刻,只有一個 JVM 進程中的一個線程「精子」可以訪問被保護的資源「卵子」。

「每一個生命,都是億級選手中的佼佼者」,加油。

分布式鎖入門

分布式鎖應該滿足哪些特性?

  • 互斥:在任何給定時刻,只有一個客戶端可以持有鎖;
  • 無死鎖:任何時刻都有可能獲得鎖,即使獲取鎖的客戶端崩潰;
  • 容錯:只要大多數(shù) Redis的節(jié)點都已經(jīng)啟動,客戶端就可以獲取和釋放鎖。

碼哥,我可以使用 SETNX key value 命令是實現(xiàn)「互斥」特性。

這個命令來自于SET if Not eXists的縮寫,意思是:如果 key 不存在,則設置 value 給這個key,否則啥都不做。

命令的返回值:

  • 1:設置成功;
  • 0:key 沒有設置成功。

如下場景:

敲代碼一天累了,想去放松按摩下肩頸。

168 號技師最搶手,大家喜歡點,所以并發(fā)量大,需要分布式鎖控制。

同一時刻只允許一個「客戶」預約 168 技師。

肖彩機申請 168 技師成功:

  1. > SETNX lock:168 1 
  2.  
  3. (integer) 1 # 獲取 168 技師成功 

謝霸哥后面到,申請失敗:

  1. > SETNX lock 2 
  2.  
  3. (integer) 0 # 客戶謝霸哥 2 獲取失敗 

此刻,申請成功的客戶就可以享受 168 技師的肩頸放松服務「共享資源」。

享受結(jié)束后,要及時釋放鎖,給后來者享受 168 技師的服務機會。

肖彩機,碼哥考考你如何釋放鎖呢?

很簡單,使用 DEL 刪除這個 key 就行。

  1. > DEL lock:168 
  2.  
  3. (integer) 1 

碼哥,你見過「龍」么?我見過,因為我被一條龍服務過。

肖彩機,事情可沒這么簡單。

這個方案存在一個存在造成「死鎖」的問題,造成該問題的場景如下:

在按摩過程中突然收到線上報警,提起褲子就跑去公司了,沒及時執(zhí)行 DEL 釋放鎖(客戶端處理業(yè)務異常,無法正確釋放鎖);

按摩過程中心肌梗塞嗝屁了,無法執(zhí)行 DEL指令。

這樣,這個鎖就會一直占用,其他客戶就「再也沒有」機會獲取 168 技師服務了。

如何避免死鎖

碼哥,我可以在獲取鎖成功的時候設置一個「超時時間」

比如設定按摩服務一次 60 分鐘,那么在給這個 key 加鎖的時候設置 60 分鐘過期即可:

  1. > SETNX lock:168 1  // 獲取鎖 
  2. (integer) 1 
  3. > EXPIRE lock:168 60  // 60s 自動刪除 
  4. (integer) 1 

這樣,到點后鎖自動釋放,其他客戶就可以繼續(xù)享受 168 技師按摩服務了。

誰要這么寫,就糟透了。

「加鎖」、「設置超時」是兩個命令,他們不是原子操作。

如果出現(xiàn)只執(zhí)行了第一條,第二條沒機會執(zhí)行就會出現(xiàn)「超時時間」設置失敗,依然出現(xiàn)死鎖。

比如以下場景導致無法執(zhí)行第二條指令:

Redis 異常宕機;

客戶端異常崩潰;

碼哥,那咋辦,我想被一條龍服務,不能出現(xiàn)死鎖啊。

Redis 2.6.12 之后,拓展了 SET 命令的參數(shù),滿足了當 key 不存在則設置 value,同時設置超時時間的語義,并且滿足原子性。

  1. SET resource_name random_value NX PX 30000 

NX:表示只有 resource_name 不存在的時候才能 SET 成功,從而保證只有一個客戶端可以獲得鎖;

PX 30000:表示這個鎖有一個 30 秒自動過期時間。

執(zhí)行時間超過鎖的過期時間

這樣我能穩(wěn)妥的享受一條龍服務了么?

No,還有一種場景會導致釋放別人的鎖:

  • 客戶 1 獲取鎖成功并設置 30 秒超時;
  • 客戶 1 因為一些原因?qū)е聢?zhí)行很慢(網(wǎng)絡問題、發(fā)生 FullGC……),過了 30 秒依然沒執(zhí)行完,但是鎖過期「自動釋放了」;
  • 客戶 2 申請加鎖成功;
  • 客戶 1 執(zhí)行完成,執(zhí)行 DEL 釋放鎖指令,這個時候就把 客戶 2 的鎖給釋放了。

有兩個關鍵問題需要解決:

  • 如何合理設置過期時間?
  • 如何避免刪除別人持有的鎖。

正確設置鎖超時

鎖的超時時間怎么計算合適呢?

這個時間不能瞎寫,一般要根據(jù)在測試環(huán)境多次測試,然后壓測多輪之后,比如計算出平均執(zhí)行時間 200 ms。

那么鎖的超時時間就放大為平均執(zhí)行時間的 3~5 倍。

為啥要放大呢?

因為如果鎖的操作邏輯中有網(wǎng)絡 IO 操作、JVM FullGC 等,線上的網(wǎng)絡不會總一帆風順,我們要給網(wǎng)絡抖動留有緩沖時間。

那我設置更大一點,比如設置 1 小時不是更安全?

不要鉆牛角,多大算大?

設置時間過長,一旦發(fā)生宕機重啟,就意味著 1 小時內(nèi),分布式鎖的服務全部節(jié)點不可用。

你要讓運維手動刪除這個鎖么?

只要運維真的不會打你。

有沒有完美的方案呢?不管時間怎么設置都不大合適。

我們可以讓獲得鎖的線程開啟一個守護線程,用來給快要過期的鎖「續(xù)航」。

加鎖的時候設置一個過期時間,同時客戶端開啟一個「守護線程」,定時去檢測這個鎖的失效時間。

如果快要過期,但是業(yè)務邏輯還沒執(zhí)行完成,自動對這個鎖進行續(xù)期,重新設置過期時間。

這個道理行得通,可我寫不出。

別慌,已經(jīng)有一個庫把這些工作都封裝好了他叫Redisson。

Redisson 是一個 Java 語言實現(xiàn)的 Redis SDK 客戶端,在使用分布式鎖時,它就采用了「自動續(xù)期」的方案來避免鎖過期,這個守護線程我們一般也把它叫做「看門狗」線程。

關于 Redisson 的使用與原理分析由于篇幅有限,大家可關注「碼哥字節(jié)」且聽下回分解。

避免釋放別人的鎖

出現(xiàn)釋放別人鎖的關鍵在于「無腦執(zhí)行」DEL指令,所以我們要想辦法檢查下這個鎖是不是自己加的。

解鈴還須系鈴人

碼哥,我在加鎖的時候設置一個「唯一標識」作為 value 代表加鎖的客戶端。

在釋放鎖的時候,客戶端將自己的「唯一標識」與鎖上的「標識」比較是否相等,匹配上則刪除,否則沒有權利釋放鎖。

偽代碼如下:

  1. // 比對 value 與 唯一標識 
  2. if (redis.get("lock:168").equals(uuid)){ 
  3.    redis.del("lock:168"); //比對成功則刪除 
  4.  } 

有沒有想過,這是 GET + DEL 指令組合而成的,這里又會涉及到原子性問題。

復現(xiàn)下情況:

  • 客戶端 1 第一步對比成功后,第二步還沒來得及執(zhí)行,這時候鎖到期了。
  • 客戶端 2 獲取鎖成功,將自己的 「uuid」設置進去。
  • 這時候客戶端 1 執(zhí)行第二步進行釋放鎖,這肯定是錯誤的。

我們是追求極致的男人,所以這里通過 Lua 腳本來實現(xiàn),這樣判斷和刪除的過程就是原子操作了。

  1. if redis.call("get",KEYS[1]) == ARGV[1] then 
  2.     return redis.call("del",KEYS[1]) 
  3. else 
  4.     return 0 
  5. end 

一路優(yōu)化下來,方案似乎比較「嚴謹」了,抽象出對應的模型如下。

通過 SET lock_resource_name $unique_id NX PX $expire_time,同時啟動守護線程為快要過期單還沒執(zhí)行完畢的客戶端的鎖續(xù)命;

客戶端執(zhí)行業(yè)務邏輯操作共享資源;

通過 Lua 腳本釋放鎖,先 get 判斷鎖是否是自己加的,再執(zhí)行 DEL。

加解鎖代碼位置有講究

根據(jù)前面的分析,我們已經(jīng)有了一個「相對嚴謹」的分布式鎖了。

于是「謝霸哥」就寫了如下代碼將分布式鎖運用到項目中,以下是偽代碼邏輯:

  1. public void doSomething() { 
  2.     try { 
  3.         redisLock.lock(); // 上鎖 
  4.         // 處理業(yè)務 
  5.         redisLock.unlock(); // 釋放鎖 
  6.     } catch (Exception e) { 
  7.         e.printStackTrace(); 
  8.     } 

一旦執(zhí)行業(yè)務邏輯過程中拋出異常,程序就無法走下一步釋放鎖的流程。

所以釋放鎖的代碼一定要放在 finally{} 塊中。

加鎖的位置也有問題,如果執(zhí)行 redisLock.lock() 加鎖異常,那么就會執(zhí)行 finally{} 代碼塊指令執(zhí)行解鎖,這個時候鎖并沒有申請成功。

所以 redisLock.lock();應該放在 try 外面。

綜上所述,正確代碼位置如下 :

  1. public void doSomething() { 
  2.    // 上鎖 
  3.    redisLock.lock(); 
  4.     try { 
  5.         // 處理業(yè)務 
  6.         ... 
  7.     } catch (Exception e) { 
  8.         e.printStackTrace(); 
  9.     } finally { 
  10.       // 釋放鎖 
  11.       redisLock.unlock(); 
  12.     } 

實現(xiàn)可重入鎖

可重入鎖要如何實現(xiàn)呢?重入之后,超時時間如何設置呢?

當一個線程執(zhí)行一段代碼成功獲取鎖之后,繼續(xù)執(zhí)行時,又遇到加鎖的代碼,可重入性就就保證線程能繼續(xù)執(zhí)行,而不可重入就是需要等待鎖釋放之后,再次獲取鎖成功,才能繼續(xù)往下執(zhí)行。

用一段代碼解釋可重入:

  1. public synchronized void a() { 
  2.     b(); 
  3. public synchronized void b() { 
  4.     // pass 

假設 X 線程在 a 方法獲取鎖之后,繼續(xù)執(zhí)行 b 方法,如果此時不可重入,線程就必須等待鎖釋放,再次爭搶鎖。

鎖明明是被 X 線程擁有,卻還需要等待自己釋放鎖,然后再去搶鎖,這看起來就很奇怪,我釋放我自己~

Redis Hash 可重入鎖

Redisson 類庫就是通過 Redis Hash 來實現(xiàn)可重入鎖,未來碼哥會專門寫一篇關于 Redisson 的使用與原理的文章……

當線程擁有鎖之后,往后再遇到加鎖方法,直接將加鎖次數(shù)加 1,然后再執(zhí)行方法邏輯。

退出加鎖方法之后,加鎖次數(shù)再減 1,當加鎖次數(shù)為 0 時,鎖才被真正的釋放。

可以看到可重入鎖最大特性就是計數(shù),計算加鎖的次數(shù)。

所以當可重入鎖需要在分布式環(huán)境實現(xiàn)時,我們也就需要統(tǒng)計加鎖次數(shù)。

加鎖邏輯

我們可以使用 Redis hash 結(jié)構實現(xiàn),key 表示被鎖的共享資源, hash 結(jié)構的 fieldKey 的 value 則保存加鎖的次數(shù)。

通過 Lua 腳本實現(xiàn)原子性,假設 KEYS1 = 「lock」, ARGV「1000,uuid」:

  1. ---- 1 代表 true 
  2. ---- 0 代表 false 
  3.  
  4. if (redis.call('exists', KEYS[1]) == 0) then 
  5.     redis.call('hincrby', KEYS[1], ARGV[2], 1); 
  6.     redis.call('pexpire', KEYS[1], ARGV[1]); 
  7.     return 1; 
  8. end ; 
  9. if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then 
  10.     redis.call('hincrby', KEYS[1], ARGV[2], 1); 
  11.     redis.call('pexpire', KEYS[1], ARGV[1]); 
  12.     return 1; 
  13. end ; 
  14. return 0; 

加鎖代碼首先使用 Redis exists 命令判斷當前 lock 這個鎖是否存在。

如果鎖不存在的話,直接使用 hincrby創(chuàng)建一個鍵為 lock hash 表,并且為 Hash 表中鍵為 uuid 初始化為 0,然后再次加 1,最后再設置過期時間。

如果當前鎖存在,則使用 hexists判斷當前 lock 對應的 hash 表中是否存在 uuid 這個鍵,如果存在,再次使用 hincrby 加 1,最后再次設置過期時間。

最后如果上述兩個邏輯都不符合,直接返回。

解鎖邏輯

  1. -- 判斷 hash set 可重入 key 的值是否等于 0 
  2. -- 如果為 0 代表 該可重入 key 不存在 
  3. if (redis.call('hexists', KEYS[1], ARGV[1]) == 0) then 
  4.     return nil; 
  5. end ; 
  6. -- 計算當前可重入次數(shù) 
  7. local counter = redis.call('hincrby', KEYS[1], ARGV[1], -1); 
  8. -- 小于等于 0 代表可以解鎖 
  9. if (counter > 0) then 
  10.     return 0; 
  11. else 
  12.     redis.call('del', KEYS[1]); 
  13.     return 1; 
  14. end ; 
  15. return nil; 

首先使用 hexists 判斷 Redis Hash 表是否存給定的域。

如果 lock 對應 Hash 表不存在,或者 Hash 表不存在 uuid 這個 key,直接返回 nil。

若存在的情況下,代表當前鎖被其持有,首先使用 hincrby使可重入次數(shù)減 1 ,然后判斷計算之后可重入次數(shù),若小于等于 0,則使用 del 刪除這把鎖。

解鎖代碼執(zhí)行方式與加鎖類似,只不過解鎖的執(zhí)行結(jié)果返回類型使用 Long。這里之所以沒有跟加鎖一樣使用 Boolean ,這是因為解鎖 lua 腳本中,三個返回值含義如下:

  • 1 代表解鎖成功,鎖被釋放
  • 0 代表可重入次數(shù)被減 1
  • null 代表其他線程嘗試解鎖,解鎖失敗

主從架構帶來的問題

碼哥,到這里分布式鎖「很完美了」吧,沒想到分布式鎖這么多門道。

路還很遠,之前分析的場景都是,鎖在「單個」Redis 實例中可能產(chǎn)生的問題,并沒有涉及到 Redis 的部署架構細節(jié)。

我們通常使用「Cluster 集群」或者「哨兵集群」的模式部署保證高可用。

這兩個模式都是基于「主從架構數(shù)據(jù)同步復制」實現(xiàn)的數(shù)據(jù)同步,而 Redis 的主從復制默認是異步的。

我們試想下如下場景會發(fā)生什么問題:

如果客戶端 1 剛往 master 節(jié)點寫入一個分布式鎖,此時這個指令還沒來得及同步到 slave 節(jié)點。

此時,master 節(jié)點宕機,其中一個 slave 被選舉為新 master,這時候新 master 是沒有客戶端 1 寫入的鎖,鎖丟失了。

此刻,客戶端 2 線程來獲取鎖,就成功了。

雖然這個概率極低,但是我們必須得承認這個風險的存在。

Redis 的作者提出了一種解決方案,叫 Redlock(紅鎖)

Redis 的作者為了統(tǒng)一分布式鎖的標準,搞了一個 Redlock,算是 Redis 官方對于實現(xiàn)分布式鎖的指導規(guī)范,https://redis.io/topics/distlock,但是這個 Redlock 也被國外的一些分布式專家給噴了。

因為它也不完美,有“漏洞”。

什么是 Redlock

紅鎖是不是這個?

泡面吃多了你,Redlock 紅鎖是為了解決主從架構中鎖丟失而提出的一種算法。

Redlock 的方案基于 2 個前提:

  • 不需要部署從庫和哨兵實例,只部署主庫
  • 但主庫要部署多個,官方推薦至少 5 個實例,這樣可以保證他們不會同時宕機。

也就是說,想用使用 Redlock,你至少要部署 5 個 Redis 實例,而且都是主庫,它們之間沒有任何關系,都是一個個孤立的實例。

一個客戶端要獲取鎖有 5 個步驟:

  • 客戶端獲取當前時間 T1(毫秒級別);
  • 使用相同的 key和 value順序嘗試從 N個 Redis實例上獲取鎖。
    • 每個請求都設置一個超時時間(毫秒級別),該超時時間要遠小于鎖的有效時間,這樣便于快速嘗試與下一個實例發(fā)送請求。
    • 比如鎖的自動釋放時間 10s,則請求的超時時間可以設置 5~50 毫秒內(nèi),這樣可以防止客戶端長時間阻塞。
  • 客戶端獲取當前時間 T2 并減去步驟 1 的 T1 來計算出獲取鎖所用的時間(T3 = T2 -T1)。當且僅當客戶端在大多數(shù)實例(N/2 + 1)獲取成功,且獲取鎖所用的總時間 T3 小于鎖的有效時間,才認為加鎖成功,否則加鎖失敗。
  • 如果第 3 步加鎖成功,則執(zhí)行業(yè)務邏輯操作共享資源,key 的真正有效時間等于有效時間減去獲取鎖所使用的時間(步驟 3 計算的結(jié)果)。
  • 如果因為某些原因,獲取鎖失敗(沒有在至少 N/2+1 個 Redis 實例取到鎖或者取鎖時間已經(jīng)超過了有效時間),客戶端應該在所有的 Redis 實例上進行解鎖(即便某些 Redis 實例根本就沒有加鎖成功)。

為什么要部署多個實例并加鎖呢?

本質(zhì)是為了高可用和容錯,即使部分實例宕機,大多數(shù)實例加鎖成功,整個分布式鎖服務依然可用。

為啥在第三步要計算加鎖的累計時間?

因為多個節(jié)點加鎖,耗時可能會比較長,網(wǎng)絡中可能存在丟包、超時等現(xiàn)象。

即使大多數(shù)節(jié)點獲取鎖成功,假如獲取鎖的總時間已經(jīng)超過鎖的有效時間,這個鎖已經(jīng)沒有意義了。

為什么釋放鎖要操作所有節(jié)點,即使有的節(jié)點加鎖未成功?

因為有可能客戶端在 Redis 實例上加鎖成功,只是客戶端讀取響應的時候失敗導致客戶端以為加鎖失敗。

為了安全的清理鎖,就需要向每個節(jié)點發(fā)送釋放鎖的請求。

Redlock 這么完美?那他解決了 Redis 主從架構節(jié)點異常宕機導致鎖丟失的問題了么?

事情可沒這么簡單,Redis 作者把這個方案提出后,受到了業(yè)界著名的分布式系統(tǒng)專家的質(zhì)疑。

兩人好比神仙打架,兩人一來一回論據(jù)充足的對一個問題提出很多論斷……

由于篇幅原因,關于 兩人的爭論分析以及 Redssion 對分布式鎖的封裝以及 Redlock 的實現(xiàn)我們下期再見。

預知后事如何,且聽下回分解…

總結(jié)

完工,我建議你合上屏幕,自己在腦子里重新過一遍,每一步都在做什么,為什么要做,解決什么問題。

我們一起從頭到尾梳理了一遍 Redis 分布式鎖中的各種門道,其實很多點是不管用什么做分布式鎖都會存在的問題,重要的是思考的過程。

對于系統(tǒng)的設計,每個人的出發(fā)點都不一樣,沒有完美的架構,沒有普適的架構,但是在完美和普適能平衡的很好的架構,就是好的架構。

關于 Redlock 的爭論主要集中在如下幾點:

  • Redlock 效率太差、太重,對于提升效率的場景下,使用分布式鎖,允許鎖的偶爾失效,那么使用單 Redis 節(jié)點的鎖方案就足夠了,簡單而且效率高。
  • 對于正確性要求高的場景下,它是依賴于時間的,不是一個足夠強的算法。Redlock 并沒有保住正確性。

 

責任編輯:武曉燕 來源: 碼哥字節(jié)
相關推薦

2020-07-23 09:10:09

Redis分布式鎖漏洞

2023-09-22 08:00:00

分布式鎖Redis

2021-06-10 06:57:39

Redis存儲數(shù)據(jù)庫

2022-07-22 06:55:20

Redis分布式鎖

2019-06-19 15:40:06

分布式鎖RedisJava

2021-02-02 16:37:25

Redis分布式

2009-07-14 15:39:34

Swing大多數(shù)控件

2025-07-07 00:00:00

MCPA2AAPI

2022-03-08 07:22:48

Redis腳本分布式鎖

2023-10-10 18:26:58

分布式緩存

2024-07-04 15:47:28

2014-01-02 10:34:54

設計設計師

2023-08-21 19:10:34

Redis分布式

2022-01-06 10:58:07

Redis數(shù)據(jù)分布式鎖

2019-02-26 09:51:52

分布式鎖RedisZookeeper

2011-05-26 10:50:31

2016-10-26 09:42:13

2022-09-19 08:17:09

Redis分布式

2024-10-07 10:07:31

2020-11-16 12:55:41

Redis分布式鎖Zookeeper
點贊
收藏

51CTO技術棧公眾號

免费观看在线午夜影视| 亚洲无人区码一码二码三码的含义| 婷婷成人激情| 国产激情视频一区二区三区欧美| 亚洲欧美精品一区二区| 日本新janpanese乱熟| 日本成人网址| 成人av网站免费| 国产精品777| 国产精品嫩草av| 亚洲不卡系列| 国产欧美一区二区精品性色超碰| 97视频在线播放| 国产sm调教视频| 桃子视频成人app| 亚洲免费观看高清| 亚洲a∨日韩av高清在线观看| 久久精品欧美一区二区| 波多野结衣的一区二区三区| 色美美综合视频| 久久人妻无码一区二区| 国产伦理一区二区| 中文字幕一区二区三区欧美日韩| 3d动漫精品啪啪一区二区竹菊| 亚洲人体一区| 四虎精品成人影院观看地址| 国产一区二区在线免费观看| 日韩免费在线看| 国产在线视频在线观看| 91超碰成人| 日韩欧美成人激情| 天堂网在线免费观看| 超碰激情在线| 91色.com| 国产福利久久精品| 国产伦子伦对白视频| 日韩精彩视频在线观看| 欧美一级电影久久| 亚洲视频免费播放| 欧美日韩色图| 91精品久久久久久久99蜜桃 | 韩国三级hd两男一女| av成人福利| 久久新电视剧免费观看| 国产精品一区二区三区观看| 性中国xxx极品hd| 韩日av一区二区| 日韩在线小视频| 国产人妻大战黑人20p| 日韩成人综合网| 亚洲一区二区三区视频在线播放 | 久草免费资源站| 国产一区二区三区免费观看在线| 亚洲在线成人精品| 国产在线拍揄自揄拍无码| 手机在线精品视频| 蜜臀va亚洲va欧美va天堂| 国产精品999999| 久久免费视频精品| 欧美xxx在线观看| 亚洲日韩中文字幕| 国产免费一区二区三区网站免费| 亚洲福利影视| 91精品欧美福利在线观看| 看看黄色一级片| 在线毛片观看| 一区二区三区国产豹纹内裤在线| 欧美一区二区在线| 国产精品久久久久一区二区国产 | 国产老熟女伦老熟妇露脸| 不卡av影片| 色猫猫国产区一区二在线视频| www.-级毛片线天内射视视| av免费在线观看网站| 亚洲综合免费观看高清在线观看| 日本黄大片在线观看| 国产乱码在线| 日韩欧中文字幕| 国产一区二区三区乱码| 日本在线免费中文字幕| 26uuuu精品一区二区| 99一区二区| 亚洲国产精品va在线看黑人动漫| 2021国产视频| 欧美wwwwwww| 天天射天天色天天干| 91在线小视频| 日韩av电影免费在线| 精品国产99久久久久久| 一区二区不卡在线视频 午夜欧美不卡在| 日韩电影免费观看高清完整| 伊人在线视频| 亚洲第一搞黄网站| 国产男女激情视频| 中文字幕不卡三区视频| 欧美日韩一级大片网址| 又大又长粗又爽又黄少妇视频| 久久久加勒比| 欧美大片日本大片免费观看| 中文字幕第六页| 日韩在线激情| 欧美日韩在线观看一区二区| 午夜精品在线免费观看| 涩涩视频在线播放| 精品美女国产在线| 国产一区二区网| av成人在线播放| 精品嫩草影院久久| 妺妺窝人体色WWW精品| 欧美a级片网站| 精品中文字幕乱| 国产乱国产乱老熟300| 香蕉久久久久久久av网站| 成人写真视频福利网| 日本一区高清| 夜夜精品浪潮av一区二区三区| 成年人免费大片| 日韩av电影资源网| 亚洲国产日韩欧美在线动漫| 可以免费看av的网址| 亚洲美女色禁图| 91精品国产高清久久久久久91裸体| 国产精品久久久久久在线| 2023国产精品视频| 日韩欧美在线电影| 在线观看麻豆蜜桃| 欧美日韩在线看| 中文字幕1区2区| 天天影视欧美综合在线观看| 欧美成年人视频网站| 久久久久久天堂| 精品一区二区三区久久久| 欧美一区二区三区在线免费观看 | 久久久精品国产免大香伊 | 亚洲乱码视频| 99国产在线| 老司机在线视频二区| 在线观看国产一区二区| 久久久久xxxx| 岛国av一区| 亚洲精品一区中文| 国产精品日日夜夜| 国产成人欧美日韩在线电影| 日韩精品第1页| 国产va在线视频| 在线观看www91| 国产偷人妻精品一区| 亚洲大片在线| 国产精品久久久久久久久久免费| 亚洲av毛片成人精品| 国产精品久久夜| 乌克兰美女av| 都市激情亚洲| 在线精品国产欧美| 中文字幕乱码一区二区| 成人的网站免费观看| 亚洲.欧美.日本.国产综合在线| a毛片在线看免费观看| 欧美日韩另类一区| 国产探花在线视频| 国产伦精品一区二区三区免费迷| 久久综合一区二区三区| 亚洲风情在线资源| 欧美一级国产精品| 国产真实乱人偷精品人妻| 久久这里有精品15一区二区三区| 欧洲精品亚洲精品| 3344国产永久在线观看视频| 337p日本欧洲亚洲大胆精品| 久久精品日韩无码| 国产一区欧美二区| 先锋影音一区二区三区| 欧美一级免费| 伊人久久精品视频| 六月丁香激情综合| 粉嫩av一区二区三区| 亚洲精品一区二| 亚洲精品伊人| 在线观看免费高清视频97| 中文字幕一区二区三区精品| 国产精品一区二区在线观看网站| 婷婷久久伊人| 久久天堂久久| 91国内免费在线视频| 激情小说 在线视频| 欧美日韩国产综合视频在线观看 | 日韩av免费在线看| 日本综合在线| 亚洲国产精久久久久久久| 波多野结衣视频在线观看| 99久久精品免费| 91免费国产精品| 精品视频在线观看网站| 97在线视频一区| 在线免费黄色| 亚洲成人1234| 91精品国产高潮对白| 国产亚洲自拍一区| 少妇极品熟妇人妻无码| 三级久久三级久久久| 日本高清xxxx| 国产一区二区三区91| 亚洲最大的成人网| 3d玉蒲团在线观看| 日韩午夜av电影| 国产精品成人免费观看| 国产乱码精品一区二区三| 久久精品免费一区二区| 中文字幕一区二区三区欧美日韩| 欧美在线一区二区三区四区| 麻豆视频久久| 色综合久久中文字幕综合网小说| 蜜桃视频在线播放| 91成人在线精品| 免费看一级一片| 国产精品三级av在线播放| 老司机免费视频| 国产亚洲毛片在线| 中国女人做爰视频| 欧美色图一区| 国产女同一区二区| 97超碰资源站在线观看| 日韩精品一区二区三区四区| 久热精品在线观看| 中文字幕一区在线观看| 97人妻精品一区二区免费| 成人网在线免费视频| 男人和女人啪啪网站| 欧美影视一区| 国产精品夜夜夜爽张柏芝| av中文字幕一区二区| 亚洲自拍偷拍第一页| 激情国产在线| 久久久久久国产免费| 成人国产免费电影| 亚洲精品成人网| 玩弄japan白嫩少妇hd| 一区二区成人免费视频| 黑人巨大精品欧美一区| 天天碰免费视频| 国产欧美二区| 伊人av成人| youjizz亚洲| 超碰国产精品久久国产精品99| 未满十八勿进黄网站一区不卡| 国产精品欧美激情在线播放| 成人在线视频观看| 国产欧美日韩中文字幕在线| h片在线观看视频免费免费| 欧美激情视频免费观看| 成人免费在线观看| 亚洲视频在线免费观看| 撸视在线观看免费视频| 亚洲免费精彩视频| 国产普通话bbwbbwbbw| 第一福利永久视频精品| 日韩精品一区二区在线播放 | 日本成人片在线| 久久视频在线播放| a视频在线免费看| 欧美高跟鞋交xxxxhd| 少女频道在线观看高清| 一区二区三区 在线观看视| 国产福利在线| 日韩中文字幕在线看| 黄色在线观看网站| 亚洲欧美日韩在线一区| 国产三级电影在线| 亚洲精品国产品国语在线| 国产美女三级无套内谢| 日韩一区二区免费在线观看| 蜜臀av在线观看| 欧美一区二区三区影视| 亚洲女同志亚洲女同女播放| 亚洲第一页在线| 99久久国产热无码精品免费| 欧美成人精精品一区二区频| 91国内精品视频| 在线一区二区三区四区五区| 亚洲图片中文字幕| 在线观看精品一区| 国产婷婷在线视频| 日韩av在线影院| av在线日韩国产精品| 亚洲情综合五月天| 性xxxfllreexxx少妇| 日韩精品一区二区三区四区| 日中文字幕在线| 中文字幕亚洲精品| 国产区视频在线播放| 日韩电影免费在线观看中文字幕| 成人资源www网在线最新版| 操日韩av在线电影| 成人国产免费电影| 欧美在线观看网址综合| 小视频免费在线观看| 国产在线精品播放| 欧美调教在线| 亚洲欧美日韩不卡| 欧美亚洲一区二区三区| 18禁免费无码无遮挡不卡网站| 蜜桃视频一区二区三区| 性色av蜜臀av浪潮av老女人| 国产精品污www在线观看| 日本三级2019| 欧美性生交xxxxx久久久| 中日韩黄色大片| 666欧美在线视频| 国产特级黄色片| 夜夜嗨av色一区二区不卡| 亚洲小说区图片区都市| 国产精品日韩久久久久| 国产精品成人国产| 黄色99视频| 亚洲精品一级二级三级| 日本午夜一区二区三区| 日韩片欧美片| 波多野结衣激情| 天堂精品中文字幕在线| 黄色av电影网站| 综合久久久久综合| 乱子伦一区二区三区| 51精品国自产在线| 成年人在线视频| 欧美性资源免费| 成人福利一区| 久久久无码中文字幕久...| 麻豆精品久久久| 中国老熟女重囗味hdxx| 9久草视频在线视频精品| 午夜国产福利一区二区| 亚洲国产wwwccc36天堂| www视频在线| 欧美成人网在线| 涩涩在线视频| 国产在线观看精品| 成人免费a**址| 欧美国产日韩在线播放| 国产一区在线看| 婷婷社区五月天| 午夜激情一区二区| 中文字幕人妻色偷偷久久| 日韩一区二区三区视频| 国产黄大片在线观看画质优化| 91精品国产综合久久香蕉922| 不卡在线一区二区| 亚洲三级视频网站| 国产suv精品一区二区三区| 国产一区二区精彩视频| 欧美性猛交xxxx久久久| 亚洲 美腿 欧美 偷拍| 亚州av一区二区| 91精品一区| 欧美激情视频一区二区三区| 男人的天堂成人在线| 久久久久久久久久久久久久久| 亚洲视频狠狠干| 国产情侣激情自拍| 久久6精品影院| 成人线上播放| 在线日韩av永久免费观看| a91a精品视频在线观看| 日本免费福利视频| 亚洲人成伊人成综合网小说| 99久久精品国产成人一区二区| 色综合男人天堂| 婷婷综合福利| www.国产区| 国产精品久久免费看| 无码人妻一区二区三区免费| 亚洲成人激情图| 日本三级在线视频| 欧美一区二区大胆人体摄影专业网站| 五月激激激综合网色播| 免费人成在线观看视频播放| 国产在线国偷精品免费看| 国产成人无码aa精品一区| 欧美精品久久久久久久多人混战 | 国产亚洲欧美日韩俺去了| 国产一级免费观看| 亚洲精品国产精品自产a区红杏吧 亚洲精品国产精品乱码不99按摩 亚洲精品国产精品久久清纯直播 亚洲精品国产精品国自产在线 | 国产老女人精品毛片久久| 久久久精品视频在线| 日韩精品视频在线| 免费一区二区三区四区| 伊人久久在线观看| 国产呦萝稀缺另类资源| 国产日产精品一区二区三区的介绍| 日韩一卡二卡三卡国产欧美| 欧美男男tv网站在线播放| 国产精品一区二区三区精品| 日韩精品一区第一页| 精品自拍偷拍视频| 91精品久久久久久久99蜜桃| 免费在线观看黄| 国产日韩欧美亚洲一区| 免费观看日韩av| 国产成人在线网址| 亚洲国产小视频| 蜜桃视频在线网站|