日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

年轻人,看看Redisson分布式锁—可重入锁吧!太重要了

發(fā)布時(shí)間:2024/1/18 数据库 58 豆豆
生活随笔 收集整理的這篇文章主要介紹了 年轻人,看看Redisson分布式锁—可重入锁吧!太重要了 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.引言

作為后端開(kāi)發(fā),對(duì)于所謂的線程安全、高并發(fā)等一系列名詞肯定都不會(huì)陌生,相關(guān)的一些概念及技術(shù)框架是面試中的寵兒,也是工作中解決一些特定場(chǎng)景下的技術(shù)問(wèn)題的銀彈。今天我們就來(lái)聊聊這些銀彈中的其中一枚——分布式鎖,更確切的說(shuō)是分布式鎖的其中一種輪子:Redisson 的可重入鎖——基于 redis 實(shí)現(xiàn)的分布式鎖。

俗話說(shuō)得好:面試造火箭,工作擰螺絲(手動(dòng)狗頭)。分布式鎖大家應(yīng)該也都不陌生,在解決譬如分布式服務(wù)下庫(kù)存超賣等類似的場(chǎng)景下很常見(jiàn),大家也應(yīng)該都學(xué)習(xí)和使用過(guò)相關(guān)的框架,或者自己實(shí)現(xiàn)過(guò)類似的分布式鎖。但一個(gè)完備的分布式鎖實(shí)現(xiàn)應(yīng)該考慮哪些問(wèn)題,如何優(yōu)雅且全面的實(shí)現(xiàn)一個(gè)分布式鎖,以及這些實(shí)現(xiàn)背后的原理,這些可能才是我們需要考慮的。就我而言,自己造不了火箭,但學(xué)習(xí)一下火箭是怎么造的還是蠻有意思的,說(shuō)不定哪天螺絲擰多了需要自己造火箭呢。退一步講,火箭造出來(lái)的過(guò)程也是一個(gè)個(gè)螺絲擰出來(lái)的嘛。只要屠龍刀在手,一刀 999,現(xiàn)在能殺雞,將來(lái)也能宰牛, skr skr ~

2.分布式鎖概覽

2.1 鎖是干嘛的?

談到鎖,第一印象就是 Java 本身支持的一些加鎖,不管是是 synchronized 還是并發(fā)包下 Lock 的一些實(shí)現(xiàn)如 ReentrantLock,更甚一些無(wú)鎖機(jī)制譬如并發(fā)包下的一些原子類如 AtomicInteger,都在不同粒度上保證了線程安全。而所謂的線程實(shí)現(xiàn),歸根到底也就是保證共享區(qū)或者共享變量的安全而已,而聊到線程安全,立馬就能聯(lián)想到三個(gè)特性:

  • 原子性

  • 可見(jiàn)性

  • 有序性

對(duì)于 Java 語(yǔ)言本身的一些保證線程安全的實(shí)現(xiàn)如 synchronized、Lock、原子類更甚至一些在此基礎(chǔ)上的一些線程安全的集合是如何在不同粒度上保證原子性、可見(jiàn)性、有序性的這里就不拆開(kāi)了,也不是本篇要討論的。更為重要的,我們回到共享資源這個(gè)概念,對(duì)于單點(diǎn)下的應(yīng)用,為什么一提到線程安全就是三大特性,為什么這三個(gè)特性可以保證線程安全。我的通俗理解是:

  • 對(duì)于共享資源的加鎖或者修改(原子類)是原子的,不可拆分的,那么加鎖或者修改本身就要么成功要么失敗,不會(huì)有中間過(guò)程的誤判

  • 而可見(jiàn)性是保證共享資源對(duì)所有線程可見(jiàn),這個(gè)也沒(méi)什么好解釋的,只有對(duì)共享資源的任何修改都可感知,才不會(huì)在不同線程下決策不同

  • 有序性的前提是多線程,單線程下的指令重排不會(huì)改變串行結(jié)果,但多線程下的指令重排下對(duì)共享區(qū)域的修改會(huì)相互干擾,所以保證多線程的有序性也是必須的

加鎖是手段,保證共享資源的安全才是目的,單點(diǎn)下 Java 是通過(guò)原子性、可見(jiàn)性、有序性來(lái)實(shí)現(xiàn)的。

2.2 分布式鎖需要考慮什么?

前面我們廢話了一堆,可以看出來(lái)鎖的目的:保證共享資源的安全。現(xiàn)在不考慮單點(diǎn)鎖還是分布式鎖:我們考慮兩個(gè)問(wèn)題:

  • 共享資源在哪里?

  • 是否保證了原子性、有序性、可見(jiàn)性加鎖就一定是完備的

對(duì)于第一個(gè)問(wèn)題,在單點(diǎn)情況下,我們可以共享資源是一個(gè)實(shí)例變量或者是一段對(duì)資源進(jìn)行操作的代碼,這些資源在不同線程下共享,而這里的線程都是在一個(gè) JVM 進(jìn)程中。那么如果是分布式系統(tǒng)呢?舉個(gè)例子:某個(gè)商品的總庫(kù)存、某個(gè)優(yōu)惠券批次的總數(shù)量,這些是共享資源嗎?當(dāng)然是,只是這里共享這些資源的對(duì)象從一個(gè) JVM 進(jìn)程下的多個(gè)線程變成了多個(gè)服務(wù)節(jié)點(diǎn)下的多個(gè) JVM 進(jìn)程下的多個(gè)線程而已。下面通過(guò)兩張圖我們可以對(duì)比一下:

1.單進(jìn)程下共享資源

2.分布式系統(tǒng)下共享資源

可以看出來(lái),在單個(gè) JVM 進(jìn)程中,共享資源只是在同一進(jìn)程下的不同線程共享,不管共享資源是實(shí)例變量、代碼段、或者數(shù)據(jù)庫(kù)的資源,所以我們可以通過(guò)單點(diǎn)下的原子性、有序性、可見(jiàn)性來(lái)保證共享資源的安全。

而在分布式系統(tǒng)下,共享資源的范圍就擴(kuò)大到了多臺(tái)機(jī)器下的多個(gè)進(jìn)程中的多個(gè)線程中。那么再看一下第二個(gè)問(wèn)題,在分布式系統(tǒng)下原子性、有序性、可見(jiàn)性還管用嗎?或者說(shuō)這三個(gè)特性在分布式系統(tǒng)下還有用嗎?我的理解是:這三個(gè)特性是依然存在的,只是針對(duì)的對(duì)象和范圍發(fā)生了變化。在單點(diǎn)情況下,任何共享資源都共存于同一個(gè) JVM 進(jìn)程中,共享資源狀態(tài)同步的范圍也只是在線程的工作內(nèi)存和主內(nèi)存之間而已,或者說(shuō)共享資源的最終狀態(tài)在主內(nèi)存,而其變化狀態(tài)發(fā)生在單點(diǎn)下的多線程的各自工作內(nèi)存中,這三個(gè)特性所在的容器也只是單個(gè) JVM 進(jìn)程而已。而分布式系統(tǒng)下,共享資源的狀態(tài)同步范圍擴(kuò)大了多臺(tái)機(jī)器各自的進(jìn)程(更細(xì)致一點(diǎn)是各個(gè)進(jìn)程中不同的線程之間),共享資源的最終狀態(tài)最終一定要依賴于 JVM 進(jìn)程外的第三方,比如數(shù)據(jù)庫(kù)、任意形式的服務(wù)器等等,而共享資源的狀態(tài)變化發(fā)生在多個(gè)進(jìn)程下的多個(gè)線程,因此分布式下的共享資源的安全保證,不僅僅是在線程之間,也在進(jìn)程之間。

2.3 分布式鎖要提供的最基礎(chǔ)的能力

當(dāng)然,前面一段理解可能有點(diǎn)過(guò)于冗繁,也可以說(shuō):分布式系統(tǒng)下整個(gè)服務(wù)集群是一個(gè)大容器,狀態(tài)的同步范圍在集群服務(wù)所有的線程之間,只是這些線程的交互不再只是通過(guò)單機(jī)的緩存一致性協(xié)議(如 MESI 協(xié)議等),而是擴(kuò)大到了端到端的通信即網(wǎng)絡(luò)交互,而共享資源的直接宿主也在第三方譬如其他服務(wù)、數(shù)據(jù)庫(kù)等。那這時(shí)候這三個(gè)特性的范圍如果也相應(yīng)的擴(kuò)大到集群線程之間,那共享資源的安全自然也是能夠保證的。當(dāng)然,這么說(shuō)可能不太嚴(yán)謹(jǐn),因?yàn)槲乙矝](méi)在相關(guān)的資料上看到過(guò)有人在分布式系統(tǒng)之間使用原子性、有序性、可見(jiàn)性來(lái)說(shuō)明分布式系統(tǒng)的多線程安全,這是只是借鑒思想,大家如果感覺(jué)名詞不夠?qū)I(yè),輕噴。

前面簡(jiǎn)單討論了分布式系統(tǒng)下的共享資源以及保證線程安全的三個(gè)特性,我們考慮一下如何才能在分布式系統(tǒng)這個(gè)大容器下保證這三個(gè)特性,或者說(shuō)如何在分布式系統(tǒng)下加鎖?首先,鎖的共享范圍必然是要和要保護(hù)的資源一致的,在單點(diǎn)下共享資源就在單個(gè) JVM 進(jìn)程中,那么鎖依靠 JVM 中的一些手段也就足夠了,比如 synchronized、Lock、原子類(當(dāng)然這個(gè)是無(wú)鎖的)等。而在分布式系統(tǒng)下,鎖的生存范圍必然是和集群節(jié)點(diǎn)平級(jí)的,要不然各個(gè)節(jié)點(diǎn)各自用自己的鎖,大家對(duì)于對(duì)方的鎖根本不認(rèn)識(shí)也無(wú)法交流那豈不是亂掉了。所以分布式鎖必須獨(dú)立于各個(gè)節(jié)點(diǎn)之外,比如借助 redis、zookeeper 等實(shí)現(xiàn),當(dāng)然,本篇我們討論的是 redis 的分布式鎖,但我認(rèn)為前面的思想是通用的,哪怕不用 redis、zookeeper 也可以實(shí)現(xiàn),只是實(shí)現(xiàn)方式、效率等方面有所差異。即分布式鎖最起碼要實(shí)現(xiàn)進(jìn)程間共享(這里的共享是指在不同進(jìn)程間是一套,而不是說(shuō)可以同時(shí)持有),并且能夠保證共享資源的原子性、有序性、可見(jiàn)性。

這里多說(shuō)一點(diǎn),由于分布式鎖宿主在 JVM 進(jìn)程之間,各個(gè)進(jìn)程加鎖以及同步是通過(guò)端到端的進(jìn)程通信,那么此時(shí)分布式系統(tǒng)下的可見(jiàn)性、有序性是自然滿足的。首先可見(jiàn)性很好理解,因?yàn)楣蚕碣Y源的獲取本身就是服務(wù)與服務(wù)間的通信,可見(jiàn)性的粒度也應(yīng)該在服務(wù),只要共享資源發(fā)生改變,任何一個(gè)服務(wù)都可以查詢到(不要說(shuō)事務(wù)什么的,我覺(jué)得這里共享資源的狀態(tài)同步應(yīng)該是在事務(wù)的上層來(lái)看)。而有序性也是在分布式鎖的前提下,不同服務(wù)之間對(duì)于共享資源的變更也變成了時(shí)間上是串行的,那么也自然滿足的,當(dāng)然這里會(huì)有性能的犧牲。那么原子性呢?我理解這里的原子性是靠分布式鎖的獲取等來(lái)保證的,只要加鎖、釋放等是原子的,那么鎖所保護(hù)的資源(或操作)對(duì)于同級(jí)的操作就是一個(gè)原子的。

2.4 分布式鎖還要考慮什么?

前面討論了分布式鎖怎么保證共享資源的安全,但是由于分布式鎖宿主在譬如 redis、zookeeper 等中間件中,加鎖、釋放、鎖續(xù)期等也是在進(jìn)程與 redis 之間通信,那么就引出了一些單點(diǎn)加鎖不存在的問(wèn)題:那就是服務(wù)如果宕機(jī)了怎么辦?或者加鎖是有時(shí)間的,如果時(shí)間過(guò)了持有鎖的任務(wù)還沒(méi)有完成怎么辦?這時(shí)候看起來(lái)就像下圖可能出現(xiàn)的情況

出現(xiàn)這些問(wèn)題的原因是雖然我們將分布式系統(tǒng)和鎖的宿主看作一個(gè)大的通信系統(tǒng),但其卻是離散的,離散的節(jié)點(diǎn)自身可能存活、死亡等,在單個(gè)離散節(jié)點(diǎn)不存在時(shí),其持有的鎖卻可能仍在另外一個(gè)離散節(jié)點(diǎn)存在(這里指的是依靠 redis 實(shí)現(xiàn)的分布式鎖),那么對(duì)于其他節(jié)點(diǎn)來(lái)說(shuō)鎖也就永遠(yuǎn)無(wú)法獲取了。反過(guò)來(lái),如果持有鎖的離散的服務(wù)節(jié)點(diǎn)對(duì)于共享資源的操作還沒(méi)有完成,Redis 由于鎖的時(shí)間到期而釋放鎖,那么其他的服務(wù)節(jié)點(diǎn)就可以獲取到本不該獲取的鎖了,這時(shí)候共享資源必然是不安全的。而這些在單個(gè)進(jìn)程中的鎖不會(huì)存在,因?yàn)閱芜M(jìn)程下的鎖、線程、資源都在一個(gè)容器即 JVM 進(jìn)程中,JVM 進(jìn)程死掉的話這些也就一起死掉了,自然也不會(huì)存在之前說(shuō)的問(wèn)題。可見(jiàn),分布式鎖不僅要維護(hù)共享資源的安全,還要維護(hù)鎖自身在不同進(jìn)程下的安全問(wèn)題。

3. redis 分布式鎖的一種實(shí)現(xiàn)—— Redisson 的可重入鎖

3.1 如何使用 Redisson 的分布式鎖

寫(xiě)到這里,我覺(jué)得前面的文字鋪墊的太多了,代碼和圖片太少了,但對(duì)我個(gè)人而言我覺(jué)得會(huì)使用分布式鎖沒(méi)有什么太大的意義,所以我前面還是堅(jiān)持寫(xiě)了一些冗繁的廢話。那么,我們先看一下如何最簡(jiǎn)單的使用 Redisson 的分布式鎖吧,畢竟 Talk is cheap,show me the code !

@Autowired private RedissonClient redisson;private static final String LOCK_PREFIX = "my:lock:";@GetMapping("redis/lock/{seq}") public String lock(@PathVariable String seq) {RLock lock = redisson.getLock(LOCK_PREFIX + seq);try {boolean lockSuccess = lock.tryLock(5, TimeUnit.SECONDS);if (lockSuccess) {System.out.println("get lock success");} else {System.out.println("get lock fail");}TimeUnit.SECONDS.sleep(15);} catch (InterruptedException e) {e.printStackTrace();return seq + " mission dead";} finally {lock.unlock();}return seq + " mission completed"; }@Bean public RedissonClient redissonClient() {Config config = new Config();// 單點(diǎn)模式config.useSingleServer().setAddress("redis://127.0.0.1:6379");// 集群模式/*config.useClusterServers().addNodeAddress("redis://127.0.0.1:7000").addNodeAddress("redis://127.0.0.1:7001").addNodeAddress("redis://127.0.0.1:7002").addNodeAddress("redis://127.0.0.1:7003").addNodeAddress("redis://127.0.0.1:7004").addNodeAddress("redis://127.0.0.1:7005");*/return Redisson.create(config); }

Redisson 實(shí)現(xiàn)的分布式鎖的使用就是這么簡(jiǎn)單,這個(gè)也沒(méi)什么好說(shuō)的,我們公司的不少服務(wù)應(yīng)該也都有過(guò)使用,就我接觸到的有兌換券、優(yōu)惠券等。下面我們就基于這段簡(jiǎn)單的代碼來(lái)理解一下 Redisson 的分布式鎖是如何實(shí)現(xiàn)的。

3.1 RedissonClient:同 redis 通信的組件

public class Redisson implements RedissonClient {static {RedissonObjectFactory.warmUp();RedissonReference.warmUp();}protected final QueueTransferService queueTransferService = new QueueTransferService();protected final EvictionScheduler evictionScheduler;protected final ConnectionManager connectionManager;protected final ConcurrentMap<Class<?>, Class<?>> liveObjectClassCache = PlatformDependent.newConcurrentHashMap();protected final Config config;protected final SemaphorePubSub semaphorePubSub = new SemaphorePubSub();protected final ConcurrentMap<String, ResponseEntry> responses = PlatformDependent.newConcurrentHashMap();protected Redisson(Config config) {this.config = config;Config configCopy = new Config(config);connectionManager = ConfigSupport.createConnectionManager(configCopy);evictionScheduler = new EvictionScheduler(connectionManager.getCommandExecutor());}public EvictionScheduler getEvictionScheduler() {return evictionScheduler;}public CommandExecutor getCommandExecutor() {return connectionManager.getCommandExecutor();}public ConnectionManager getConnectionManager() {return connectionManager;}/*** Create sync/async Redisson instance with default config** @return Redisson instance*/public static RedissonClient create() {Config config = new Config();config.useSingleServer().setTimeout(1000000).setAddress("redis://127.0.0.1:6379"); // config.useMasterSlaveConnection().setMasterAddress("127.0.0.1:6379").addSlaveAddress("127.0.0.1:6389").addSlaveAddress("127.0.0.1:6399"); // config.useSentinelConnection().setMasterName("mymaster").addSentinelAddress("127.0.0.1:26389", "127.0.0.1:26379"); // config.useClusterServers().addNodeAddress("127.0.0.1:7000");return create(config);}/*** Create sync/async Redisson instance with provided config** @param config for Redisson* @return Redisson instance*/public static RedissonClient create(Config config) {Redisson redisson = new Redisson(config);if (config.isReferenceEnabled()) {redisson.enableRedissonReferenceSupport();}return redisson;}@Overridepublic RLock getLock(String name) {return new RedissonLock(connectionManager.getCommandExecutor(), name);}// 省略巴拉巴拉 }

不得不說(shuō),這段代碼復(fù)制粘貼的是有點(diǎn)臭長(zhǎng)啊,畢竟 CV 工程師,哈哈。總結(jié)起來(lái)就是一句話:Redisson 類是 RedissonClient 的實(shí)現(xiàn),封裝了一些配置、同 redis 的連接管理、一些定時(shí)任務(wù)、發(fā)布訂閱組件等,另外提供一些獲取 Redisson 基于 Redis 實(shí)現(xiàn)的分布式鎖、分布式集合、分布式信號(hào)量等接口方法,比如我們的分布式鎖-可重入鎖。

public RLock getLock(String name) {return new RedissonLock(connectionManager.getCommandExecutor(), name); }

而這里實(shí)際上我們獲取到的只是 Redisson 封裝好的對(duì)分布式鎖的抽象的對(duì)象而已,并不是真正的就執(zhí)行加鎖操作了。而加鎖、釋放鎖等就是基于 Redisson 的鎖接口 RLock 來(lái)做的,而本文討論的可重入鎖則 RedissonLock 是其中一種實(shí)現(xiàn)。

3.2 RedissonLock 是如何加鎖的

下面我們就以 demo 的代碼為入口看一下 RedissonLock 是如何加鎖的:

@Override public boolean tryLock(long waitTime, TimeUnit unit) throws InterruptedException {return tryLock(waitTime, -1, unit); }

通過(guò) demo 中使用的 tryLock(long waitTime, TimeUnit unit) 我們可以看出來(lái),真正調(diào)用的是下面這個(gè)方法:

@Override public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {long time = unit.toMillis(waitTime);long current = System.currentTimeMillis();long threadId = Thread.currentThread().getId();Long ttl = tryAcquire(waitTime, leaseTime, unit, threadId);// 加鎖成功 返回null 否則返回的是該鎖將要過(guò)期的剩余時(shí)間// lock acquiredif (ttl == null) {return true;}time -= System.currentTimeMillis() - current;// 未獲取到鎖,且第一次嘗試獲取鎖花費(fèi)時(shí)間超過(guò)了預(yù)設(shè)等待時(shí)間,則獲取鎖失敗,不再等待if (time <= 0) {acquireFailed(waitTime, unit, threadId);return false;}current = System.currentTimeMillis();RFuture<RedissonLockEntry> subscribeFuture = subscribe(threadId);if (!subscribeFuture.await(time, TimeUnit.MILLISECONDS)) {if (!subscribeFuture.cancel(false)) {subscribeFuture.onComplete((res, e) -> {if (e == null) {unsubscribe(subscribeFuture, threadId);}});}acquireFailed(waitTime, unit, threadId);return false;}try {time -= System.currentTimeMillis() - current;if (time <= 0) {acquireFailed(waitTime, unit, threadId);return false;}while (true) {long currentTime = System.currentTimeMillis();ttl = tryAcquire(waitTime, leaseTime, unit, threadId);// lock acquiredif (ttl == null) {return true;}time -= System.currentTimeMillis() - currentTime;if (time <= 0) {acquireFailed(waitTime, unit, threadId);return false;}// waiting for messagecurrentTime = System.currentTimeMillis();if (ttl >= 0 && ttl < time) {subscribeFuture.getNow().getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);} else {subscribeFuture.getNow().getLatch().tryAcquire(time, TimeUnit.MILLISECONDS);}time -= System.currentTimeMillis() - currentTime;if (time <= 0) {acquireFailed(waitTime, unit, threadId);return false;}}} finally {unsubscribe(subscribeFuture, threadId);} // return get(tryLockAsync(waitTime, leaseTime, unit)); }

而關(guān)于這段代碼呢,我們先忽略其他邏輯,重點(diǎn)看這一行:

Long ttl = tryAcquire(leaseTime, unit, threadId);

這一行第一次嘗試加鎖,接著往下看:

private Long tryAcquire(long leaseTime, TimeUnit unit, long threadId) {return get(tryAcquireAsync(leaseTime, unit, threadId)); }private <T> RFuture<Long> tryAcquireAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId) {// 如果自己設(shè)置了鎖釋放時(shí)間,則獲取鎖后直接返回,且不會(huì)設(shè)置定時(shí)刷新的邏輯(上層方法沒(méi)有設(shè)置定時(shí)任務(wù)),則獲取到鎖后超過(guò)設(shè)定的事件后自動(dòng)釋放// 或者在設(shè)定時(shí)間內(nèi)手動(dòng)調(diào)用釋放鎖if (leaseTime != -1) {return tryLockInnerAsync(waitTime, leaseTime, unit, threadId, RedisCommands.EVAL_LONG);}RFuture<Long> ttlRemainingFuture = tryLockInnerAsync(waitTime, internalLockLeaseTime,TimeUnit.MILLISECONDS, threadId, RedisCommands.EVAL_LONG);ttlRemainingFuture.onComplete((ttlRemaining, e) -> {// 未獲取到鎖if (e != null) {return;}// 獲取到鎖,開(kāi)啟自動(dòng)延期鎖的定時(shí)任務(wù)// lock acquiredif (ttlRemaining == null) {scheduleExpirationRenewal(threadId);}});return ttlRemainingFuture; }

可以看出來(lái)對(duì)于 leaseTime != -1 的判斷會(huì)走兩種方式:真正的加鎖是通過(guò) tryLockInnerAsync(long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) 這個(gè)方法來(lái)做的,而當(dāng) leaseTime != -1 時(shí),直接返回加鎖結(jié)果了,而當(dāng) leaseTime = -1 時(shí),在返回加鎖結(jié)果之前,會(huì)監(jiān)聽(tīng)加鎖的結(jié)果:如果加鎖成功了還會(huì)開(kāi)啟一個(gè)自動(dòng)延期鎖的定時(shí)任務(wù)。而這個(gè) leaseTime 指的就是加鎖成功后鎖的默認(rèn)持有時(shí)間。當(dāng)我們不指定 leaseTime 時(shí),默認(rèn)的鎖持有時(shí)間是 30 秒(這個(gè)時(shí)間叫作看門狗 - lockWatchdogTimeout),并且每 10 秒(30/3)去確認(rèn)一下鎖的狀態(tài):如果鎖仍未被釋放,則重新設(shè)置鎖的過(guò)期時(shí)間為 30 秒(當(dāng)然,持有鎖的服務(wù)宕機(jī)后在 30 秒后鎖會(huì)自動(dòng)釋放,這個(gè)我們后面再說(shuō))。而當(dāng)我們指定 leaseTime 時(shí),我們可以看出來(lái)前面的代碼不會(huì)走到定時(shí)續(xù)期鎖的邏輯,這時(shí)表示:成功獲取到鎖后,在 leaseTime 后,如果鎖仍沒(méi)有被服務(wù)主動(dòng)釋放,鎖將自動(dòng)過(guò)期,而不會(huì)管持有鎖的線程有沒(méi)有完成對(duì)應(yīng)的操作,相當(dāng)于在持有所得服務(wù)執(zhí)行了比較耗時(shí)的任務(wù)且未完成時(shí),這時(shí)鎖已經(jīng)被釋放,這時(shí)候自然也是不安全的。上面兩段代碼的流程如下:

從前面的流程圖我們可以看出,RedissonLock.tryLock(long waitTime, long leaseTime, TimeUnit unit) 是對(duì)于 waitTime, leaseTime 入?yún)?huì)產(chǎn)生不同的行為,這也是 RedissonLock 嘗試加鎖相對(duì)最完整的一個(gè)鏈路,其他方法譬如我們直接使用的 tryLock(long waitTime, TimeUnit unit) 也只是復(fù)用了其中一個(gè)邏輯分支。

3.3 RedissonLock分布式鎖的數(shù)據(jù)結(jié)構(gòu)與加鎖原理

前面一小節(jié)我們看到了 RedissonLock 完整的加鎖鏈路,那么分布式鎖在 Redis 是如何實(shí)現(xiàn)的呢?怎么判斷加鎖失敗以及鎖的剩余時(shí)間呢?現(xiàn)在我們就來(lái)看看這個(gè)。

if (leaseTime != -1) {return tryLockInnerAsync(waitTime, leaseTime, unit, threadId, RedisCommands.EVAL_LONG);}RFuture<Long> ttlRemainingFuture = tryLockInnerAsync(waitTime, internalLockLeaseTime,TimeUnit.MILLISECONDS, threadId, RedisCommands.EVAL_LONG); // 巴拉巴拉 }

通過(guò)前面的代碼我們可以看出來(lái)真正執(zhí)行加鎖以及返回加鎖結(jié)果是調(diào)用了下面的方法:

<T> RFuture<T> tryLockInnerAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) {internalLockLeaseTime = unit.toMillis(leaseTime);// 鎖不存在,加鎖成功,設(shè)置hash數(shù)據(jù)結(jié)構(gòu)鎖: 鎖名 -> 加鎖線程:id -> 加鎖次數(shù)(1)// 鎖存在且是本線程的鎖 加鎖次數(shù)增加:鎖名 -> 加鎖線程:id -> 加鎖次數(shù)+1// 鎖存在且不是本線程的鎖 加鎖失敗 返回鎖剩余過(guò)期時(shí)間return evalWriteAsync(getName(), LongCodec.INSTANCE, command,"if (redis.call('exists', KEYS[1]) == 0) then " +"redis.call('hincrby', KEYS[1], ARGV[2], 1); " +"redis.call('pexpire', KEYS[1], ARGV[1]); " +"return nil; " +"end; " +"if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +"redis.call('hincrby', KEYS[1], ARGV[2], 1); " +"redis.call('pexpire', KEYS[1], ARGV[1]); " +"return nil; " +"end; " +"return redis.call('pttl', KEYS[1]);",Collections.singletonList(getName()), internalLockLeaseTime, getLockName(threadId)); }

到了這里,我們才能看到 RedissonLock 的加鎖(僅僅指執(zhí)行加鎖這一動(dòng)作)以及鎖在 Redis 中的數(shù)據(jù)結(jié)構(gòu)的廬山真面目:可以看出來(lái)上面是執(zhí)行了一段 lua 腳本,這段 lua 腳 本是會(huì)涉及到多個(gè)判斷以及數(shù)據(jù)修改的,這個(gè)時(shí)候就可以回到我們說(shuō)的關(guān)于加鎖的原子性問(wèn)題了。先不看這段加鎖的邏輯,只考慮加鎖過(guò)程涉及到多個(gè)判斷以及操作時(shí),那么那些動(dòng)作必須是原子的,要么同時(shí)成功要么同時(shí)失敗,而 RedissonLock 實(shí)現(xiàn)加鎖過(guò)程的原子性就是借助了 lua 腳本(鎖延期等也會(huì)使用 lua 腳本)。那么我們看一下這段 lua 腳本的含義吧:結(jié)合注釋,Redisson 實(shí)現(xiàn)的可重入鎖的數(shù)據(jù)結(jié)構(gòu)使用了 Redis中 的 hash 對(duì)象數(shù)據(jù)類型來(lái)實(shí)現(xiàn),其在 Redis 中大概長(zhǎng)這個(gè)樣子:

從上面這張圖我們可以看出來(lái) Redisson 的分布式鎖在 Redis 中的 hash 數(shù)據(jù)結(jié)構(gòu):{鎖名}:{uuid:threadId}:{count},另外對(duì)于已經(jīng)存在的健值對(duì)初始化過(guò)期時(shí)間為 30 秒。結(jié)合前面的加鎖流程圖,我們就可以看出來(lái) Redisson 分布式鎖是如何實(shí)現(xiàn)加鎖的原子性,以下操作是一個(gè)原子操作:
  • 某一個(gè)節(jié)點(diǎn)下的線程加鎖首先判斷該線程對(duì)于的 hash 鍵是否存在

  • 若不存在(鎖未被持有),則將鎖的鍵設(shè)置為線程 id 對(duì)應(yīng)的唯一標(biāo)識(shí),值為 1 (第一次加鎖),返回空表示加鎖成功

  • 鎖存在且對(duì)應(yīng)的是本線程,說(shuō)明之前加鎖的線程為同一個(gè),則將 hash 值 1 (加鎖次數(shù),可重入),另外將該鎖對(duì)應(yīng)的存活時(shí)間重新設(shè)置,返回空表示加鎖成功

  • 鎖存在但鍵對(duì)應(yīng)的不是當(dāng)前線程,說(shuō)明持有鎖的是其他線程,返回鎖剩余的過(guò)期時(shí)間表示加鎖失敗

到這里,Redisson 的分布式鎖加鎖的流程以及鎖在 Redis 中的數(shù)據(jù)結(jié)構(gòu)已經(jīng)清楚了,這時(shí)候我們可以對(duì)比一下 Java 自身實(shí)現(xiàn)的可重入鎖 ReentrantLock。對(duì)于 ReentrantLock,甚至更多的線程安全組件如 Semaphore、CountDownLatch 等,其底層的實(shí)現(xiàn)都依賴于 AQS(AbstractQueuedSynchronizer),而 AQS 本身是一個(gè)隊(duì)列,隊(duì)列中的節(jié)點(diǎn) Node 同樣也是封裝了線程的對(duì)象,只是 AQS 是本地單節(jié)點(diǎn)的,Redis 卻是分布式的可以被任何 JVM 共享。另外 AQS 中還封裝了一個(gè) int 類型的狀態(tài)變量 state:

/*** The synchronization state.*/ private volatile int state;

當(dāng)涉及到具體的實(shí)現(xiàn)時(shí),state 有不同的含義,對(duì) ReentrantLock 來(lái)說(shuō) state 就是可重入鎖的加鎖次數(shù),對(duì) Semaphore 來(lái)說(shuō) state 就是信號(hào)量,對(duì) CountDownLatch 來(lái)說(shuō)就是計(jì)數(shù)量。可以看出來(lái), Java 的 AQS 一些抽象和 Redisson 實(shí)現(xiàn)的分布式鎖是可以類比的,比如 thread 標(biāo)識(shí)對(duì)應(yīng)的封裝,加鎖次數(shù)等。只是 AQS 的實(shí)現(xiàn)原子操作一般是基于原子類的 CAS,而 Redisson 實(shí)現(xiàn)原子操作是基于 Redis 的 lua 腳本。另外 AQS 實(shí)現(xiàn)隊(duì)列節(jié)點(diǎn)狀態(tài)同步是基于隊(duì)列本身可以遍歷的特性以及節(jié)點(diǎn)中的幾種狀態(tài)(這里不再贅述),而 Redisson 不同線程之間阻塞同步是基于發(fā)布訂閱(后面會(huì)提到)。可以得出:本地鎖和分布式鎖很多概念和思想是相似的,甚至其數(shù)據(jù)結(jié)構(gòu)以及目標(biāo)都是可類比的,只是分布式鎖對(duì)本地鎖的對(duì)象、范圍、通信方式基于服務(wù)之間通信進(jìn)行了實(shí)現(xiàn)。關(guān)于 AQS 的原理這里不再展開(kāi),大家可以參考 JDK 的源碼。

3.3 鎖的自動(dòng)續(xù)期

前面我們從 Redisson 加鎖為入口,分析了加鎖的整體流程并詳細(xì)看了加鎖時(shí)的細(xì)節(jié)以及數(shù)據(jù)結(jié)構(gòu),現(xiàn)在我們看一下 Redisson 分布式鎖是如何自動(dòng)續(xù)期的。前面我們已經(jīng)提到了當(dāng)?shù)谝淮渭渔i成功時(shí)會(huì)開(kāi)啟自動(dòng)續(xù)期的定時(shí)任務(wù),對(duì)于的代碼入口即為:

// 獲取到鎖,開(kāi)啟自動(dòng)延期鎖的定時(shí)任務(wù)// lock acquiredif (ttlRemaining == null) {scheduleExpirationRenewal(threadId);}

繼續(xù)往下看,進(jìn)入如下代碼:

private void scheduleExpirationRenewal(long threadId) {ExpirationEntry entry = new ExpirationEntry();ExpirationEntry oldEntry = EXPIRATION_RENEWAL_MAP.putIfAbsent(getEntryName(), entry);if (oldEntry != null) {// 表示不是第一次加鎖 則加鎖次數(shù)加 1 不會(huì)再開(kāi)啟續(xù)期鎖 因?yàn)榈谝淮渭渔i時(shí)調(diào)用 scheduleExpirationRenewal(long threadId) 會(huì)進(jìn)入// else 會(huì)開(kāi)啟 renewExpiration()oldEntry.addThreadId(threadId);} else {// 在加鎖時(shí)第一次調(diào)用 開(kāi)啟自動(dòng)續(xù)期(定時(shí)重設(shè)鎖的過(guò)期時(shí)間)entry.addThreadId(threadId);renewExpiration();} }

ExpirationEntry 封裝了定時(shí)任務(wù)對(duì)應(yīng)的線程對(duì)象,結(jié)合注釋這一段也不必展開(kāi),我們繼續(xù)往下看真正開(kāi)啟續(xù)期的方法 renewExpiration():

private void renewExpiration() {ExpirationEntry ee = EXPIRATION_RENEWAL_MAP.get(getEntryName());// 鎖已經(jīng)不存在了直接返回if (ee == null) {return;}Timeout task = commandExecutor.getConnectionManager().newTimeout(new TimerTask() {@Overridepublic void run(Timeout timeout) throws Exception {ExpirationEntry ent = EXPIRATION_RENEWAL_MAP.get(getEntryName());if (ent == null) {return;}Long threadId = ent.getFirstThreadId();if (threadId == null) {return;}RFuture<Boolean> future = renewExpirationAsync(threadId);// 這里監(jiān)聽(tīng)續(xù)期 成功后遞歸調(diào)用(十秒后再次重復(fù))future.onComplete((res, e) -> {if (e != null) {log.error("Can't update lock " + getName() + " expiration", e);EXPIRATION_RENEWAL_MAP.remove(getEntryName());return;}if (res) {// reschedule itselfrenewExpiration();}});}// 10 秒續(xù)期一次(如果還持有鎖) 30000/3}, internalLockLeaseTime / 3, TimeUnit.MILLISECONDS);ee.setTimeout(task); }

可以看出來(lái)鎖自動(dòng)續(xù)期的流程為:

  • 若鎖已經(jīng)不存在了(比如手動(dòng)釋放了鎖),直接返回

  • 若鎖仍存在,調(diào)用 Redis 異步設(shè)置鎖的過(guò)期時(shí)間 renewExpirationAsync(threadId),同時(shí)監(jiān)聽(tīng)續(xù)期結(jié)果

  • 若續(xù)期成功,則遞歸調(diào)用 renewExpiration(),否則異常返回

  • 以上過(guò)程每 10 秒重復(fù)一次 (internalLockLeaseTime / 3)

  • 然后我們看一下調(diào)用 Redis 對(duì)鎖進(jìn)行續(xù)期的過(guò)程:

    protected RFuture<Boolean> renewExpirationAsync(long threadId) {// 當(dāng)前線程持有的鎖還存在 重新設(shè)置鎖的過(guò)期時(shí)間(默認(rèn) 30 秒)// 否則失敗return evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,"if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +"redis.call('pexpire', KEYS[1], ARGV[1]); " +"return 1; " +"end; " +"return 0;",Collections.singletonList(getName()),internalLockLeaseTime, getLockName(threadId)); }

    這里同樣使用 lua 腳本來(lái)執(zhí)行了一段原子操作:

    • 判斷當(dāng)前線程對(duì)應(yīng)的鎖是否存在,若存在則重新設(shè)置鎖的過(guò)期時(shí)間(默認(rèn)為 30 秒),返回 true

    • 否則返回 false

    3.4 鎖的手動(dòng)釋放

    至此,Redisson 的加鎖、自動(dòng)續(xù)期我們已經(jīng)討論過(guò)了,現(xiàn)在看一下鎖的手動(dòng)釋放, 其入口為:

    public void unlock() {try {get(unlockAsync(Thread.currentThread().getId()));} catch (RedisException e) {if (e.getCause() instanceof IllegalMonitorStateException) {throw (IllegalMonitorStateException)e.getCause();} else {throw e;}}}

    接著看底層實(shí)現(xiàn) unlockAsync(final long threadId):

    public RFuture<Void> unlockAsync(long threadId) {RPromise<Void> result = new RedissonPromise<Void>();// 釋放鎖RFuture<Boolean> future = unlockInnerAsync(threadId);// 監(jiān)聽(tīng)釋放鎖結(jié)果future.onComplete((opStatus, e) -> {// 取消自動(dòng)續(xù)期cancelExpirationRenewal(threadId);if (e != null) {result.tryFailure(e);return;}if (opStatus == null) {IllegalMonitorStateException cause = new IllegalMonitorStateException("attempt to unlock lock, not locked by current thread by node id: "+ id + " thread-id: " + threadId);result.tryFailure(cause);return;}result.trySuccess(null);});return result; }

    可以看出來(lái),釋放鎖會(huì)執(zhí)行以下操作:

    • 調(diào)用 Redis 釋放鎖

    • 監(jiān)聽(tīng)釋放鎖結(jié)果,取消自動(dòng)續(xù)期

    然后看一下真正釋放鎖的操作:

    protected RFuture<Boolean> unlockInnerAsync(long threadId) {// 若鎖不存在 返回// 若鎖存在 加鎖次數(shù) -1// 若加鎖次數(shù)仍不等于 0 (可重入),重新設(shè)置鎖的過(guò)期時(shí)間,返回// 若加鎖次數(shù)減為 0,刪除鎖,同步發(fā)布釋放鎖事件,返回return evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,"if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then " +"return nil;" +"end; " +"local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1); " +"if (counter > 0) then " +"redis.call('pexpire', KEYS[1], ARGV[2]); " +"return 0; " +"else " +"redis.call('del', KEYS[1]); " +"redis.call('publish', KEYS[2], ARGV[1]); " +"return 1; " +"end; " +"return nil;",Arrays.asList(getName(), getChannelName()), LockPubSub.UNLOCK_MESSAGE, internalLockLeaseTime, getLockName(threadId)); }

    上面這段 lua 腳本的含義基本與注釋一致,這里不再贅述。至此,鎖會(huì)被原子性的釋放。

    3.5 加鎖等待

    討論了加鎖成功、鎖自動(dòng)續(xù)期、鎖釋放后,我們?cè)賮?lái)看一下加鎖等待。前面加鎖的代碼中,我們可以看到,若制定了加鎖的等待時(shí)間 waitTime 時(shí),若鎖已經(jīng)被占有,加鎖會(huì)失敗并返回鎖剩余的過(guò)期時(shí)間,然后循環(huán)嘗試加鎖,對(duì)應(yīng)以下代碼:

    current = System.currentTimeMillis();RFuture<RedissonLockEntry> subscribeFuture = subscribe(threadId);if (!subscribeFuture.await(time, TimeUnit.MILLISECONDS)) {if (!subscribeFuture.cancel(false)) {subscribeFuture.onComplete((res, e) -> {if (e == null) {unsubscribe(subscribeFuture, threadId);}});}acquireFailed(waitTime, unit, threadId);return false;}try {time -= System.currentTimeMillis() - current;if (time <= 0) {acquireFailed(waitTime, unit, threadId);return false;}// 等待鎖釋放 循環(huán)獲取鎖while (true) {long currentTime = System.currentTimeMillis();ttl = tryAcquire(waitTime, leaseTime, unit, threadId);// lock acquiredif (ttl == null) {return true;}time -= System.currentTimeMillis() - currentTime;if (time <= 0) {acquireFailed(waitTime, unit, threadId);return false;}// waiting for messagecurrentTime = System.currentTimeMillis();if (ttl >= 0 && ttl < time) {subscribeFuture.getNow().getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);} else {subscribeFuture.getNow().getLatch().tryAcquire(time, TimeUnit.MILLISECONDS);}time -= System.currentTimeMillis() - currentTime;if (time <= 0) {acquireFailed(waitTime, unit, threadId);return false;}}} finally {unsubscribe(subscribeFuture, threadId);}

    在上面的 while 循環(huán)中,我們可以看出來(lái),每次循環(huán)都會(huì)調(diào)用

    ttl = tryAcquire(waitTime, leaseTime, unit, threadId);

    這里就回到了我們之前分析的加鎖流程,不再贅述。整個(gè)加鎖等待流程如下:

    • 如果加鎖成功,返回成功

    • 加鎖失敗,基于發(fā)布訂閱(基于 Semaphore )阻塞,收到鎖釋放消息后繼續(xù)循環(huán),再次嘗試加鎖

    • 如果整個(gè)加鎖嘗試時(shí)間超過(guò)了 waitTime 后仍然未搶到鎖,返回加鎖失敗

    4.總結(jié)

    至此,Redisson 基于 Redis 實(shí)現(xiàn)的分布式鎖的可重入鎖 RedissonLock 的大致原理就分析完了。我們分析了分布式系統(tǒng)下保證共享資源安全的一些必要特性,然后針對(duì) Redisson 實(shí)現(xiàn)的可重入鎖的加鎖、自動(dòng)續(xù)期、鎖釋放、鎖等待的代碼進(jìn)行了分析,整個(gè)過(guò)程有所簡(jiǎn)略,只關(guān)注了整體流程。更為細(xì)節(jié)的內(nèi)容如如何和 Redis 進(jìn)行通信、配置管理覆蓋、發(fā)布訂閱如何實(shí)現(xiàn),感興趣的話大家可以自己探索一下。

    全文完


    以下文章您可能也會(huì)感興趣:

    • 簡(jiǎn)單說(shuō)說(shuō)spring的循環(huán)依賴

    • Mysql redo log 漫游

    • 單元測(cè)試的實(shí)踐之路

    • 可線性化檢查:與 NP 完全問(wèn)題做斗爭(zhēng)

    • Java 類型系統(tǒng)從入門到放棄

    • Webpack 快速上手(下)

    • Webpack 快速上手(中)

    • Webpack 快速上手(上)

    • Airbnb 的 React Native 之路(下)

    • Airbnb 的 React Native 之路(上)

    • 零基礎(chǔ)玩轉(zhuǎn) Serverless

    • iOS 開(kāi)發(fā):深入理解 Xcode 工程結(jié)構(gòu)(一)

    • 三大報(bào)表:財(cái)務(wù)界的通用語(yǔ)言

    • 四維閱讀法 - 我的高效學(xué)習(xí)“秘技”

    • 一個(gè)創(chuàng)業(yè)公司的容器化之路(三) - 容器即未來(lái)

    • 一個(gè)創(chuàng)業(yè)公司的容器化之路(二) - 容器化

    • 一個(gè)創(chuàng)業(yè)公司的容器化之路(一) - 容器化之前

    • 樂(lè)高式微服務(wù)化改造(下)

    • 樂(lè)高式微服務(wù)化改造(上)

    我們正在招聘 Java 工程師,歡迎有興趣的同學(xué)投遞簡(jiǎn)歷到 rd-hr@xingren.com 。

    總結(jié)

    以上是生活随笔為你收集整理的年轻人,看看Redisson分布式锁—可重入锁吧!太重要了的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    天天操天天射天天爱 | 久久国产综合视频 | 在线观看免费色 | 日韩av偷拍| 欧美一级乱黄 | 天天干天天操av | 日韩最新在线视频 | 国产精品久久久久久久久久99 | 国产在线观看中文字幕 | 黄色大片国产 | 丁香狠狠 | 亚洲丝袜中文 | 国产精品久久久久毛片大屁完整版 | 日本二区三区在线 | 久久精品视频中文字幕 | 国产老太婆免费交性大片 | 色哟哟国产精品 | 99久久er热在这里只有精品15 | av在线不卡观看 | 00av视频| 天堂网一区二区三区 | 在线国产专区 | 亚洲伊人色 | 成人免费xxx在线观看 | 婷婷六月在线 | www.狠狠插.com | 99国产精品视频免费观看一公开 | 亚洲人人射 | 久久精品韩国 | 久久y| 亚洲91网站 | 成人宗合网 | 国产a级免费 | 国产999在线观看 | 久久久精品一区二区三区 | 久久超碰网 | 亚洲国产片 | 国产玖玖精品视频 | 激情久久影院 | 日本大尺码专区mv | 久久99精品国产99久久6尤 | 国产伦精品一区二区三区四区视频 | 91漂亮少妇露脸在线播放 | 国内精品久久久久久 | 91精品久久久久久粉嫩 | 日韩在线视频网 | 成年人免费在线 | 精品999在线| 午夜丰满寂寞少妇精品 | 九九视频这里只有精品 | 欧美性猛片| 精品国产乱码一区二 | 亚洲一区二区精品在线 | 在线视频福利 | 又黄又色又爽 | 国产精品免费一区二区 | 人人狠狠| 国产一级黄色电影 | 亚洲黄色激情小说 | 少妇bbbb揉bbbb日本 | 国产九九九九九 | 免费看毛片在线 | aaa毛片视频| 国产精品久久久久婷婷二区次 | 亚洲视频 在线观看 | 婷婷色社区| 精品五月天 | 欧美最猛性xxxxx免费 | 日本性久久 | 亚洲综合在线五月 | www日韩视频 | 久草观看 | 久久久精品网站 | 久草爱 | 国产97碰免费视频 | 国产精品久久久久一区 | 国产九色视频在线观看 | 成年人在线免费视频观看 | 亚洲男女精品 | 中文字幕免 | 国产成人av一区二区三区在线观看 | 国产色视频一区二区三区qq号 | 日韩一级电影网站 | www.久草视频 | 亚洲精品在线一区二区三区 | 午夜性福利 | 一区二区久久久久 | 国产在线欧美在线 | 91av欧美| 五月激情亚洲 | 在线免费观看av网站 | 亚洲欧洲精品一区二区精品久久久 | 亚洲视频久久久 | 天天摸夜夜操 | 欧美性久久久久久 | 亚洲成成品网站 | 日日夜夜精品免费观看 | 在线观看国产日韩 | 久久天天拍| 亚洲丝袜一区二区 | 国产精成人品免费观看 | 国产在线观看91 | 亚洲美女精品区人人人人 | 国内精品久久久久久久影视简单 | av在线激情 | 中文字幕成人在线 | 日韩av网站在线播放 | 国产精品久久久久一区二区 | 天天艹日日干 | 在线中文字幕网站 | 久草在在线 | av在线一 | 久久精品综合网 | 国产综合在线视频 | 国产一区福利在线 | 天无日天天操天天干 | 亚洲国产精品久久 | 日韩欧美高清一区二区 | 在线免费观看黄色小说 | 91九色最新 | 麻豆视频免费入口 | 国产黄色精品 | 9色在线视频 | 久久视频这里有久久精品视频11 | 狠狠狠色| 在线观看中文字幕一区二区 | 久热电影| 一级黄色av | 日本中文在线 | 天天综合色天天综合 | 一区二区精品在线 | 99精品网站 | 中文字幕在线视频网站 | 欧美一区二区三区在线 | 国产韩国日本高清视频 | 最近日本中文字幕 | 日韩一区二区三免费高清在线观看 | 丁香视频 | 久久五月天婷婷 | 国产精品video爽爽爽爽 | 婷婷av综合 | av电影不卡| 韩国精品一区二区三区六区色诱 | 国产精品一区二区免费视频 | 午夜av免费 | 欧美成人黄色片 | 国产精品黑丝在线观看 | 国产欧美日韩视频 | 瑞典xxxx性hd极品 | 日批视频在线播放 | 欧美贵妇性狂欢 | 特级a老妇做爰全过程 | 久久99精品国产 | 欧美一区二区精品在线 | 国产黄色免费电影 | 亚洲午夜精品一区 | 日韩精品欧美视频 | 韩国av免费观看 | 91大神dom调教在线观看 | 三级av免费观看 | 久久字幕网 | 97超碰在线视 | 国产精品嫩草69影院 | 天天干夜夜夜 | 四虎成人精品永久免费av | 九九九九色 | 国产亚洲精品久 | av丝袜在线 | 麻豆视频一区 | 五月婷婷激情综合 | 久草五月 | 一本之道乱码区 | 在线观看av麻豆 | 国产精品午夜免费福利视频 | 最新国产精品久久精品 | 久草视频在线播放 | 精品国产美女 | 国产手机视频在线观看 | 97超在线 | 波多野结衣在线视频免费观看 | 国产69精品久久app免费版 | 免费大片av | 91视频免费看片 | 国产丝袜美腿在线 | 天天操天天操天天 | 成人av播放| 精品福利在线视频 | 国产精品黄色在线观看 | 在线成人一区二区 | 丁香婷婷久久久综合精品国产 | 国产精品嫩草影视久久久 | 欧美有色 | 夜夜操天天 | 国产高清免费 | 四虎8848免费高清在线观看 | 亚洲精品午夜国产va久久成人 | 国产高清在线看 | 精品视频免费在线 | 丁香婷婷激情国产高清秒播 | 国产网站在线免费观看 | 黄色91在线观看 | 人人澡人人爱 | 久久久久北条麻妃免费看 | 一本一本久久a久久精品综合小说 | 国产一区二区精品久久91 | 午夜精品久久久99热福利 | 日女人免费视频 | 亚洲综合小说 | 色久综合 | 国内一级片在线观看 | 香蕉视频久久 | 欧美男女爱爱视频 | 成人app在线播放 | 日韩亚洲在线观看 | 国产精品一区二区三区观看 | 欧美人牲 | 中文字幕色网站 | 亚洲视频观看 | 99视频| 最近中文字幕 | 免费中文字幕在线观看 | 国产九九在线 | 五月婷在线观看 | 91久久国产精品 | 五月婷在线观看 | 永久精品视频 | 在线看毛片网站 | 欧美日韩中文在线视频 | 97免费中文视频在线观看 | 人人爽人人香蕉 | 免费视频色 | 日韩三级一区 | 午夜视频在线观看一区二区三区 | 日韩一区二区三区免费视频 | 国产精品2018 | 超碰在97 | 奇米先锋 | 在线看成人片 | 免费国产一区二区 | 国产一二三区av | 日日爱夜夜爱 | 国产精品高潮呻吟久久av无 | 97色se | 欧美日韩亚洲精品在线 | 一区视频在线 | 国产黄av | 欧美日韩国产一区二区在线观看 | 免费又黄又爽 | 99热99re6国产在线播放 | 日韩精品2区| av电影免费在线播放 | 国产精品自拍在线 | 婷婷国产一区二区三区 | 99r在线精品 | 欧美日韩国产二区 | 亚洲精品在线免费 | 91综合色| 中文亚洲欧美日韩 | 国产看片网站 | 亚洲免费av在线 | 五月婷婷色综合 | 好看av在线 | 精品国产美女在线 | 91免费日韩 | 欧美 日韩 国产 中文字幕 | 午夜av电影院 | 欧美精品999 | 国产乱码精品一区二区蜜臀 | 色婷婷综合久久久 | 成人国产精品入口 | 免费一级特黄录像 | 日韩精品一区在线观看 | 色婷婷福利视频 | 伊人国产女 | 91精选在线观看 | 一级一片免费看 | 91视频在线国产 | 国产一区二区成人 | 大型av综合网站 | www亚洲视频| 中文字幕在线专区 | 日韩av资源站 | 成片免费观看视频大全 | 992tv在线| 日韩久久激情 | 一区二区不卡高清 | 日韩三级在线 | av电影久久 | 国产在线色站 | 免费日韩电影 | 国产美女精品视频免费观看 | 91九色国产在线 | 国产一区欧美日韩 | 啪啪免费试看 | 欧美日韩一区二区三区免费视频 | 色综合久久精品 | 亚洲精品视频中文字幕 | 国产福利一区二区在线 | 成人国产精品一区二区 | 日韩免费一区二区在线观看 | 久草网站在线观看 | 婷婷久久综合网 | 麻豆成人在线观看 | 日韩精品视频免费专区在线播放 | 成人app在线免费观看 | 国产成免费视频 | 国产成人精品亚洲精品 | 日本三级香港三级人妇99 | 色噜噜噜 | 久久免费视频99 | 人人爽人人干 | 一区二区三区电影 | 在线观看视频福利 | 精品国产理论片 | www免费在线观看 | 欧美一区二区日韩一区二区 | 91在线永久 | 美女网站在线播放 | 日韩欧在线 | 日本大尺码专区mv | 国产美女主播精品一区二区三区 | 天天躁日日躁狠狠躁 | 日韩av电影中文字幕 | 成人av一级片 | 亚洲精品国产精品乱码在线观看 | 青青五月天 | 香蕉色综合 | 精品免费久久久久 | 精品你懂的 | 日韩激情小视频 | 亚洲综合导航 | 91九色国产视频 | 9999精品免费视频 | 国产成人一区二区三区在线观看 | 国产四虎影院 | 亚洲va欧美va国产va黑人 | 丁香视频全集免费观看 | 久久最新视频 | 欧美 日韩精品 | 丁香视频全集免费观看 | 亚洲精品国产精品国 | 国产精品爽爽久久久久久蜜臀 | 日日弄天天弄美女bbbb | 国产精品入口传媒 | 久久国产精品二国产精品中国洋人 | 中文字幕视频一区 | 91九色视频国产 | 天天操夜夜曰 | 日批视频国产 | 天天射天 | 久久综合9988久久爱 | 美女在线免费观看视频 | 99免费在线 | 国产亚州av| 国产精品日韩高清 | 色综合久久88色综合天天 | 国模视频一区二区 | 激情五月综合 | 成人免费在线网 | av手机在线播放 | 亚洲精品久 | 97福利社| 亚洲资源在线 | 天天做天天射 | 中文在线√天堂 | 国产精品一区二区62 | 免费看国产黄色 | 就要干b| 国内精品久久久久影院优 | 色婷婷婷 | 亚洲国产小视频在线观看 | 久久在线免费视频 | 中文字幕乱在线伦视频中文字幕乱码在线 | av片在线观看免费 | 国产一区二区在线播放视频 | 久艹视频免费观看 | 中文字幕视频播放 | 日韩欧美一区二区在线播放 | 成人影片免费 | 91成人久久 | 国产一级一级国产 | 日本在线精品视频 | av最新资源 | 日韩精品视频免费看 | 日韩欧美在线第一页 | 欧美三级免费 | 亚洲一级电影 | 不卡视频在线看 | 有码中文字幕在线观看 | 99久热在线精品视频 | 免费av电影网站 | 久久久久久久久毛片精品 | 欧美另类tv | 97精品视频在线播放 | av大片网站| 国产精品69av| 69久久夜色精品国产69 | 欧美日韩国产精品一区 | 国产玖玖视频 | 免费高清无人区完整版 | 在线看片中文字幕 | 国产精品第10页 | 国产一区二区在线免费视频 | 天天操天天添天天吹 | 在线观看亚洲电影 | 中文字幕在线专区 | 亚洲精品资源在线 | 国产91学生粉嫩喷水 | 五月激情视频 | 一区精品在线 | 久久免费视频这里只有精品 | 8x成人在线 | 国产不卡在线观看视频 | 免费黄色一区 | 五月激情亚洲 | 亚洲片在线资源 | 97电影手机| 麻豆一精品传二传媒短视频 | 国产69精品久久久久99 | 国产不卡在线观看视频 | 免费看的国产视频网站 | 免费看污在线观看 | 国产美女被啪进深处喷白浆视频 | 91精品视频免费在线观看 | 狠狠狠色丁香综合久久天下网 | 99精品免费久久久久久久久日本 | 青青草视频精品 | 99这里只有久久精品视频 | 91在线免费播放 | 9在线观看免费高清完整版在线观看明 | 国产精品永久久久久久久久久 | 国产精品久久久久久99 | 久久字幕 | 日韩在线观看中文 | 免费观看成年人视频 | 日韩在线观看精品 | 亚洲国产成人在线播放 | 国产最新在线观看 | 99精品免费在线 | 狠狠色丁香婷婷综合久久片 | 人人干天天干 | 亚洲毛片视频 | 91看片成人| 草久久av | 国产黄影院色大全免费 | 伊人小视频 | 亚洲国产精品传媒在线观看 | 一区二区精品久久 | 五月婷婷丁香色 | 久久美女视频 | 欧美99精品 | 日批在线观看 | 91亚洲精品久久久蜜桃借种 | 999色视频| 国产一区二区成人 | 国产成人a亚洲精品 | 亚洲成人资源 | 国产中文字幕三区 | aaawww| 播五月婷婷 | 超碰国产97| 国产一级a毛片视频爆浆 | av中文字幕网 | 成人黄色电影在线 | 91av电影在线观看 | 国产精品精品国产婷婷这里av | 香蕉久久国产 | 成人午夜精品久久久久久久3d | 看片网站黄色 | 丁香影院在线 | 日韩av高清 | 国产一区二区三区 在线 | 久草在线在线 | 激情深爱五月 | 伊人久操| 欧美在线观看视频 | 免费av在线网站 | 在线播放视频一区 | 久久久久久在线观看 | 在线观av| 日日干干 | 国产视频一区在线播放 | 狠狠色丁香久久婷婷综 | 日韩中文字幕免费 | 免费人成在线观看网站 | 91网址在线 | 黄色字幕网 | 99视频在线观看一区三区 | 欧美日韩一区二区免费在线观看 | 国产男女免费完整视频 | 碰超人人| 日本久久影视 | 超碰在线国产 | 日本性动态图 | 国产乱码精品一区二区三区介绍 | 国产精品日韩欧美 | 99久久婷婷国产一区二区三区 | 日韩av专区 | 日韩久久精品一区二区三区 | 久久国内精品 | 欧美久久久久久久久久久 | 九九在线高清精品视频 | 999国产 | 视频一区二区免费 | 在线综合 亚洲 欧美在线视频 | 久久精品成人热国产成 | 丝袜美腿在线视频 | 色婷婷狠狠 | 精品视频在线视频 | 日本中文在线 | 久久三级视频 | 精品一二三四在线 | a成人v | 国产成人三级在线 | av不卡免费看 | 国产一区私人高清影院 | 久久精品在线视频 | 欧美一级专区免费大片 | 韩国精品福利一区二区三区 | 91久久精品一区二区三区 | 久久久久国产a免费观看rela | 中日韩三级视频 | 高清免费在线视频 | 91丨九色丨91啦蝌蚪老版 | 国产亚洲精品成人 | 久久久伊人网 | 久久免费国产视频 | 国产精品 日韩 欧美 | 999久久精品 | 成人av日韩| 精品在线播放视频 | 久久精品国产v日韩v亚洲 | 97国产精品 | 久草视频在线免费看 | 欧美孕妇视频 | 免费看的毛片 | 国产精品免费久久久 | 国产精品福利久久久 | 免费高清在线观看成人 | 激情综合狠狠 | 久久se视频 | 少妇av网 | 91精品办公室少妇高潮对白 | 天天爽夜夜爽人人爽一区二区 | 国产精品久久久久av福利动漫 | 夜夜爽天天爽 | 国产成人一区二区三区 | 91夫妻视频 | 国产99久久九九精品免费 | 亚洲人人爱 | 国产精品久久久久久av | 天天激情站| 天天操天天干天天爱 | 欧美日韩69 | 国产视频 亚洲精品 | 日韩视频在线播放 | 天天射天天艹 | 久久国产精品久久精品 | 国产精品久久久久久久久岛 | 欧美日韩国产免费视频 | 久久久久综合精品福利啪啪 | 大型av综合网站 | 国产女教师精品久久av | 操高跟美女 | 天天射天天操天天 | 日日添夜夜添 | 1024手机看片国产 | 91精彩视频| 亚洲综合情 | 欧美色图亚洲图片 | 中文字幕日本在线 | 人成在线免费视频 | 久久色在线观看 | 天天干.com| 免费在线观看成人 | 亚洲欧美乱综合图片区小说区 | 丁香 婷婷 激情 | 丁香五婷| 国产精品人人做人人爽人人添 | 久久在视频| 久久久免费少妇 | aⅴ精品av导航| 操操日| 久久精精品视频 | 超碰官网 | 天天色棕合合合合合合 | 91精品视频播放 | 久久综合九色 | 日韩精品一卡 | 91亚洲国产成人久久精品网站 | 中文字幕av电影下载 | 999国产在线| av电影中文字幕在线观看 | 欧美在线视频二区 | 免费在线日韩 | 日韩欧美精品免费 | 欧美91片| 成人免费在线看片 | 91看片淫黄大片在线播放 | 久久久久国产精品午夜一区 | 国产99久久精品一区二区300 | 国产一区在线视频播放 | 亚洲永久精品在线 | 成人精品视频久久久久 | 麻豆视频免费网站 | 黄色av电影免费观看 | 成年人视频在线免费播放 | 青青色影院| 日韩在线高清免费视频 | 色婷婷综合视频在线观看 | 亚洲成人一区 | 夜夜干天天操 | 久久夜色精品国产欧美乱极品 | 99久久精品免费看国产免费软件 | 精品婷婷| 久久9999久久免费精品国产 | 国产精品久久久视频 | 黄色网www| 久久精品三级 | 精品一区二区三区四区在线 | 97超碰.com| 久久精品一区二区三区国产主播 | 嫩草伊人久久精品少妇av | 国产糖心vlog在线观看 | 在线观看亚洲a | 天天躁日日| 中文字幕二区三区 | 国产色婷婷 | 国内外成人免费在线视频 | 永久免费的啪啪网站免费观看浪潮 | 免费美女av| 中文一区在线观看 | av黄色免费在线观看 | 蜜臀av性久久久久av蜜臀三区 | 天天鲁一鲁摸一摸爽一爽 | 美女视频久久久 | 国产91精品看黄网站 | 天堂中文在线视频 | 中文字幕一区二区三区精华液 | 国产精品久久久久久久久毛片 | 午夜999 | 国产精品亚洲成人 | 久久免费视频在线观看6 | 人人插人人做 | 成人午夜毛片 | 亚洲精选在线观看 | 热久久99这里有精品 | 亚洲欧美国产视频 | 久久久视屏 | 亚洲一区天堂 | 久久久久国产一区二区三区四区 | 日韩高清不卡在线 | 99色免费| 成年人免费电影 | 久久99精品国产91久久来源 | 夜夜视频欧洲 | 日韩大片在线免费观看 | 久久伦理| 久久国产午夜精品理论片最新版本 | 成人不用播放器 | 韩国av一区| 欧美在线观看禁18 | 久久精品一区二区三区视频 | 99热这里只有精品在线观看 | 91av视频免费观看 | 亚洲国产日韩精品 | 色资源在线观看 | 黄色www在线观看 | 国产日女人 | 国产亚洲精品美女久久 | 国产精品久久一区二区三区不卡 | 香蕉精品视频在线观看 | 曰本三级在线 | 国产精品欧美激情在线观看 | 国产精品 欧美 日韩 | 亚洲成人黄色在线 | 超碰日韩在线 | 日韩欧三级 | 99视频精品 | 九色最新网址 | 伊人久久五月天 | 国产精品18久久久久久久网站 | 色婷婷一区| 波多野结衣电影一区二区 | 黄色一级大片在线免费看产 | 欧美一级特黄高清视频 | 天天做天天看 | av成年人电影 | 91久久丝袜国产露脸动漫 | 蜜臀久久99精品久久久无需会员 | 182午夜在线观看 | 久久久精品高清 | 天天艹天天爽 | 日韩在线网址 | 亚洲欧美日韩在线一区二区 | 久久精品欧美视频 | 亚洲日本精品 | 国产精品毛片一区视频播不卡 | www.天天干.com | 中文字幕日韩伦理 | 久久精品视频日本 | 在线观看成年人 | 中日韩欧美精彩视频 | 在线观看中文字幕第一页 | 九九热在线免费观看 | 永久免费的av电影 | 超碰人人干人人 | 亚洲精品乱码久久久久久蜜桃动漫 | 成人在线观看免费视频 | 91九色在线视频观看 | 国产黄色电影 | 超碰在线人人爱 | 欧美精品久久人人躁人人爽 | 亚洲一级片免费观看 | 欧美孕妇与黑人孕交 | 国产精品一区二区免费视频 | 久久国产高清 | 亚洲91中文字幕无线码三区 | 亚洲激情 在线 | 色婷婷精品大在线视频 | 亚洲精品成人在线 | 久久精品99久久久久久2456 | 国产3p视频 | 国产xxxx| 久久婷婷网| 中文字幕黄色网 | 97超碰中文字幕 | 国产又粗又长又硬免费视频 | 2019中文最近的2019中文在线 | 国产精品久久久久久久久久久免费看 | 六月丁香激情网 | 亚洲 中文字幕av | 天天操天天射天天插 | 99久国产 | 国产丝袜一区二区三区 | 久久成人人人人精品欧 | 在线免费观看成人 | 成人四虎影院 | 午夜精品久久久99热福利 | 91在线亚洲| 亚洲视频久久久 | 久草国产精品 | av电影中文字幕在线观看 | 丁香激情五月 | 亚洲精品xx | 亚洲一区二区麻豆 | 免费久久久久久 | 日韩av在线网站 | 婷婷在线不卡 | 国产成人精品av久久 | 国产流白浆高潮在线观看 | 亚洲成年人在线播放 | 国产黄在线看 | www蜜桃视频 | 日韩高清在线观看 | www.亚洲精品视频 | 波多野结衣在线播放一区 | 欧美日韩中 | 国产又粗又猛又爽 | 九色最新网址 | 六月色| 亚洲精品乱码久久久久久蜜桃91 | 午夜婷婷综合 | 国产精品成人免费一区久久羞羞 | 开心激情五月网 | 日批视频在线观看免费 | 国产成人精品一区二区三区在线观看 | av怡红院 | 中文字幕2021 | 99在线观看免费视频精品观看 | 天天搞天天干 | 天天操天天干天天干 | 中文字幕激情 | 午夜精品电影 | 久草剧场 | 久综合网| 午夜精品av | 亚洲成人资源在线观看 | 亚洲视频免费在线观看 | 日本免费久久高清视频 | 久久精品电影院 | 欧美成人区 | 国产成人中文字幕 | 特黄色大片 | 久草在线一免费新视频 | 欧美大片mv免费 | 99免费在线观看视频 | 成人av免费在线观看 | 精品视频www | 天天爱天天射天天干天天 | 欧美va日韩va | 中文字幕高清免费日韩视频在线 | 国产黄色精品在线观看 | 日韩高清无线码2023 | 日本中文字幕一二区观 | 日韩在线高清视频 | 欧美性久久久久久 | 免费在线国产视频 | 国产亚洲精品久 | 久久免费a | 国产精品久久久久久久久软件 | 国产69久久久 | av福利免费 | 国产又粗又猛又色 | 中文字幕制服丝袜av久久 | 久久久久久久久久久久影院 | 激情视频久久 | 国产精品永久久久久久久www | 96精品高清视频在线观看软件特色 | 久久婷婷影视 | 免费观看特级毛片 | 正在播放五月婷婷狠狠干 | 久久99久久久久久 | 国产成人精品免高潮在线观看 | 国产精品一区二区你懂的 | 久久免费在线观看视频 | 国产伦精品一区二区三区高清 | 免费黄av| 欧美日韩久 | 中文字幕一区二区三区四区 | 少妇视频一区 | 天天爱天天草 | 久久久久国产精品www | www国产亚洲精品久久麻豆 | 国产91对白在线 | 午夜精品久久一牛影视 | 91九色最新 | 在线看一区 | 国产在线久久久 | 成人a在线| 亚洲国产网站 | 中文字幕免费在线看 | 成人av在线直播 | 亚洲精品福利视频 | 日韩精品视频在线观看网址 | 亚洲闷骚少妇在线观看网站 | 超碰在线人人 | 成人在线播放视频 | 色婷婷视频网 | 99精品视频在线观看视频 | 欧美一级片在线观看视频 | 国产精品久久久久av福利动漫 | 亚洲久草网 | 在线小视频 | www.com.日本一级| www.91成人| 久久毛片视频 | 国产91精品一区二区麻豆亚洲 | 精品久久久久久久久久国产 | 亚洲成人国产 | 日韩高清观看 | 亚洲区精品视频 | 97人人精品 | 91精品系列 | 成人欧美在线 | 免费在线观看av的网站 | 久久中文网 | 午夜精品久久久久久久99热影院 | 国内视频在线 | 91色欧美 | 成人免费观看大片 | 日韩色综合 | 国产日韩欧美在线观看视频 | 欧美日比视频 | 91精品国产一区二区在线观看 | 2023亚洲精品国偷拍自产在线 | 欧美久久久久久久 | 男女激情网址 | 日韩精品中文字幕一区二区 | 精品国产一区二区三区久久影院 | av电影亚洲 | 亚洲香蕉在线观看 | 国产69精品久久久久99尤 | 免费看国产黄色 | 国产女人18毛片水真多18精品 | 在线观看网站你懂的 | 国产亚洲va综合人人澡精品 | 久久国产电影 | 日本久久久精品视频 | 91精品免费在线 | 中文字幕 在线 一 二 | 91人人澡人人爽 | 久久精品视频网站 | 婷婷国产一区二区三区 | 亚洲人成网站精品片在线观看 | 欧美精品中文字幕亚洲专区 | 在线播放 日韩专区 | www.com.日本一级 | 国产成人一区二区三区影院在线 | 免费在线观看毛片网站 | 国产精品成人a免费观看 | 日韩午夜三级 | av网站大全免费 | 91九色网站 | 久久久久久免费网 | 国产精品一区二区av麻豆 | 亚洲精品美女在线观看 | 日本精品在线视频 | 精品欧美一区二区三区久久久 | 狠狠狠综合 | 久久韩国免费视频 | av福利电影 | 日韩精品一区二区三区免费观看视频 | 91久久精品一区二区二区 | 天天操天天干天天摸 | 亚洲精品国偷拍自产在线观看蜜桃 | 中文字幕在线一二 | 97电影在线 | 中文字幕专区高清在线观看 | av免费在线观看网站 | 国产精品九九九 | 黄色毛片在线 | 日韩精品在线免费播放 | 99热精品国产一区二区在线观看 | 草久久精品 | 亚洲精品视频在线观看视频 | 日韩一区二区三免费高清在线观看 | 91久久精| 色噜噜狠狠色综合中国 | 欧美日韩中文字幕综合视频 | 国产精品12 | 91精品无人成人www | 五月天久久久久久 | 麻豆91精品91久久久 | 91精品一 | 在线观看不卡的av | 免费91麻豆精品国产自产在线观看 | 亚洲精品乱码久久久久久蜜桃欧美 | 日韩99热| 丁香九月激情综合 | 麻豆高清免费国产一区 | 日韩电影在线观看一区二区 | 六月丁香激情综合色啪小说 | 91精品国产91热久久久做人人 | www.色com| 亚洲精品乱码久久久久久蜜桃91 | 亚洲砖区区免费 | 国产精品九九九九九九 | 久久色视频| 欧美精品日韩 | 欧美精品久久久久久 | 色综合中文综合网 | 久久99爱视频 | 97电影手机 | 精品av网站 | 国产黄色免费看 | 久久综合久久久 | 三级在线国产 | 久久精品三级 | 91精品在线免费 | 91在线中字 | 亚洲久草网 | 18国产精品福利片久久婷 | 日韩一区二区三区在线看 | 色 免费观看 | 91麻豆精品国产91久久久无限制版 | 日韩精品视频在线免费观看 | 涩av在线| 91香蕉久久 | 麻豆成人小视频 | 黄色一及电影 | 国产亚洲婷婷免费 | 一级片视频免费观看 | 日韩精品一二三 | 999视频精品 | 日日日日日 | 成人午夜av电影 | 五月婷婷播播 | 久久成人毛片 | 国产h片在线观看 | 久久久久福利视频 | 亚洲精品免费视频 | 欧美a在线免费观看 | av色影院 | 亚洲精品福利在线 | 日韩黄色在线 | 在线免费观看国产 | 色综合天天综合 | 国产精品久久久久aaaa九色 | 亚洲成aⅴ人在线观看 | 夜添久久精品亚洲国产精品 | 正在播放 久久 | 国产最新福利 | 国产免费又爽又刺激在线观看 | 天天操月月操 | 欧美 日韩 久久 | 五月天免费网站 | 日本婷婷色 | 国产精品九九九九九 | 欧美aaa视频 | 欧美日韩视频在线观看一区二区 | 亚洲免费av网站 | 欧美一二三区在线播放 | 久久久精品日本 | 91女人18片女毛片60分钟 | 在线视频 影院 | 久热免费在线 | 亚洲黄a|