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

用MySQL實(shí)現(xiàn)分布式鎖,你聽過嗎?

數(shù)據(jù)庫 MySQL 分布式
以前參加過一個庫存系統(tǒng),由于其業(yè)務(wù)復(fù)雜性,搞了很多個應(yīng)用來支撐。這樣的話一份庫存數(shù)據(jù)就有可能同時(shí)有多個應(yīng)用來修改庫存數(shù)據(jù)。

概述

以前參加過一個庫存系統(tǒng),由于其業(yè)務(wù)復(fù)雜性,搞了很多個應(yīng)用來支撐。這樣的話一份庫存數(shù)據(jù)就有可能同時(shí)有多個應(yīng)用來修改庫存數(shù)據(jù)。

比如說,有定時(shí)任務(wù)域xx.cron,和SystemA域和SystemB域這幾個JAVA應(yīng)用,可能同時(shí)修改同一份庫存數(shù)據(jù)。如果不做協(xié)調(diào)的話,就會有臟數(shù)據(jù)出現(xiàn)。

對于跨JAVA進(jìn)程的線程協(xié)調(diào),可以借助外部環(huán)境,例如DB或者Redis。下文介紹一下如何使用DB來實(shí)現(xiàn)分布式鎖。

[[427766]]

設(shè)計(jì)

本文設(shè)計(jì)的分布式鎖的交互方式如下:

  • 根據(jù)業(yè)務(wù)字段生成transaction_id,并線程安全的創(chuàng)建鎖資源
  • 根據(jù)transaction_id申請鎖
  • 釋放鎖

動態(tài)創(chuàng)建鎖資源

在使用synchronized關(guān)鍵字的時(shí)候,必須指定一個鎖對象。 

  1. synchronized(obj) {  

進(jìn)程內(nèi)的線程可以基于obj來實(shí)現(xiàn)同步。obj在這里可以理解為一個鎖對象。如果線程要進(jìn)入synchronized代碼塊里,必須先持有obj對象上的鎖。這種鎖是JAVA里面的內(nèi)置鎖,創(chuàng)建的過程是線程安全的。那么借助DB,如何保證創(chuàng)建鎖的過程是線程安全的呢?

可以利用DB中的UNIQUE KEY特性,一旦出現(xiàn)了重復(fù)的key,由于UNIQUE KEY的唯一性,會拋出異常的。在JAVA里面,是SQLIntegrityConstraintViolationException異常。 

  1. create table distributed_lock 
  2.  id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '自增主鍵'
  3.  transaction_id varchar(128) NOT NULL DEFAULT '' COMMENT '事務(wù)id'
  4.  last_update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL COMMENT '最后更新時(shí)間'
  5.  create_time TIMESTAMP DEFAULT '0000-00-00 00:00:00' NOT NULL COMMENT '創(chuàng)建時(shí)間'
  6.  UNIQUE KEY `idx_transaction_id` (`transaction_id`) 

transaction_id是事務(wù)Id,比如說,可以用

倉庫 + 條碼 + 銷售模式

來組裝一個transaction_id,表示某倉庫某銷售模式下的某個條碼資源。不同條碼,當(dāng)然就有不同的transaction_id。如果有兩個應(yīng)用,拿著相同的transaction_id來創(chuàng)建鎖資源的時(shí)候,只能有一個應(yīng)用創(chuàng)建成功。

一條distributed_lock記錄插入成功了,就表示一份鎖資源創(chuàng)建成功了。

DB連接池列表設(shè)計(jì)

在寫操作頻繁的業(yè)務(wù)系統(tǒng)中,通常會進(jìn)行分庫,以降低單數(shù)據(jù)庫寫入的壓力,并提高寫操作的吞吐量。如果使用了分庫,那么業(yè)務(wù)數(shù)據(jù)自然也都分配到各個數(shù)據(jù)庫上了。

在這種水平切分的多數(shù)據(jù)庫上使用DB分布式鎖,可以自定義一個DataSouce列表。并暴露一個getConnection(String transactionId)方法,按照transactionId找到對應(yīng)的Connection。

實(shí)現(xiàn)代碼如下: 

  1. package dlock; 
  2.  
  3. import com.alibaba.druid.pool.DruidDataSource; 
  4. import org.springframework.stereotype.Component; 
  5.  
  6. import javax.annotation.PostConstruct; 
  7. import java.io.FileInputStream; 
  8. import java.io.IOException; 
  9. import java.sql.Connection
  10. import java.util.ArrayList; 
  11. import java.util.List; 
  12. import java.util.Properties; 
  13.  
  14. @Component 
  15. public class DataSourcePool { 
  16.     private List<DruidDataSource> dlockDataSources = new ArrayList<>(); 
  17.  
  18.     @PostConstruct 
  19.     private void initDataSourceList() throws IOException { 
  20.         Properties properties = new Properties(); 
  21.         FileInputStream fis = new FileInputStream("db.properties"); 
  22.         properties.load(fis); 
  23.  
  24.         Integer lockNum = Integer.valueOf(properties.getProperty("DLOCK_NUM")); 
  25.         for (int i = 0; i < lockNum; i++) { 
  26.             String user = properties.getProperty("DLOCK_USER_" + i); 
  27.             String password = properties.getProperty("DLOCK_PASS_" + i); 
  28.             Integer initSize = Integer.valueOf(properties.getProperty("DLOCK_INIT_SIZE_" + i)); 
  29.             Integer maxSize = Integer.valueOf(properties.getProperty("DLOCK_MAX_SIZE_" + i)); 
  30.             String url = properties.getProperty("DLOCK_URL_" + i); 
  31.  
  32.             DruidDataSource dataSource = createDataSource(user,password,initSize,maxSize,url); 
  33.             dlockDataSources.add(dataSource); 
  34.         } 
  35.     } 
  36.  
  37.     private DruidDataSource createDataSource(String user, String passwordInteger initSize, Integer maxSize, String url) { 
  38.         DruidDataSource dataSource = new DruidDataSource(); 
  39.         dataSource.setDriverClassName("com.mysql.jdbc.Driver"); 
  40.         dataSource.setUsername(user); 
  41.         dataSource.setPassword(password); 
  42.         dataSource.setUrl(url); 
  43.         dataSource.setInitialSize(initSize); 
  44.         dataSource.setMaxActive(maxSize); 
  45.  
  46.         return dataSource; 
  47.     } 
  48.  
  49.     public Connection getConnection(String transactionId) throws Exception { 
  50.         if (dlockDataSources.size() <= 0) { 
  51.             return null
  52.         } 
  53.  
  54.         if (transactionId == null || "".equals(transactionId)) { 
  55.             throw new RuntimeException("transactionId是必須的"); 
  56.         } 
  57.  
  58.         int hascode = transactionId.hashCode(); 
  59.         if (hascode < 0) { 
  60.             hascode = - hascode; 
  61.         } 
  62.  
  63.         return dlockDataSources.get(hascode % dlockDataSources.size()).getConnection(); 
  64.     } 

首先編寫一個initDataSourceList方法,并利用Spring的PostConstruct注解初始化一個DataSource 列表。相關(guān)的DB配置從db.properties讀取。 

  1. DLOCK_NUM=2 
  2.  
  3. DLOCK_USER_0="user1" 
  4. DLOCK_PASS_0="pass1" 
  5. DLOCK_INIT_SIZE_0=2 
  6. DLOCK_MAX_SIZE_0=10 
  7. DLOCK_URL_0="jdbc:mysql://localhost:3306/test1" 
  8.  
  9. DLOCK_USER_1="user1" 
  10. DLOCK_PASS_1="pass1" 
  11. DLOCK_INIT_SIZE_1=2 
  12. DLOCK_MAX_SIZE_1=10 
  13. DLOCK_URL_1="jdbc:mysql://localhost:3306/test2" 

DataSource使用阿里的DruidDataSource。

接著最重要的一個實(shí)現(xiàn)getConnection(String transactionId)方法。實(shí)現(xiàn)原理很簡單,獲取transactionId的hashcode,并對DataSource的長度取模即可。

連接池列表設(shè)計(jì)好后,就可以實(shí)現(xiàn)往distributed_lock表插入數(shù)據(jù)了。 

  1. package dlock; 
  2.  
  3. import org.springframework.beans.factory.annotation.Autowired; 
  4. import org.springframework.stereotype.Component; 
  5.  
  6. import java.sql.*; 
  7.  
  8. @Component 
  9. public class DistributedLock { 
  10.  
  11.     @Autowired 
  12.     private DataSourcePool dataSourcePool; 
  13.  
  14.     /** 
  15.      * 根據(jù)transactionId創(chuàng)建鎖資源 
  16.      */ 
  17.     public String createLock(String transactionId) throws Exception{ 
  18.         if (transactionId == null) { 
  19.             throw new RuntimeException("transactionId是必須的"); 
  20.         } 
  21.         Connection connection = null
  22.         Statement statement = null
  23.         try { 
  24.             connection = dataSourcePool.getConnection(transactionId); 
  25.             connection.setAutoCommit(false); 
  26.             statement = connection.createStatement(); 
  27.             statement.executeUpdate("INSERT INTO distributed_lock(transaction_id) VALUES ('" + transactionId + "')"); 
  28.             connection.commit(); 
  29.             return transactionId; 
  30.         } 
  31.         catch (SQLIntegrityConstraintViolationException icv) { 
  32.             //說明已經(jīng)生成過了。 
  33.             if (connection != null) { 
  34.                 connection.rollback(); 
  35.             } 
  36.             return transactionId; 
  37.         } 
  38.         catch (Exception e) { 
  39.             if (connection != null) { 
  40.                 connection.rollback(); 
  41.             } 
  42.             throw  e; 
  43.         } 
  44.         finally { 
  45.             if (statement != null) { 
  46.                 statement.close(); 
  47.             } 
  48.  
  49.             if (connection != null) { 
  50.                 connection.close(); 
  51.             } 
  52.         } 
  53.     } 

根據(jù)transactionId鎖住線程

接下來利用DB的select for update特性來鎖住線程。當(dāng)多個線程根據(jù)相同的transactionId并發(fā)同時(shí)操作select for update的時(shí)候,只有一個線程能成功,其他線程都block住,直到select for update成功的線程使用commit操作后,block住的所有線程的其中一個線程才能開始干活。

我們在上面的DistributedLock類中創(chuàng)建一個lock方法。 

  1. public boolean lock(String transactionId) throws Exception { 
  2.        Connection connection = null
  3.        PreparedStatement preparedStatement = null
  4.        ResultSet resultSet = null
  5.        try { 
  6.            connection = dataSourcePool.getConnection(transactionId); 
  7.            preparedStatement = connection.prepareStatement("SELECT * FROM distributed_lock WHERE transaction_id = ? FOR UPDATE "); 
  8.            preparedStatement.setString(1,transactionId); 
  9.            resultSet = preparedStatement.executeQuery(); 
  10.            if (!resultSet.next()) { 
  11.                connection.rollback(); 
  12.                return false
  13.            } 
  14.            return true
  15.        } catch (Exception e) { 
  16.            if (connection != null) { 
  17.                connection.rollback(); 
  18.            } 
  19.            throw  e; 
  20.        } 
  21.        finally { 
  22.            if (preparedStatement != null) { 
  23.                preparedStatement.close(); 
  24.            } 
  25.  
  26.            if (resultSet != null) { 
  27.                resultSet.close(); 
  28.            } 
  29.  
  30.            if (connection != null) { 
  31.                connection.close(); 
  32.            } 
  33.        } 
  34.    } 

實(shí)現(xiàn)解鎖操作

當(dāng)線程執(zhí)行完任務(wù)后,必須手動的執(zhí)行解鎖操作,之前被鎖住的線程才能繼續(xù)干活。在我們上面的實(shí)現(xiàn)中,其實(shí)就是獲取到當(dāng)時(shí)select for update成功的線程對應(yīng)的Connection,并實(shí)行commit操作即可。

那么如何獲取到呢?我們可以利用ThreadLocal。首先在DistributedLock類中定義

  1. private ThreadLocal threadLocalConn = new ThreadLocal<>(); 

每次調(diào)用lock方法的時(shí)候,把Connection放置到ThreadLocal里面。我們修改lock方法。 

  1. public boolean lock(String transactionId) throws Exception { 
  2.        Connection connection = null
  3.        PreparedStatement preparedStatement = null
  4.        ResultSet resultSet = null
  5.        try { 
  6.            connection = dataSourcePool.getConnection(transactionId); 
  7.            threadLocalConn.set(connection); 
  8.            preparedStatement = connection.prepareStatement("SELECT * FROM distributed_lock WHERE transaction_id = ? FOR UPDATE "); 
  9.            preparedStatement.setString(1,transactionId); 
  10.            resultSet = preparedStatement.executeQuery(); 
  11.            if (!resultSet.next()) { 
  12.                connection.rollback(); 
  13.                threadLocalConn.remove(); 
  14.                return false
  15.            } 
  16.            return true
  17.        } catch (Exception e) { 
  18.            if (connection != null) { 
  19.                connection.rollback(); 
  20.                threadLocalConn.remove(); 
  21.            } 
  22.            throw  e; 
  23.        } 
  24.        finally { 
  25.            if (preparedStatement != null) { 
  26.                preparedStatement.close(); 
  27.            } 
  28.  
  29.            if (resultSet != null) { 
  30.                resultSet.close(); 
  31.            } 
  32.  
  33.            if (connection != null) { 
  34.                connection.close(); 
  35.            } 
  36.        } 
  37.    } 

這樣子,當(dāng)獲取到Connection后,將其設(shè)置到ThreadLocal中,如果lock方法出現(xiàn)異常,則將其從ThreadLocal中移除掉。

有了這幾步后,我們可以來實(shí)現(xiàn)解鎖操作了。我們在DistributedLock添加一個unlock方法。 

  1. public void unlock() throws Exception { 
  2.        Connection connection = null
  3.        try { 
  4.            connection = threadLocalConn.get(); 
  5.            if (!connection.isClosed()) { 
  6.                connection.commit(); 
  7.                connection.close(); 
  8.                threadLocalConn.remove(); 
  9.            } 
  10.        } catch (Exception e) { 
  11.            if (connection != null) { 
  12.                connection.rollback(); 
  13.                connection.close(); 
  14.            } 
  15.            threadLocalConn.remove(); 
  16.            throw e; 
  17.        } 
  18.    } 

缺點(diǎn)

畢竟是利用DB來實(shí)現(xiàn)分布式鎖,對DB還是造成一定的壓力。當(dāng)時(shí)考慮使用DB做分布式的一個重要原因是,我們的應(yīng)用是后端應(yīng)用,平時(shí)流量不大的,反而關(guān)鍵的是要保證庫存數(shù)據(jù)的正確性。對于像前端庫存系統(tǒng),比如添加購物車占用庫存等操作,最好別使用DB來實(shí)現(xiàn)分布式鎖了。

進(jìn)一步思考

如果想鎖住多份數(shù)據(jù)該怎么實(shí)現(xiàn)?比如說,某個庫存操作,既要修改物理庫存,又要修改虛擬庫存,想鎖住物理庫存的同時(shí),又鎖住虛擬庫存。其實(shí)也不是很難,參考lock方法,寫一個multiLock方法,提供多個transactionId的入?yún)ⅲ琭or循環(huán)處理就可以了。這個后續(xù)有時(shí)間再補(bǔ)上。

 

責(zé)任編輯:未麗燕 來源: 今日頭條
相關(guān)推薦

2024-01-09 08:20:05

2024-07-29 09:57:47

2023-01-12 08:24:45

ZookeeperZK服務(wù)器

2022-07-06 08:01:05

數(shù)據(jù)庫分布式

2019-02-26 09:51:52

分布式鎖RedisZookeeper

2021-10-25 10:21:59

ZK分布式鎖ZooKeeper

2023-08-21 19:10:34

Redis分布式

2022-01-06 10:58:07

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

2024-11-28 15:11:28

2020-11-16 12:55:41

Redis分布式鎖Zookeeper

2019-07-16 09:22:10

RedisZookeeper分布式鎖

2022-03-04 09:54:04

Redis分布式鎖腳本

2019-06-19 15:40:06

分布式鎖RedisJava

2024-04-26 08:06:58

分布式系統(tǒng)

2025-01-07 08:37:35

2023-12-01 08:39:29

分布式鎖系統(tǒng)

2020-10-19 07:30:57

Java Redis 開發(fā)

2024-10-07 10:07:31

2021-02-28 07:49:28

Zookeeper分布式

2017-01-16 14:13:37

分布式數(shù)據(jù)庫
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

97在线看免费观看视频在线观看| 日韩一区二区三区三四区视频在线观看 | 日韩女优一区二区| 午夜日韩影院| 欧美专区日韩专区| 国产爆乳无码一区二区麻豆| 色资源在线观看| 精一区二区三区| 97超碰蝌蚪网人人做人人爽| 黑人と日本人の交わりビデオ| 国语精品视频| 日本久久电影网| 韩国无码av片在线观看网站| 瑟瑟在线观看| 国产麻豆成人传媒免费观看| 青青草国产精品一区二区| 男女性高潮免费网站| 色爱综合av| 欧美一区二区精品在线| 日本成人中文字幕在线| 天堂av中文在线| 欧美国产成人精品| 久久精品国产一区二区三区日韩| 99国产揄拍国产精品| 日欧美一区二区| 韩国v欧美v日本v亚洲| 情侣偷拍对白清晰饥渴难耐| 欧美成a人免费观看久久| 欧美日韩国产精选| 不要播放器的av网站| 国产精品186在线观看在线播放| 国产精品久久久一区麻豆最新章节| 国产精品yjizz| 国产精品探花视频| 热久久一区二区| 欧美在线观看网站| 亚洲一区二区91| 欧美成人综合| 久久九九全国免费精品观看| 在线观看亚洲大片短视频| 欧美挤奶吃奶水xxxxx| 精品日韩欧美在线| 久久精品无码一区二区三区毛片| 成人av色网站| 欧美综合亚洲图片综合区| 116极品美女午夜一级| av在线资源| 精品久久香蕉国产线看观看亚洲| 日韩精品一区二区免费| 亚洲图区一区| 夜夜亚洲天天久久| 99久re热视频精品98| 成人国产免费电影| 亚洲乱码中文字幕| 国产精品8888| 日本中文字幕中出在线| 亚洲美女屁股眼交3| 69精品丰满人妻无码视频a片| 51xtv成人影院| 亚洲综合丁香婷婷六月香| 国产一级片91| 激情网站在线| 精品欧美国产一区二区三区| 秋霞无码一区二区| 欧美一级鲁丝片| 色综合久久久久久久久| 国产欧美在线一区| 成人在线视频免费| 911精品国产一区二区在线| 免费黄频在线观看| 中文久久电影小说| 日韩av在线看| 91视频免费在观看| 久久久久电影| 久久久久久久久久久久久久久久久久av | 亚洲特黄一级片| www.18av.com| 极品av在线| 日韩欧美国产高清91| 自拍偷拍 国产| 成年永久一区二区三区免费视频| 91精品国产麻豆| 欧美一级片黄色| 国产精品亚洲人成在99www| 中文字幕欧美专区| 久草国产在线观看| 亚洲综合激情| 成人免费福利视频| 欧美一区二区三区成人片在线| 91亚洲永久精品| 一本色道久久综合亚洲精品婷婷| 日本乱理伦在线| 日本久久一区二区| 在线播放黄色av| 日韩精品亚洲aⅴ在线影院| 一区二区三区高清国产| 无码黑人精品一区二区| 日韩午夜在线电影| 91精品久久久久久久久久入口| 亚洲精品人妻无码| 国产片一区二区| 欧美精品卡一卡二| 国产欧美自拍| 日韩久久午夜影院| 暗呦丨小u女国产精品| 99这里有精品| 91蜜桃网站免费观看| 精品影院一区| 亚洲亚洲人成综合网络| 污版视频在线观看| 日韩电影在线观看完整免费观看| 中文字幕亚洲图片| 中文字幕日韩一级| 国产麻豆91精品| 亚洲欧美日韩精品久久久 | 青青色在线视频| 亚洲精品欧美在线| 天天爽人人爽夜夜爽| 欧美激情网址| 久久久噜噜噜久久久| 中文字幕一区二区免费| 久久综合九色综合欧美就去吻 | 精品国产一区二区三区免费| 免费观看在线午夜影视| 色国产综合视频| 大桥未久恸哭の女教师| 欧美a级片一区| 成人性教育视频在线观看| 番号集在线观看| 色婷婷激情一区二区三区| av在线播放网址| 国产精品黄色| 9a蜜桃久久久久久免费| 成人看片免费| 欧美一二三四在线| 四虎影院中文字幕| 久久精品国产亚洲一区二区三区| 日本一区二区三不卡| 性爽视频在线| 精品亚洲永久免费精品 | 欧美日韩一区二区在线视频| 日本黄色特级片| 国产精品毛片在线看| 国产一区二区三区免费不卡| 日韩另类在线| 精品电影一区二区| 97超碰人人干| 91视频91自| 久久久久狠狠高潮亚洲精品| 欧美一级一片| 日韩美女视频免费在线观看| 天堂在线中文资源| 夜夜嗨一区二区三区| 91中文字幕在线观看| 在线观看男女av免费网址| 91精品国产欧美日韩| 老湿机69福利| 福利电影一区二区| 国产a级片网站| 卡通动漫精品一区二区三区| 午夜精品视频网站| 日本免费不卡| 欧美日韩国产经典色站一区二区三区| 欧美日韩生活片| 国产美女精品人人做人人爽| 成人在线观看毛片| 卡一精品卡二卡三网站乱码| 日韩av不卡在线| av女优在线| 欧美一区二区日韩| 日本天堂网在线观看| 久久看人人爽人人| 欧美性猛交xxxx乱大交91| 欧美激情91| 欧美国产综合视频| 成人在线不卡| 欧美激情视频在线观看| 五月婷在线视频| 欧美视频日韩视频| 国产盗摄x88av| 91丝袜美腿高跟国产极品老师| 日韩中文字幕二区| 亚洲综合中文| 久久精品国产精品国产精品污 | 在线观看av一区二区| 任我爽在线视频| 成人精品免费网站| 99热手机在线| 黄色成人精品网站| 日产中文字幕在线精品一区| 精品国产18久久久久久二百| 97人洗澡人人免费公开视频碰碰碰| 国产对白叫床清晰在线播放| 日韩一级视频免费观看在线| 91久久国产视频| 亚洲视频在线观看三级| 黄色性生活一级片| 精品一区二区国语对白| 亚洲欧洲日产国码无码久久99| 青青草国产免费一区二区下载| 国产伦理久久久| 人人精品久久| 奇米四色中文综合久久| 亚洲91av| 色噜噜国产精品视频一区二区| 天天操天天操天天干| 欧美乱熟臀69xxxxxx| 中国一级免费毛片| 亚洲男女毛片无遮挡| 精品人妻无码一区二区三区换脸| 国产麻豆成人传媒免费观看| 国产成人手机视频| 99在线精品视频在线观看| 中文字幕第一页亚洲| 欧美色网址大全| 久久99精品久久久久久久青青日本 | 国内揄拍国内精品久久| 亚洲视频电影| 欧美精品一二| 久久久久一区二区| 成人另类视频| 超碰97国产在线| 日韩欧国产精品一区综合无码| 欧洲日本亚洲国产区| 激情影院在线| 欧美国产日本高清在线| а√天堂8资源在线官网| 在线性视频日韩欧美| 黄色免费在线播放| 亚洲精品之草原avav久久| www.com在线观看| 3atv在线一区二区三区| 伊人亚洲综合网| 91成人免费在线视频| 国产超碰人人爽人人做人人爱| 一级特黄大欧美久久久| 好吊色视频在线观看| 日韩理论片中文av| 91香蕉一区二区三区在线观看| 欧美激情一区在线| 欧美熟妇激情一区二区三区| 久久美女高清视频| 妺妺窝人体色WWW精品| 久久精品无码一区二区三区| 野外性满足hd| 久久免费电影网| 一级特黄曰皮片视频| 国产欧美一区二区精品久导航 | 91精品国产91久久久| 91美女精品| 国产91ⅴ在线精品免费观看| 日韩影院在线| 青青在线视频一区二区三区 | 91免费在线视频网站| 大胆国模一区二区三区| 51精品国产人成在线观看 | 黄色视屏在线免费观看| 2019亚洲男人天堂| 久久电影tv| 国产精品永久免费视频| 中文字幕日韩亚洲| aa成人免费视频| 久久夜色电影| 欧洲久久久久久| 欧美1级片网站| 国产乱子伦精品视频| 亚洲二区精品| 亚洲精品怡红院| 国产在线观看免费一区| 97中文字幕在线观看| 91在线视频播放| 你懂得视频在线观看| 亚洲码国产岛国毛片在线| 日韩成人高清视频| 91成人国产精品| 99久久精品无免国产免费| 精品成人佐山爱一区二区| 黄色影院在线播放| 欧美成人免费va影院高清| 天堂中文在线播放| 国产欧美一区二区三区久久| 亚洲日本va| 日韩一区国产在线观看| 欧美在线影院| 日本一本二本在线观看| 精品亚洲porn| 搡老熟女老女人一区二区| 国产精品色呦呦| 国产成人精品亚洲男人的天堂| 色综合久久99| 亚洲国产福利视频| 一区二区在线视频播放| 羞羞视频在线观看免费| 日韩美女激情视频| 9国产精品午夜| 亚洲精品一品区二品区三品区| 欧美亚洲不卡| 在线观看免费视频高清游戏推荐| 粉嫩一区二区三区在线看| 日韩女同一区二区三区| 亚洲国产欧美一区二区三区丁香婷| 久久精品视频5| 日韩欧美亚洲国产精品字幕久久久| 久久av少妇| 久久久久久这里只有精品| 丁香婷婷久久| 美女亚洲精品| 精品二区视频| 色婷婷一区二区三区在线观看| 久久免费精品国产久精品久久久久 | 色婷婷中文字幕| 不卡毛片在线看| 深夜视频一区二区| 精品乱码一区二区三区| 亚洲美女视频| 欧美成人乱码一二三四区免费| 91丨九色丨尤物| 国产精彩视频在线观看| 制服丝袜国产精品| 91美女视频在线| 日韩免费精品视频| 欧美做受69| 成人精品视频在线播放| 国产麻豆日韩欧美久久| 欧美美女性生活视频| 欧美亚一区二区| 精品999视频| 欧美一区在线直播| 日韩av不卡一区| 黄色成人在线看| 丰满放荡岳乱妇91ww| 久久久久久欧美精品se一二三四 | 水中色av综合| 久久免费视频网| 91精品国产自产精品男人的天堂| 色香蕉在线观看| 狠狠v欧美v日韩v亚洲ⅴ| 日本激情视频一区二区三区| 欧美日韩情趣电影| 免费黄色在线| 91久久久久久| 中文视频一区| 中文字幕乱码在线人视频| 亚洲男人的天堂网| 亚洲伦理在线观看| 91精品国产91久久久久| 欧美日韩另类图片| 人妻有码中文字幕| 久久久久国产精品麻豆ai换脸| 国产精品久久久久久久久久精爆| 亚洲欧美另类中文字幕| 日韩成人影音| 亚洲精品乱码视频| 国产在线精品免费| 国产亚洲精品码| 亚洲电影在线看| 亚洲欧洲自拍| 色爱区成人综合网| 精品一二线国产| 久久久久久欧美精品se一二三四| 亚洲第一av网站| 男人最爱成人网| 亚洲一区二区精品在线观看| 精品在线观看视频| 久久久久久久久久综合| 国产午夜精品麻豆| 成人在线免费av| 青青在线视频免费观看| 91小视频在线观看| 伊人亚洲综合网| 国内精品小视频| av一区二区高清| 久久精品无码一区二区三区毛片| 亚洲电影一区二区三区| 成人在线二区| 99免费在线视频观看| 国产精品五区| 欧美性猛交xxxx乱大交少妇| 日韩三区在线观看| 桃色av一区二区| 正在播放国产精品| 白白色亚洲国产精品| 最近中文字幕在线观看| 欧美韩国理论所午夜片917电影| 亚洲精品推荐| 中文字幕久久av| 精品福利免费观看| 国产精品久久麻豆| 久久久久久久久久码影片| 精油按摩中文字幕久久| 亚洲精品www久久久久久| 日韩在线小视频| 欧美调教视频| 91欧美一区二区三区| 色一情一乱一乱一91av| 新版中文在线官网| 视频一区不卡| 91在线视频18| 亚洲狼人综合网| 国产日产久久高清欧美一区|