精品欧美一区二区三区在线观看 _久久久久国色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ù)棧公眾號

国产精品1区| 黄色一级大片在线免费看产| 日韩亚洲国产精品| 亚洲美女免费精品视频在线观看| 无遮挡又爽又刺激的视频| 国产免费av高清在线| 国产米奇在线777精品观看| 久久久久国产精品免费| 国产美女免费网站| 日韩精品一区国产| 在线免费观看日韩欧美| 国产免费裸体视频| 国产福利在线| www.亚洲色图| 91精品在线一区| 在线精品免费视| 欧美成人一品| 国产亚洲欧美视频| 亚洲一级av无码毛片精品| 成人在线观看免费视频| 午夜精品123| 男女h黄动漫啪啪无遮挡软件| 五月激情六月婷婷| 国产精品综合在线视频| 国产精品91久久| 国产精品50页| 亚洲五月综合| 在线午夜精品自拍| 亚洲av无码一区二区三区观看| 精品亚洲二区| 欧美日韩精品电影| 免费日韩视频在线观看| 国产精品探花在线| 国产精品久久综合| 日本一区二区三区四区高清视频 | 日韩欧美自拍偷拍| 宅男噜噜噜66国产免费观看| 成人免费高清观看| 一区二区三区中文字幕电影| 中文字幕一区二区三区乱码| av在线之家电影网站| 26uuu精品一区二区三区四区在线 26uuu精品一区二区在线观看 | 成人一区二区三区在线观看| 亚洲精品免费网站| 在线观看免费视频a| 葵司免费一区二区三区四区五区| 69av在线播放| 人人干人人干人人干| 黑丝一区二区| 久久大大胆人体| 一本一本久久a久久| 久久社区一区| www.亚洲成人| avtt天堂在线| 欧美激情一区| 国内精品小视频在线观看| www.97视频| 亚洲成人日韩| 欧美福利视频在线观看| 欧美日韩在线观看免费| 国产一区久久| 午夜精品久久久久久久99热浪潮| 国产主播在线观看| 中文日韩在线| 国产精品白丝jk喷水视频一区| 秋霞精品一区二区三区| 久久性天堂网| 国产日韩欧美中文| 99热这里只有精品在线| 成人一区二区视频| 美女精品国产| av基地在线| 亚洲日本在线a| 国产美女永久无遮挡| 多野结衣av一区| 日本高清不卡视频| 中文字幕永久有效| 99这里只有精品视频| 亚洲国产日韩一区| 中文字幕av久久爽一区| 欧美第一精品| 亚洲**2019国产| 无码一区二区三区在线观看| 蜜桃视频一区二区三区在线观看| 成人黄色生活片| 免费看黄色一级视频| 久久先锋资源网| 麻豆中文字幕在线观看| 黄网av在线| 欧美午夜电影一区| 九色91porny| 亚洲区小说区| 欧美成人免费全部| 特黄视频免费看| 精品一区二区三区久久| 国产视频在线观看一区| 成人免费黄色网页| 亚洲男同性视频| 韩国日本在线视频| 欧美视频二区欧美影视| 亚洲欧美中文日韩在线| 国产少妇在线观看| 久久久久欧美精品| av观看久久| www.久久热.com| 亚洲国产人成综合网站| 91极品尤物在线播放国产| 视频在线观看免费影院欧美meiju 视频一区中文字幕精品 | 国产乱人伦精品一区| 中文字幕久精品免费视频| 国产无遮挡又黄又爽在线观看 | 日本一本在线视频| 红桃成人av在线播放| 欧美高清电影在线看| 毛片在线免费播放| 欧美精品亚州精品| 97中文在线观看| 人妻与黑人一区二区三区| 欧美激情一区二区三区| 丁香花在线影院观看在线播放| 欧美大片免费播放器| 亚洲精品久久久久久久久久久久久久 | 国产视频手机在线| 国产精品一品视频| 夜夜爽99久久国产综合精品女不卡 | 黄色精品网站| 国产精品一区二区性色av| 天堂v在线观看| 亚洲主播在线观看| 中文字幕第22页| 青青草91久久久久久久久| 欧美中在线观看| 午夜精品久久久久久久爽| 欧美国产国产综合| 亚洲综合在线网站| 日本一区二区三区视频在线看| 日韩亚洲欧美中文高清在线| 国产成人精品一区二三区| 国产成人8x视频一区二区| 婷婷精品国产一区二区三区日韩| 91超碰国产在线| 日韩欧美一区二区视频| 久久国产高清视频| 麻豆成人综合网| 日韩精品最新在线观看| 欧美影视资讯| 在线日韩欧美视频| 特级西西444www大胆免费看| 国产片一区二区| 黄色国产小视频| 国产精品一区二区av日韩在线| 欧美亚洲国产另类| 手机福利在线| 欧美日韩中国免费专区在线看| aaaa黄色片| 国产精品日韩| 欧美午夜欧美| 草莓视频成人appios| 在线播放日韩欧美| 在线观看av大片| 国产精品久久久久久福利一牛影视| 欧美在线aaa| 911精品美国片911久久久| 成人欧美一区二区三区黑人| 日本激情在线观看| 欧美一区二区三区爱爱| 国产精品久久久久久久精| 久久国产福利国产秒拍| 国产又黄又爽免费视频| 日韩免费成人| 18一19gay欧美视频网站| 亚洲区小说区图片区| 色天使久久综合网天天| 很污很黄的网站| 国产成人精品三级| 欧美有码在线观看| a黄色在线观看| 91精品国产乱码久久蜜臀| 久久免费少妇高潮99精品| 91视频免费观看| 天堂网在线免费观看| 欧美日本一区二区视频在线观看 | 久久久久久蜜桃一区二区| 亚洲欧洲美洲一区二区三区| 成人女人免费毛片| 成人软件在线观看| 欧美成人精品一区二区三区| 五月婷婷六月激情| 欧美色涩在线第一页| 欧美成人精品欧美一| 久久综合一区二区| 国内av一区二区| 国产午夜精品一区二区三区欧美| 亚洲国产欧美不卡在线观看 | 欧美大陆一区二区| 日韩免费在线电影| 91国产视频在线播放| 在线免费看黄网站| 日韩电影中文字幕在线| 国产毛片久久久久| 日本高清免费不卡视频| 精品午夜福利在线观看| 国产精品美女久久久久久久| 一级黄色片毛片| 久久99国内精品| 国内外免费激情视频| 欧美精品福利| 亚洲午夜激情| 综合色就爱涩涩涩综合婷婷| 亚洲tv在线观看| 国产经典一区| 51色欧美片视频在线观看| 国产欧美久久久久久久久| 国产一区二区日韩| 亚洲av片一区二区三区| 日韩欧美在线网站| 伊人网综合在线| 色综合久久88色综合天天免费| 免费中文字幕在线观看| 中文字幕日韩一区二区| 一色道久久88加勒比一| 99久久精品国产麻豆演员表| 白丝校花扒腿让我c| 黄色精品一二区| 久久久久久蜜桃一区二区| 麻豆成人在线| 国产成人在线免费看| 激情视频一区| 久久www视频| 性欧美欧美巨大69| 永久免费精品视频网站| 成人久久久久| 香蕉久久夜色| 精品久久久久中文字幕小说| 麻豆av一区| 亚洲ab电影| 欧美xxxx黑人又粗又长密月 | 亚洲免费av电影| 亚洲av激情无码专区在线播放| 亚洲电影免费观看高清完整版在线| 国产欧美综合视频| 91精品国产综合久久久久久久久久 | 免费黄网在线观看| 日韩在线视频网站| 午夜免费播放观看在线视频| 最新69国产成人精品视频免费| 91涩漫在线观看| 中文字幕亚洲一区在线观看 | 亚洲免费在线电影| 国产少妇在线观看| 一区二区在线看| 免费中文字幕在线观看| 亚洲电影第三页| 97久久久久久久| 色婷婷av一区| 中文字幕乱码中文字幕| 欧美视频一区二| 夜夜躁狠狠躁日日躁av| 欧美一区二区久久| 性一交一乱一精一晶| 亚洲国产成人av在线| 青青草视频免费在线观看| 亚洲人成77777在线观看网| 岛国在线视频免费看| 综合久久五月天| 菠萝菠萝蜜在线视频免费观看 | 中文在线最新版地址| 国产精品成人免费视频| 免费成人高清在线视频| 91久久精品www人人做人人爽| 日韩免费高清视频网站| 久久96国产精品久久99软件| 国内精品视频在线观看| 中文字幕在线中文字幕日亚韩一区| 欧美另类女人| 久久美女福利视频| 久久av中文字幕片| 波多野结衣办公室双飞| 91老师国产黑色丝袜在线| 欧美88888| 午夜在线成人av| 中文字幕一区二区人妻电影| 欧美人妖巨大在线| 欧美视频xxx| 中文精品99久久国产香蕉| 怡红院在线播放| 日韩美女中文字幕| 在线观看欧美| 久久日韩精品| 亚洲女同另类| 久久综合久久色| 国产精品1024久久| 国产成人福利在线| 亚洲小说欧美激情另类| 欧美日韩 一区二区三区| 日韩三级视频在线观看| 黄色毛片在线看| 欧美二区在线播放| 久久91超碰青草在哪里看| 国产欧美韩日| 99久久99久久精品国产片桃花| 成人毛片视频网站| 国产精品88888| 第一次破处视频| 午夜伦理一区二区| 国产精品色综合| 中文欧美在线视频| 小早川怜子影音先锋在线观看| 亚洲最大的免费| 欧美自拍偷拍| 爱福利视频一区二区| 国产xxx精品视频大全| 永久av免费网站| 在线观看亚洲专区| 亚洲日本国产精品| 欧美国产日韩精品| 999精品视频在线观看| 欧洲国产精品| 亚洲一区二区成人| 婷婷五月精品中文字幕| 亚洲欧美日韩国产另类专区| 在线免费一区二区| 亚洲欧美www| 三级中文字幕在线观看| 国产成人免费观看| 中文字幕免费一区二区| 久热精品在线播放| 中文字幕乱码日本亚洲一区二区| 久草手机在线视频| 亚洲国内精品在线| 欧美一卡二卡| 亚洲自拍小视频免费观看| 天堂美国久久| 一本色道久久亚洲综合精品蜜桃| 国产日韩精品一区二区三区在线| 亚洲精品男人天堂| 日韩高清欧美高清| 18aaaa精品欧美大片h| 国产 高清 精品 在线 a| 欧美精品国产| 成人欧美精品一区二区| 一区二区三区四区激情| a视频免费在线观看| 久久av在线看| 97久久综合区小说区图片区| 激情五月六月婷婷| 国产99久久久国产精品潘金网站| 欧美日韩偷拍视频| 欧美xxxx老人做受| xxxcom在线观看| 精品一区久久久| 先锋影音久久| 日本一级免费视频| 欧美唯美清纯偷拍| 人人干在线视频| 亚洲最大的成人网| 亚洲国产精品第一区二区三区| 在线免费播放av| 色狠狠色噜噜噜综合网| 都市激情一区| 91香蕉嫩草影院入口| 欧美特黄a级高清免费大片a级| 性欧美18—19sex性高清| 欧美小视频在线观看| 成人全视频高清免费观看| 国产精品一区二区三区在线播放 | 一级片在线观看视频| 久久精品国产69国产精品亚洲| 成人短视频软件网站大全app| www国产无套内射com| 99久久99久久综合| 夜夜爽妓女8888视频免费观看| 中文字幕日韩专区| 一区二区在线视频观看| 男人添女人下面高潮视频| 国产欧美日产一区| 国产色综合视频| 欧美亚洲激情在线| 99精品小视频| 风间由美一二三区av片| 欧美日韩在线直播| h片在线观看| 亚洲在线视频一区二区| 成人av在线一区二区三区| 91视频在线视频| 欧美成人在线网站| 国产精品欧美在线观看| 亚洲综合123| 一本色道久久综合亚洲aⅴ蜜桃| 亚洲成a人v欧美综合天堂麻豆| 国产精品久久一区二区三区| 久久一本综合频道| 玖玖爱免费视频| 国产一区二区三区丝袜| 澳门成人av| 亚洲涩涩在线观看| 欧美性猛交xxxx富婆| 18videosex性欧美麻豆| 日韩和欧美的一区二区| 成人晚上爱看视频|