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

利用DB實現分布式鎖的思路

數據庫 其他數據庫 后端 分布式
以前參加過一個庫存系統,由于其業務復雜性,搞了很多個應用來支撐。這樣的話一份庫存數據就有可能同時有多個應用來修改庫存數據。比如說,有定時任務域xx.cron,和SystemA域和SystemB域這幾個JAVA應用,可能同時修改同一份庫存數據。如果不做協調的話,就會有臟數據出現。對于跨JAVA進程的線程協調,可以借助外部環境,例如DB或者Redis。下文介紹一下如何使用DB來實現分布式鎖。

[[225288]]

概述

以前參加過一個庫存系統,由于其業務復雜性,搞了很多個應用來支撐。這樣的話一份庫存數據就有可能同時有多個應用來修改庫存數據。比如說,有定時任務域xx.cron,和SystemA域和SystemB域這幾個JAVA應用,可能同時修改同一份庫存數據。如果不做協調的話,就會有臟數據出現。對于跨JAVA進程的線程協調,可以借助外部環境,例如DB或者Redis。下文介紹一下如何使用DB來實現分布式鎖。

設計

本文設計的分布式鎖的交互方式如下:

1、根據業務字段生成transaction_id,并線程安全的創建鎖資源

2、根據transaction_id申請鎖

3、釋放鎖

動態創建鎖資源

在使用synchronized關鍵字的時候,必須指定一個鎖對象。

synchronized(obj) { }

進程內的線程可以基于obj來實現同步。obj在這里可以理解為一個鎖對象。如果線程要進入synchronized代碼塊里,必須先持有obj對象上的鎖。這種鎖是JAVA里面的內置鎖,創建的過程是線程安全的。那么借助DB,如何保證創建鎖的過程是線程安全的呢?可以利用DB中的UNIQUE KEY特性,一旦出現了重復的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 '事務id' 
  4.     last_update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL COMMENT '***更新時間' 
  5.     create_time TIMESTAMP DEFAULT '0000-00-00 00:00:00' NOT NULL COMMENT '創建時間' 
  6.     UNIQUE KEY `idx_transaction_id` (`transaction_id`)  

transaction_id是事務Id,比如說,可以用

倉庫 + 條碼 + 銷售模式

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

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

DB連接池列表設計

在寫操作頻繁的業務系統中,通常會進行分庫,以降低單數據庫寫入的壓力,并提高寫操作的吞吐量。如果使用了分庫,那么業務數據自然也都分配到各個數據庫上了。在這種水平切分的多數據庫上使用DB分布式鎖,可以自定義一個DataSouce列表。并暴露一個getConnection(String transactionId)方法,按照transactionId找到對應的Connection。

實現代碼如下:

 

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

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

 

  1. DLOCK_NUM=2   
  2. DLOCK_USER_0="user1"  
  3. DLOCK_PASS_0="pass1"  
  4. DLOCK_INIT_SIZE_0=2  
  5. DLOCK_MAX_SIZE_0=10  
  6. DLOCK_URL_0="jdbc:mysql://localhost:3306/test1" 
  7.   
  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。

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

連接池列表設計好后,就可以實現往distributed_lock表插入數據了。

 

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

根據transactionId鎖住線程

接下來利用DB的select for update特性來鎖住線程。當多個線程根據相同的transactionId并發同時操作select for update的時候,只有一個線程能成功,其他線程都block住,直到select for update成功的線程使用commit操作后,block住的所有線程的其中一個線程才能開始干活。我們在上面的DistributedLock類中創建一個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.     } 

實現解鎖操作

當線程執行完任務后,必須手動的執行解鎖操作,之前被鎖住的線程才能繼續干活。在我們上面的實現中,其實就是獲取到當時select for update成功的線程對應的Connection,并實行commit操作即可。

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

 

  1. private ThreadLocal threadLocalConn = new ThreadLocal(); 

每次調用lock方法的時候,把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.             if (resultSet != null) {  
  29.                 resultSet.close();  
  30.             } 
  31.  
  32.             if (connection != null) {  
  33.                 connection.close();  
  34.             }  
  35.         }  
  36.     } 

這樣子,當獲取到Connection后,將其設置到ThreadLocal中,如果lock方法出現異常,則將其從ThreadLocal中移除掉。

有了這幾步后,我們可以來實現解鎖操作了。我們在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.     } 

缺點

畢竟是利用DB來實現分布式鎖,對DB還是造成一定的壓力。當時考慮使用DB做分布式的一個重要原因是,我們的應用是后端應用,平時流量不大的,反而關鍵的是要保證庫存數據的正確性。對于像前端庫存系統,比如添加購物車占用庫存等操作,***別使用DB來實現分布式鎖了。

進一步思考

 

如果想鎖住多份數據該怎么實現?比如說,某個庫存操作,既要修改物理庫存,又要修改虛擬庫存,想鎖住物理庫存的同時,又鎖住虛擬庫存。其實也不是很難,參考lock方法,寫一個multiLock方法,提供多個transactionId的入參,for循環處理就可以了。這個后續有時間再補上。 

責任編輯:龐桂玉 來源: 數據庫開發
相關推薦

2015-05-18 09:59:48

ZooKeeper分布式計算Hadoop

2024-11-28 15:11:28

2019-06-19 15:40:06

分布式鎖RedisJava

2021-02-28 07:49:28

Zookeeper分布式

2017-01-16 14:13:37

分布式數據庫

2018-04-03 16:24:34

分布式方式

2022-04-08 08:27:08

分布式鎖系統

2017-04-13 10:51:09

Consul分布式

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數據分布式鎖

2024-10-09 17:12:34

2022-10-27 10:44:14

分布式Zookeeper

2023-03-01 08:07:51

2023-09-13 09:52:14

分布式鎖Java

2024-10-07 10:07:31

2024-07-29 09:57:47

2024-01-02 13:15:00

分布式鎖RedissonRedis

2024-04-01 05:10:00

Redis數據庫分布式鎖
點贊
收藏

51CTO技術棧公眾號

亚洲男人天堂久久| 一级做a爰片毛片| caoporm免费视频在线| 激情综合色播激情啊| 欧美日韩国产成人| 国产美女视频免费观看下载软件| 成人影院大全| 亚洲天堂网中文字| 国产aⅴ精品一区二区三区黄| 国产一级一级片| 尤物tv在线精品| 在线电影院国产精品| 国产精品专区在线| av影片在线看| jlzzjlzz亚洲日本少妇| 国产精品尤物福利片在线观看| 青青草激情视频| 久久最新网址| 欧美大片一区二区| jizz欧美激情18| 国产极品人妖在线观看| 中文字幕高清不卡| 精品高清视频| 国产av无码专区亚洲av| 久久综合伊人| 欧美激情免费在线| 大地资源高清在线视频观看| 亚洲日产av中文字幕| 日韩午夜小视频| 久久婷五月综合| 深夜av在线| 一区二区三区高清不卡| 一区二区精品在线| 每日更新在线观看av| 丁香啪啪综合成人亚洲小说 | 亚洲一区二区自偷自拍 | 久久综合给合久久狠狠色| 99久久精品国产成人一区二区| 日欧美一区二区| 亚州国产精品久久久| 欧美成人三级在线观看| 偷偷www综合久久久久久久| 亚洲视屏在线播放| 久久亚洲AV成人无码国产野外| 中文字幕区一区二区三| 91精品国产一区二区三区| 超碰在线人人爱| 粉嫩一区二区三区| 色狠狠av一区二区三区| 国产特级黄色大片| 黄色漫画在线免费看| 亚洲妇女屁股眼交7| 无码人妻精品一区二区蜜桃网站| 中文字幕有码在线观看| 亚洲色图欧洲色图婷婷| 综合视频免费看| 免费a在线看| 国产精品黄色在线观看| 一本色道久久综合亚洲精品婷婷 | 久久这里只有精品视频网| 国产在线精品一区二区三区| 亚洲乱色熟女一区二区三区| 国产成人精品亚洲777人妖| 99re6在线| 亚洲第一视频在线播放| 成人av资源站| 久久久久久久久久久一区| 亚洲人在线观看视频| 91免费在线视频观看| 欧美日韩国产不卡在线看| 九色视频网站在线观看| 欧美国产丝袜视频| 免费观看中文字幕| 国产亚av手机在线观看| 精品国产电影一区| 欧美日韩亚洲一二三| 国产成人精品一区二三区在线观看| 欧美亚日韩国产aⅴ精品中极品| 天堂社区在线视频| 成人午夜888| 亚洲成人动漫在线播放| www.久久国产| 色中色综合网| 欧美激情小视频| 中文字幕视频网站| 久久国产精品第一页| 亚洲字幕一区二区| 日韩a在线观看| 国产精品久久久久久久久图文区| 久久久久亚洲av无码专区喷水| 色黄网站在线观看| 色国产综合视频| 亚洲男人天堂2021| 女仆av观看一区| 最新69国产成人精品视频免费| 欧美国产日韩在线观看成人| 国产亚洲精品自拍| 国产日韩亚洲欧美| 韩国av在线免费观看| 国产丝袜在线精品| 人妻互换免费中文字幕| 九九热线视频只有这里最精品| 91精品国产色综合久久不卡蜜臀| 亚洲男人在线天堂| 亚洲天堂免费| 日本伊人精品一区二区三区介绍| 97人妻人人澡人人爽人人精品| www.亚洲在线| 在线天堂一区av电影| 久草在线资源站手机版| 欧美精品精品一区| 最近中文字幕免费视频| 黑人一区二区| 国产视频999| 欧美男男同志| 亚洲第一搞黄网站| 九九九九九九九九| 国产欧美日韩影院| 性欧美视频videos6一9| 国产精品伦理一区| 国产亚洲精品超碰| 国产精品国产亚洲精品看不卡| 亚洲欧洲专区| 国产一区二区三区网站| 800av免费在线观看| 国产成人无遮挡在线视频| 亚洲午夜精品福利| 日韩美女在线看免费观看| 亚洲变态欧美另类捆绑| 免费成年人视频在线观看| 日本不卡一区二区三区高清视频| 精品视频在线观看| 女子免费在线观看视频www| 欧美美女激情18p| 在线免费观看视频| 日韩精品一二区| 鲁丝一区鲁丝二区鲁丝三区| av美女在线观看| 日韩精品一区二区三区在线| 中文字幕五月天| 久久国产日韩欧美精品| 色综合电影网| 少妇精品视频一区二区免费看| 精品在线欧美视频| 国产尤物在线视频| 97aⅴ精品视频一二三区| 成人午夜精品久久久久久久蜜臀| 91大神精品| 欧美日韩国产二区| www国产在线| 亚洲一区中文在线| 在线精品视频播放| 最新日韩欧美| 久久亚洲免费| 成人美女大片| 亚洲欧美三级伦理| 国产一卡二卡三卡| 中日韩av电影| 一级 黄 色 片一| 一区二区三区四区在线观看国产日韩| 成人h视频在线观看播放| 日韩免费网站| 欧美一区二区国产| 欧美日韩在线观看成人| 国产成人在线观看免费网站| 日韩精品免费一区| 精品国产一区二区三区不卡蜜臂 | 国产真实乱人偷精品视频| 风间由美性色一区二区三区| 2018日日夜夜| 视频国产一区| 国产精品影片在线观看| 伊人影院在线视频| 亚洲精品在线免费观看视频| 中文字幕亚洲高清| 国产欧美久久久精品影院| 亚洲色图 在线视频| 亚洲电影影音先锋| 好吊色欧美一区二区三区| 亚洲第一影院| 精品国产一区二区三区久久久狼| 精品毛片一区二区三区| 午夜国产精品一区| 懂色av粉嫩av浪潮av| 国产精品一二二区| 男人天堂网视频| 久久在线视频免费观看| av成人综合网| 色豆豆成人网| 欧美美女操人视频| 欧美日韩免费做爰大片| 欧美一区二区啪啪| 亚洲图片在线视频| 亚洲三级小视频| 精品人妻一区二区三区香蕉| 久久国产精品色婷婷| 免费看又黄又无码的网站| 91亚洲成人| 久久精品中文字幕一区二区三区| 青青国产精品| 欧美在线视频免费播放| 成人国产免费电影| 一区二区欧美激情| 色婷婷av一区二区三| 欧美日韩1区2区| 久久久成人免费视频| 一区二区三区自拍| 少妇的滋味中文字幕bd| 99久久婷婷国产综合精品| 国产亚洲视频一区| 美女被久久久| av高清在线免费观看| 99久精品视频在线观看视频| 免费h精品视频在线播放| 日本少妇精品亚洲第一区| 国产精品久久久久久久av大片| 国产精品186在线观看在线播放| 日韩在线观看免费高清| 欧美女子与性| 亚洲激情免费观看| 亚洲av无码乱码国产精品| 欧美性大战久久久| 成人公开免费视频| 午夜视频久久久久久| 欧美日韩在线视频免费| 国产精品久久毛片a| 扒开jk护士狂揉免费| 成人午夜免费av| 欧美视频亚洲图片| 免费的成人av| 日韩在线第三页| 亚洲毛片一区| www.av蜜桃| 欧美欧美全黄| 精品国产一区二区三区在线| 欧美日韩国产免费观看视频| 精品一区二区日本| 久草在线综合| 国产99在线播放| 亚洲小说春色综合另类电影| 99精品欧美一区二区三区| 24小时成人在线视频| 国产日韩精品一区二区| 国产亚洲欧美日韩精品一区二区三区| 国产999精品久久久影片官网| 日本蜜桃在线观看视频| 91精品国产色综合久久不卡98| 麻豆蜜桃在线| 国语自产精品视频在线看一大j8 | 欧美在线一区二区视频| 伊人网在线播放| 热久久视久久精品18亚洲精品| 中日韩脚交footjobhd| 欧美综合国产精品久久丁香| 激情都市亚洲| 国产精品久久久久久久久免费看| 免费观看成人性生生活片| 国产精品福利在线观看网址| 国产a亚洲精品| 国产精品自产拍在线观看中文| 国产精品亲子伦av一区二区三区| 国产欧美一区二区三区视频| 亚洲伊人精品酒店| 成人欧美一区二区三区在线观看| 中文字幕一区二区三区中文字幕 | 97免费视频在线| 97人澡人人添人人爽欧美| 欧美亚洲视频在线观看| 久久精品女人天堂av免费观看| 国产精品美女免费看| av日韩在线免费观看| 91视频婷婷| 欧美一级色片| 五月天综合网| 伊人久久大香线蕉精品组织观看| 91大学生片黄在线观看| 国产婷婷精品| 超碰人人草人人| 播五月开心婷婷综合| 熟女少妇内射日韩亚洲| 亚洲人妖av一区二区| 精品91久久久| 欧美日韩亚洲综合一区| www.四虎在线观看| 精品无人国产偷自产在线| 尤物在线视频| 久久久久久久影院| 日韩高清在线| 99爱精品视频| 国产欧美高清视频在线| 中文字幕の友人北条麻妃| 亚洲综合社区| 黄色三级视频在线播放| 久久伊人蜜桃av一区二区| 91人妻一区二区三区蜜臀| 日韩欧美大尺度| 精品久久久久中文慕人妻| 亚洲人成在线播放| 少妇视频在线| 国产精品亚洲一区二区三区| a看欧美黄色女同性恋| 先锋影音一区二区三区| 黑丝一区二区三区| 国内外成人免费在线视频| 99精品视频在线观看免费| 中文字幕手机在线观看| 在线精品观看国产| 人妻va精品va欧美va| 色偷偷av一区二区三区| 涩涩涩视频在线观看| 91九色露脸| 欧美gvvideo网站| 国产成人亚洲精品无码h在线 | 少妇户外露出[11p]| 亚洲男同性恋视频| 最近中文字幕av| 日韩精品久久久久| 麻豆网站免费观看| 国产精品扒开做爽爽爽的视频| 亚洲深夜福利在线| 9999在线视频| 91精品综合久久| 久久久久久影院| 深夜黄色小视频| 久久亚洲综合色| 中日韩黄色大片| 亚洲大胆人体在线| 色呦呦网站在线观看| 亚洲va欧美va国产综合剧情| 日韩精品第一区| 亚洲一区二区蜜桃| 久久精品视频在线免费观看| 黄色片免费观看视频| 精品99久久久久久| 国产精品偷拍| 国产精品欧美久久| 激情久久五月| 国产av一区二区三区传媒| 亚洲乱码中文字幕综合| 国产偷拍一区二区| 久久成人精品视频| 精品午夜视频| 国产欧美综合一区| 国产成人h网站| 久久久一区二区三区四区| 日韩精品一区二区三区三区免费| 91精品久久久久久粉嫩| 97久草视频| 亚洲激情av| 国产精品第七页| 日韩欧美在线免费观看| 国产资源在线播放| 国产精品久久国产精品99gif| 国产成人1区| 在线观看国产中文字幕| **性色生活片久久毛片| 国产视频手机在线| 欧美国产日韩二区| 久久人人爽人人爽人人片av不| 三上悠亚久久精品| 91蜜桃网址入口| 激情网站在线观看| 这里只有精品在线观看| 欧美视频免费看| 久久久久久久香蕉| 不卡一区在线观看| 不卡av电影在线| 日韩视频亚洲视频| 成人影院中文字幕| 黄色免费视频大全| 国产精品日韩成人| 99国产精品欲| 91a在线视频| 欧美在线电影| 四虎国产精品永久免费观看视频| 亚洲国产一区二区a毛片| 久久久久久女乱国产| 国产综合福利在线| 尤物在线精品| 日韩精品无码一区二区三区久久久 | 欧美女孩性生活视频| 18+激情视频在线| 久久精品国产第一区二区三区最新章节 | 91丨九色丨蝌蚪丨老版| 中国a一片一级一片| 久久99久久99精品免观看粉嫩| 欧美一区二区三区久久| 少妇网站在线观看| 亚洲妇女屁股眼交7| 1区2区3区在线观看| 国产伦精品一区二区三区照片91| 日韩激情视频在线观看| 午夜少妇久久久久久久久| 国产视频亚洲视频| 久久久久亚洲精品中文字幕| 国产在线观看福利| 亚洲黄色尤物视频| 嫩草研究院在线观看| 97视频中文字幕| 日韩av成人高清|