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

簡單幾步,設計一個高性能的秒殺系統!

開發 架構 開發工具
本次采用循序漸進的方式逐步提高性能達到并發秒殺的效果,文章較長,請準備好瓜子板凳!

 本次采用循序漸進的方式逐步提高性能達到并發秒殺的效果,文章較長,請準備好瓜子板凳!

[[269065]] 

圖片來自包圖網

之前在 Java-Interview 中提到過秒殺架構的設計,這次基于其中的理論簡單實現了一下。

本文所有涉及的代碼:

  • https://github.com/crossoverJie/SSM
  • https://github.com/crossoverJie/distributed-redis-tool

首先來看看最終架構圖:

 

先簡單根據這個圖談下請求的流轉,因為后面不管怎么改進,這些都是不變的:

  • 前端請求進入 Web 層,對應的代碼就是 Controller。
  • 之后將真正的庫存校驗、下單等請求發往 Service 層,其中 RPC 調用依然采用的 Dubbo,只是更新為***版本。
  • Service 層再對數據進行落地,下單完成。

***制

拋開秒殺這個場景來說,正常的一個下單流程可以簡單分為以下幾步:

  • 校驗庫存
  • 扣庫存
  • 創建訂單
  • 支付

基于上文的架構,我們有了以下實現,先看看實際項目的結構:

 

還是和以前一樣:

  • 提供出一個 API 用于 Service 層實現,以及 Web 層消費。
  • Web 層簡單來說就是一個 Spring MVC。
  • Service 層則是真正的數據落地。
  • SSM-SECONDS-KILL-ORDER-CONSUMER 則是后文會提到的 Kafka 消費。

數據庫也是只有簡單的兩張表模擬下單:

  1. CREATE TABLE `stock` ( 
  2.   `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
  3.   `namevarchar(50) NOT NULL DEFAULT '' COMMENT '名稱'
  4.   `countint(11) NOT NULL COMMENT '庫存'
  5.   `sale` int(11) NOT NULL COMMENT '已售'
  6.   `version` int(11) NOT NULL COMMENT '樂觀鎖,版本號'
  7.   PRIMARY KEY (`id`) 
  8. ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; 
  9.  
  10.  
  11. CREATE TABLE `stock_order` ( 
  12.   `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
  13.   `sid` int(11) NOT NULL COMMENT '庫存ID'
  14.   `namevarchar(30) NOT NULL DEFAULT '' COMMENT '商品名稱'
  15.   `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '創建時間'
  16.   PRIMARY KEY (`id`) 
  17. ) ENGINE=InnoDB AUTO_INCREMENT=55 DEFAULT CHARSET=utf8; 

Web 層 Controller 實現:

  1. @Autowired 
  2.    private StockService stockService; 
  3.  
  4.    @Autowired 
  5.    private OrderService orderService; 
  6.  
  7.    @RequestMapping("/createWrongOrder/{sid}"
  8.    @ResponseBody 
  9.    public String createWrongOrder(@PathVariable int sid) { 
  10.        logger.info("sid=[{}]", sid); 
  11.        int id = 0; 
  12.        try { 
  13.            id = orderService.createWrongOrder(sid); 
  14.        } catch (Exception e) { 
  15.            logger.error("Exception",e); 
  16.        } 
  17.        return String.valueOf(id); 
  18.    } 

其中 Web 作為一個消費者調用看 OrderService 提供出來的 Dubbo 服務。

Service 層, OrderService 實現,首先是對 API 的實現(會在 API 提供出接口):

  1. @Service 
  2. public class OrderServiceImpl implements OrderService { 
  3.  
  4.     @Resource(name = "DBOrderService"
  5.     private com.crossoverJie.seconds.kill.service.OrderService orderService ; 
  6.  
  7.     @Override 
  8.     public int createWrongOrder(int sid) throws Exception { 
  9.         return orderService.createWrongOrder(sid); 
  10.     } 

這里只是簡單調用了 DBOrderService 中的實現,DBOrderService 才是真正的數據落地,也就是寫數據庫了。

DBOrderService 實現:

  1. Transactional(rollbackFor = Exception.class) 
  2. @Service(value = "DBOrderService"
  3. public class OrderServiceImpl implements OrderService { 
  4.     @Resource(name = "DBStockService"
  5.     private com.crossoverJie.seconds.kill.service.StockService stockService; 
  6.  
  7.     @Autowired 
  8.     private StockOrderMapper orderMapper; 
  9.  
  10.     @Override 
  11.     public int createWrongOrder(int sid) throws Exception{ 
  12.  
  13.         //校驗庫存 
  14.         Stock stock = checkStock(sid); 
  15.  
  16.         //扣庫存 
  17.         saleStock(stock); 
  18.  
  19.         //創建訂單 
  20.         int id = createOrder(stock); 
  21.  
  22.         return id; 
  23.     } 
  24.  
  25.     private Stock checkStock(int sid) { 
  26.         Stock stock = stockService.getStockById(sid); 
  27.         if (stock.getSale().equals(stock.getCount())) { 
  28.             throw new RuntimeException("庫存不足"); 
  29.         } 
  30.         return stock; 
  31.     } 
  32.  
  33.     private int saleStock(Stock stock) { 
  34.         stock.setSale(stock.getSale() + 1); 
  35.         return stockService.updateStockById(stock); 
  36.     } 
  37.  
  38.     private int createOrder(Stock stock) { 
  39.         StockOrder order = new StockOrder(); 
  40.         order.setSid(stock.getId()); 
  41.         order.setName(stock.getName()); 
  42.         int id = orderMapper.insertSelective(order); 
  43.         return id; 
  44.     }         
  45.  

預先初始化了 10 條庫存。手動調用下 createWrongOrder/1 接口發現:

 

庫存表

 

訂單表

一切看起來都沒有問題,數據也正常。但是當用 JMeter 并發測試時:

 

測試配置是:300 個線程并發。測試兩輪來看看數據庫中的結果:

 

請求都響應成功,庫存確實也扣完了,但是訂單卻生成了 124 條記錄。這顯然是典型的超賣現象。

其實現在再去手動調用接口會返回庫存不足,但為時晚矣。

樂觀鎖更新

怎么來避免上述的現象呢?最簡單的做法自然是樂觀鎖了,來看看具體實現:

其實其他的都沒怎么改,主要是 Service 層:

  1. @Override 
  2.    public int createOptimisticOrder(int sid) throws Exception { 
  3.  
  4.        //校驗庫存 
  5.        Stock stock = checkStock(sid); 
  6.  
  7.        //樂觀鎖更新庫存 
  8.        saleStockOptimistic(stock); 
  9.  
  10.        //創建訂單 
  11.        int id = createOrder(stock); 
  12.  
  13.        return id; 
  14.    } 
  15.  
  16.    private void saleStockOptimistic(Stock stock) { 
  17.        int count = stockService.updateStockByOptimistic(stock); 
  18.        if (count == 0){ 
  19.            throw new RuntimeException("并發更新庫存失敗") ; 
  20.        } 
  21.    } 

對應的 XML:

  1. <update id="updateByOptimistic" parameterType="com.crossoverJie.seconds.kill.pojo.Stock"
  2.        update stock 
  3.        <set
  4.            sale = sale + 1, 
  5.            version = version + 1, 
  6.        </set
  7.  
  8.        WHERE id = #{id,jdbcType=INTEGER
  9.        AND version = #{version,jdbcType=INTEGER
  10.  
  11.    </update

同樣的測試條件,我們再進行上面的測試 /createOptimisticOrder/1:

 

這次發現無論是庫存訂單都是 OK 的。

查看日志發現:

 

很多并發請求會響應錯誤,這就達到了效果。

提高吞吐量

為了進一步提高秒殺時的吞吐量以及響應效率,這里的 Web 和 Service 都進行了橫向擴展:

  • Web 利用 Nginx 進行負載。
  • Service 也是多臺應用。

 

再用 JMeter 測試時可以直觀的看到效果。

由于我是在阿里云的一臺小水管服務器進行測試的,加上配置不高、應用都在同一臺,所以并沒有完全體現出性能上的優勢( Nginx 做負載轉發時候也會增加額外的網絡消耗)。

Shell 腳本實現簡單的 CI

由于應用多臺部署之后,手動發版測試的痛苦相信經歷過的都有體會。

這次并沒有精力去搭建完整的 CICD,只是寫了一個簡單的腳本實現了自動化部署,希望給這方面沒有經驗的同學帶來一點啟發。

構建 Web:

  1. #!/bin/bash 
  2.  
  3. # 構建 web 消費者 
  4.  
  5. #read appname 
  6.  
  7. appname="consumer" 
  8. echo "input="$appname 
  9.  
  10. PID=$(ps -ef | grep $appname | grep -v grep | awk '{print $2}'
  11.  
  12. # 遍歷殺掉 pid 
  13. for var in ${PID[@]}; 
  14. do 
  15.     echo "loop pid= $var" 
  16.     kill -9 $var 
  17. done 
  18.  
  19. echo "kill $appname success" 
  20.  
  21. cd .. 
  22.  
  23. git pull 
  24.  
  25. cd SSM-SECONDS-KILL 
  26.  
  27. mvn -Dmaven.test.skip=true clean package 
  28.  
  29. echo "build war success" 
  30.  
  31. cp /home/crossoverJie/SSM/SSM-SECONDS-KILL/SSM-SECONDS-KILL-WEB/target/SSM-SECONDS-KILL-WEB-2.2.0-SNAPSHOT.war /home/crossoverJie/tomcat/tomcat-dubbo-consumer-8083/webapps 
  32. echo "cp tomcat-dubbo-consumer-8083/webapps ok!" 
  33.  
  34. cp /home/crossoverJie/SSM/SSM-SECONDS-KILL/SSM-SECONDS-KILL-WEB/target/SSM-SECONDS-KILL-WEB-2.2.0-SNAPSHOT.war /home/crossoverJie/tomcat/tomcat-dubbo-consumer-7083-slave/webapps 
  35. echo "cp tomcat-dubbo-consumer-7083-slave/webapps ok!" 
  36.  
  37. sh /home/crossoverJie/tomcat/tomcat-dubbo-consumer-8083/bin/startup.sh 
  38. echo "tomcat-dubbo-consumer-8083/bin/startup.sh success" 
  39.  
  40. sh /home/crossoverJie/tomcat/tomcat-dubbo-consumer-7083-slave/bin/startup.sh 
  41. echo "tomcat-dubbo-consumer-7083-slave/bin/startup.sh success" 
  42.  
  43. echo "start $appname success" 

構建 Service:

  1. # 構建服務提供者 
  2.  
  3. #read appname 
  4.  
  5. appname="provider" 
  6.  
  7. echo "input="$appname 
  8.  
  9.  
  10. PID=$(ps -ef | grep $appname | grep -v grep | awk '{print $2}'
  11.  
  12. #if [ $? -eq 0 ]; then 
  13. #    echo "process id:$PID" 
  14. #else 
  15. #    echo "process $appname not exit" 
  16. #    exit 
  17. #fi 
  18.  
  19. # 遍歷殺掉 pid 
  20. for var in ${PID[@]}; 
  21. do 
  22.     echo "loop pid= $var" 
  23.     kill -9 $var 
  24. done 
  25.  
  26. echo "kill $appname success" 
  27.  
  28.  
  29. cd .. 
  30.  
  31. git pull 
  32.  
  33. cd SSM-SECONDS-KILL 
  34.  
  35. mvn -Dmaven.test.skip=true clean package 
  36.  
  37. echo "build war success" 
  38.  
  39. cp /home/crossoverJie/SSM/SSM-SECONDS-KILL/SSM-SECONDS-KILL-SERVICE/target/SSM-SECONDS-KILL-SERVICE-2.2.0-SNAPSHOT.war /home/crossoverJie/tomcat/tomcat-dubbo-provider-8080/webapps 
  40.  
  41. echo "cp tomcat-dubbo-provider-8080/webapps ok!" 
  42.  
  43. cp /home/crossoverJie/SSM/SSM-SECONDS-KILL/SSM-SECONDS-KILL-SERVICE/target/SSM-SECONDS-KILL-SERVICE-2.2.0-SNAPSHOT.war /home/crossoverJie/tomcat/tomcat-dubbo-provider-7080-slave/webapps 
  44.  
  45. echo "cp tomcat-dubbo-provider-7080-slave/webapps ok!" 
  46.  
  47. sh /home/crossoverJie/tomcat/tomcat-dubbo-provider-8080/bin/startup.sh 
  48. echo "tomcat-dubbo-provider-8080/bin/startup.sh success" 
  49.  
  50. sh /home/crossoverJie/tomcat/tomcat-dubbo-provider-7080-slave/bin/startup.sh 
  51. echo "tomcat-dubbo-provider-8080/bin/startup.sh success" 
  52.  
  53. echo "start $appname success" 

之后每當我有更新,只需要執行這兩個腳本就可以幫我自動構建。都是最基礎的 Linux 命令,相信大家都看得明白。

樂觀鎖更新 + 分布式限流

上文的結果看似沒有問題,其實還差得遠呢。這里只是模擬了 300 個并發沒有問題,但是當請求達到了 3000,3W,300W 呢?

雖說可以橫向擴展支撐更多的請求,但是能不能利用最少的資源解決問題呢?

仔細分析下會發現:假設我的商品一共只有 10 個庫存,那么無論你多少人來買其實最終也最多只有 10 人可以下單成功。所以其中會有 99% 的請求都是無效的。

大家都知道:大多數應用數據庫都是壓倒駱駝的***一根稻草。通過 Druid 的監控來看看之前請求數據庫的情況:

因為 Service 是兩個應用:

 

數據庫也有 20 多個連接。怎么樣來優化呢?其實很容易想到的就是分布式限流。

我們將并發控制在一個可控的范圍之內,然后快速失敗這樣就能***程度的保護系統。

①distributed-redis-tool ⬆v1.0.3

為此還對 https://github.com/crossoverJie/distributed-redis-tool 進行了小小的升級。

因為加上該組件之后所有的請求都會經過 Redis,所以對 Redis 資源的使用也是要非常小心。

②API 更新

修改之后的 API 如下:

  1. @Configuration 
  2. public class RedisLimitConfig { 
  3.  
  4.     private Logger logger = LoggerFactory.getLogger(RedisLimitConfig.class); 
  5.  
  6.     @Value("${redis.limit}"
  7.     private int limit; 
  8.  
  9.  
  10.     @Autowired 
  11.     private JedisConnectionFactory jedisConnectionFactory; 
  12.  
  13.     @Bean 
  14.     public RedisLimit build() { 
  15.         RedisLimit redisLimit = new RedisLimit.Builder(jedisConnectionFactory, RedisToolsConstant.SINGLE) 
  16.                 .limit(limit) 
  17.                 .build(); 
  18.  
  19.         return redisLimit; 
  20.     } 

這里構建器改用了 JedisConnectionFactory,所以得配合 Spring 來一起使用。

并在初始化時顯示傳入 Redis 是以集群方式部署還是單機(強烈建議集群,限流之后對 Redis 還是有一定的壓力)。

③限流實現

既然 API 更新了,實現自然也要修改:

  1. /** 
  2.   * limit traffic 
  3.   * @return if true 
  4.   */ 
  5.  public boolean limit() { 
  6.  
  7.      //get connection 
  8.      Object connection = getConnection(); 
  9.  
  10.      Object result = limitRequest(connection); 
  11.  
  12.      if (FAIL_CODE != (Long) result) { 
  13.          return true
  14.      } else { 
  15.          return false
  16.      } 
  17.  } 
  18.  
  19.  private Object limitRequest(Object connection) { 
  20.      Object result = null
  21.      String key = String.valueOf(System.currentTimeMillis() / 1000); 
  22.      if (connection instanceof Jedis){ 
  23.          result = ((Jedis)connection).eval(script, Collections.singletonList(key), Collections.singletonList(String.valueOf(limit))); 
  24.          ((Jedis) connection).close(); 
  25.      }else { 
  26.          result = ((JedisCluster) connection).eval(script, Collections.singletonList(key), Collections.singletonList(String.valueOf(limit))); 
  27.          try { 
  28.              ((JedisCluster) connection).close(); 
  29.          } catch (IOException e) { 
  30.              logger.error("IOException",e); 
  31.          } 
  32.      } 
  33.      return result; 
  34.  } 
  35.  
  36.  private Object getConnection() { 
  37.      Object connection ; 
  38.      if (type == RedisToolsConstant.SINGLE){ 
  39.          RedisConnection redisConnection = jedisConnectionFactory.getConnection(); 
  40.          connection = redisConnection.getNativeConnection(); 
  41.      }else { 
  42.          RedisClusterConnection clusterConnection = jedisConnectionFactory.getClusterConnection(); 
  43.          connection = clusterConnection.getNativeConnection() ; 
  44.      } 
  45.      return connection
  46.  } 

如果是原生的 Spring 應用得采用 @SpringControllerLimit(errorCode=200) 注解。

實際使用如下,Web 端:

  1. /** 
  2.      * 樂觀鎖更新庫存 限流 
  3.      * @param sid 
  4.      * @return 
  5.      */ 
  6.     @SpringControllerLimit(errorCode = 200) 
  7.     @RequestMapping("/createOptimisticLimitOrder/{sid}"
  8.     @ResponseBody 
  9.     public String createOptimisticLimitOrder(@PathVariable int sid) { 
  10.         logger.info("sid=[{}]", sid); 
  11.         int id = 0; 
  12.         try { 
  13.             id = orderService.createOptimisticOrder(sid); 
  14.         } catch (Exception e) { 
  15.             logger.error("Exception",e); 
  16.         } 
  17.         return String.valueOf(id); 
  18.     } 

Service 端就沒什么更新了,依然是采用的樂觀鎖更新數據庫。

再壓測看下效果 /createOptimisticLimitOrderByRedis/1:

首先是看結果沒有問題,再看數據庫連接以及并發請求數都有明顯的下降。

樂觀鎖更新+分布式限流+Redis 緩存

仔細觀察 Druid 監控數據發現這個 SQL 被多次查詢:

其實這是實時查詢庫存的 SQL,主要是為了在每次下單之前判斷是否還有庫存。

這也是個優化點。這種數據我們完全可以放在內存中,效率比在數據庫要高很多。

由于我們的應用是分布式的,所以堆內緩存顯然不合適,Redis 就非常適合。

  • 這次主要改造的是 Service 層:
  • 每次查詢庫存時走 Redis。
  • 扣庫存時更新 Redis。

需要提前將庫存信息寫入 Redis。(手動或者程序自動都可以)

主要代碼如下:

  1. @Override 
  2.   public int createOptimisticOrderUseRedis(int sid) throws Exception { 
  3.       //檢驗庫存,從 Redis 獲取 
  4.       Stock stock = checkStockByRedis(sid); 
  5.  
  6.       //樂觀鎖更新庫存 以及更新 Redis 
  7.       saleStockOptimisticByRedis(stock); 
  8.  
  9.       //創建訂單 
  10.       int id = createOrder(stock); 
  11.       return id ; 
  12.   } 
  13.  
  14.  
  15.   private Stock checkStockByRedis(int sid) throws Exception { 
  16.       Integer count = Integer.parseInt(redisTemplate.opsForValue().get(RedisKeysConstant.STOCK_COUNT + sid)); 
  17.       Integer sale = Integer.parseInt(redisTemplate.opsForValue().get(RedisKeysConstant.STOCK_SALE + sid)); 
  18.       if (count.equals(sale)){ 
  19.           throw new RuntimeException("庫存不足 Redis currentCount=" + sale); 
  20.       } 
  21.       Integer version = Integer.parseInt(redisTemplate.opsForValue().get(RedisKeysConstant.STOCK_VERSION + sid)); 
  22.       Stock stock = new Stock() ; 
  23.       stock.setId(sid); 
  24.       stock.setCount(count); 
  25.       stock.setSale(sale); 
  26.       stock.setVersion(version); 
  27.  
  28.       return stock; 
  29.   }     
  30.  
  31.  
  32.   /** 
  33.    * 樂觀鎖更新數據庫 還要更新 Redis 
  34.    * @param stock 
  35.    */ 
  36.   private void saleStockOptimisticByRedis(Stock stock) { 
  37.       int count = stockService.updateStockByOptimistic(stock); 
  38.       if (count == 0){ 
  39.           throw new RuntimeException("并發更新庫存失敗") ; 
  40.       } 
  41.       //自增 
  42.       redisTemplate.opsForValue().increment(RedisKeysConstant.STOCK_SALE + stock.getId(),1) ; 
  43.       redisTemplate.opsForValue().increment(RedisKeysConstant.STOCK_VERSION + stock.getId(),1) ; 
  44.   }     

壓測看看實際效果 /createOptimisticLimitOrderByRedis/1:

***發現數據沒問題,數據庫的請求與并發也都下來了。

樂觀鎖更新+分布式限流+Redis 緩存+Kafka 異步

***的優化還是想如何來再次提高吞吐量以及性能的。我們上文所有例子其實都是同步請求,完全可以利用同步轉異步來提高性能啊。

這里我們將寫訂單以及更新庫存的操作進行異步化,利用 Kafka 來進行解耦和隊列的作用。

每當一個請求通過了限流到達了 Service 層通過了庫存校驗之后就將訂單信息發給 Kafka ,這樣一個請求就可以直接返回了。

消費程序再對數據進行入庫落地。因為異步了,所以最終需要采取回調或者是其他提醒的方式提醒用戶購買完成。

這里代碼較多就不貼了,消費程序其實就是把之前的 Service 層的邏輯重寫了一遍,不過采用的是 Spring Boot。

總結

經過上面的一頓優化總結起來無非就是以下幾點:

  • 盡量將請求攔截在上游。
  • 還可以根據 UID 進行限流。
  • ***程度的減少請求落到 DB。
  • 多利用緩存。
  • 同步操作異步化。
  • Fail Fast,盡早失敗,保護應用。

碼字不易,這應該是我寫過字數最多的了,想想當年高中 800 字的作文都憋不出來😂,可想而知是有多難得了。

以上內容歡迎討論,感興趣的朋友可以看下:

  1. https://github.com/crossoverJie/SSM/tree/master/SSM-SECONDS-KILL/SSM-SECONDS-KILL-ORDER-CONSUMER 

 

 

責任編輯:武曉燕 來源: crossoverJie
相關推薦

2019-11-27 15:19:44

系統緩存架構

2025-10-28 02:00:00

秒殺系統客戶端并發

2025-01-22 08:00:00

架構秒殺系統Java

2022-07-18 08:02:16

秒殺系統后端

2023-07-26 13:29:43

高性能短鏈系統

2021-03-16 16:35:39

網關Java代碼

2024-06-17 11:59:39

2019-10-31 13:58:32

阿里電商系統

2024-06-21 08:15:25

2017-03-03 10:40:41

2011-09-14 10:08:07

Beanstalkd

2024-09-02 18:10:20

2018-11-22 14:09:45

iOS架構組件開發

2020-03-03 07:59:29

設計秒殺系統

2024-11-12 08:13:09

2024-11-19 16:31:23

2020-03-17 14:21:39

數據平臺架構

2021-08-30 09:30:29

Kafka高性能設計

2017-10-11 16:12:19

內存

2024-08-28 08:38:51

點贊
收藏

51CTO技術棧公眾號

日韩国产一区久久| 欧美国产视频日韩| wwwwwxxxx日本| 任你弄在线视频免费观看| 成人妖精视频yjsp地址| 人体精品一二三区| 亚洲少妇xxx| 久久a爱视频| 欧美日韩在线免费视频| av免费观看大全| 青青青青在线| 91香蕉视频mp4| 成人精品一区二区三区| www成人在线| 91成人精品视频| 亚洲天天在线日亚洲洲精| 国产伦精品一区二区三区妓女下载| 手机在线观看av网站| 中文字幕日韩精品一区| 蜜桃传媒一区二区| 午夜美女福利视频| 美国一区二区三区在线播放 | 4438亚洲最大| 国产黄色特级片| 波多野结衣精品| 亚洲三级免费观看| 天堂资源在线亚洲资源| 天天操天天干天天爱| 国产精品一区二区久久精品爱涩| 国产精品免费久久久| 五月婷婷开心网| 激情亚洲成人| 欧美国产视频一区二区| 四虎精品免费视频| 日韩免费视频| 伊人精品在线观看| 亚洲精品国产熟女久久久| 麻豆一区一区三区四区| 精品国免费一区二区三区| 日韩av加勒比| 亚洲综合资源| 欧美区一区二区三区| 看欧美ab黄色大片视频免费| 天堂中文av在线资源库| 动漫精品一区二区| 免费一级特黄毛片| 国产在线观看www| 亚洲国产精品尤物yw在线观看| 欧美日韩午夜爽爽| 四季久久免费一区二区三区四区| 亚洲女同女同女同女同女同69| 在线观看日韩片| 日本a在线播放| 中文文精品字幕一区二区| 日韩精品久久久免费观看| 精品电影在线| 国产精品污污网站在线观看| 日韩视频在线观看国产| 成人高清在线| 自拍偷拍欧美精品| 老司机午夜网站| 青春草免费在线视频| 亚洲一卡二卡三卡四卡五卡| 性一交一乱一伧国产女士spa| 欧美24videosex性欧美| 午夜精品久久久久影视| 97av视频在线观看| 免费亚洲电影| 欧美日韩黄色一区二区| 天天久久综合网| av综合网站| 亚洲毛片一区二区| 国产欧美小视频| 91精品婷婷色在线观看| 欧美激情一级欧美精品| 日韩经典在线观看| 日韩成人一级片| 成人疯狂猛交xxx| 亚洲AV无码精品自拍| 99久久精品99国产精品| 亚洲成人网上| 男女免费观看在线爽爽爽视频| 欧美日韩国产页| 亚洲一区在线不卡| 97一区二区国产好的精华液| 日韩av影视综合网| 69xxx免费| 黑丝一区二区三区| 国产精品久久久一区| 国产女人18毛片18精品| 93久久精品日日躁夜夜躁欧美| 欧美亚洲免费高清在线观看 | 国产精品27p| 国产老妇伦国产熟女老妇视频| 成人晚上爱看视频| 日韩videos| 色呦呦视频在线观看| 色老头久久综合| 精品人妻二区中文字幕| 欧美特黄一级大片| 欧美大片第1页| 欧美一级做a爰片免费视频| 国产高清在线精品| 日韩aⅴ视频一区二区三区| 性欧美1819sex性高清大胸| 色综合久久天天综合网| 91福利视频免费观看| 色综合综合网| 欧美精品激情在线| 97精品人妻一区二区三区| 99这里只有久久精品视频| 一区二区三区四区五区精品| 高清视频在线观看三级| 91精品国产一区二区三区香蕉| 黄瓜视频污在线观看| 欧美一区影院| 国产精品欧美日韩一区二区| 色视频在线观看免费| 亚洲天堂成人网| 少妇人妻互换不带套| 丁香综合av| 久久综合电影一区| 亚洲天堂网在线观看视频| 99精品视频在线观看免费| 特级黄色录像片| 成人精品国产亚洲| 亚洲欧美成人在线| 日本少妇激情舌吻| 国产乱子轮精品视频| 一区二区三视频| 亚洲电影有码| 国产一区二区三区在线视频| 国产成人一区二区三区影院在线| 懂色av中文一区二区三区| 精品一区二区成人免费视频| 激情欧美一区二区三区黑长吊| 日韩黄色高清视频| 日韩人妻无码一区二区三区99| 岛国精品在线观看| 久青草视频在线播放| 国产一区二区三区免费在线 | 国产精品综合二区| a级片免费视频| 福利视频999| 久久三级中文| 日韩在线国产精品| 制服丝袜在线一区| 国产欧美精品国产国产专区| 成年人网站大全| 久久综合五月| 日韩欧美国产电影| 欧美88888| 久久精品国产在热久久| 欧美亚洲另类久久综合| 日本美女一区| 亚洲天堂一区二区三区| 国产精品xxxxxx| 国产精品天天摸av网| 超碰在线播放91| 羞羞色午夜精品一区二区三区| 国产欧美久久一区二区| 久久99精品久久久久久野外| 91精品国产综合久久国产大片| 污软件在线观看| 国产成人精品午夜视频免费| avav在线播放| 欧美三级午夜理伦三级小说| 欧美综合在线观看| 国产精品秘入口| 欧美久久久影院| 欧美xxxx黑人xyx性爽| 成人禁用看黄a在线| 欧洲黄色一级视频| 青青草原综合久久大伊人精品| 国产精品一二区| 成人av黄色| 国产在线观看免费| 一区二区三区中文在线| 午夜久久久久久久| 日本少妇一区二区| 日韩精品手机在线观看| 噜噜噜狠狠夜夜躁精品仙踪林| 日韩av电影免费观看高清| 日本在线观看免费| 亚洲国产精品va在线看黑人动漫| 日韩国产成人在线| 一区二区欧美国产| 中文字幕在线观看免费高清| 精品一区二区在线播放| 91丨porny丨探花| 成人在线一区| 国产精品一码二码三码在线| 日韩电影免费观| 久久成人在线视频| 欧美婷婷久久五月精品三区| 欧美精品久久久久久久多人混战 | 欧美,日韩,国产在线| 精品久久网站| 国产美女精品在线观看| 在线成人视屏| 久久久亚洲欧洲日产国码aⅴ| а天堂8中文最新版在线官网| 日韩视频在线永久播放| 欧美日韩a v| 亚洲妇熟xx妇色黄| 日韩影院一区二区| 国产午夜精品一区二区 | 国产毛片久久久久| 色成人在线视频| 国产亚洲第一页| 亚洲日本中文字幕区| 亚洲天堂视频一区| 成人午夜碰碰视频| 古装做爰无遮挡三级聊斋艳谭| 日韩国产在线一| 99精品人妻少妇一区二区| 欧美人成在线| 国产精品亚洲天堂| 欧美在线观看视频一区| 久久视频在线观看中文字幕| 99国产精品免费网站| 成人网址在线观看| 99久久久国产精品免费调教网站| 97激碰免费视频| 日韩少妇视频| 另类专区欧美制服同性| av大片在线看| 中文字幕欧美专区| 精品无吗乱吗av国产爱色| 日韩精品视频中文在线观看| 亚洲av无码一区二区三区性色| 欧美人成免费网站| 亚洲天堂一二三| 欧美巨大另类极品videosbest| 无码人妻精品一区二区三区蜜桃91 | 国产午夜精品在线| 亚洲网一区二区三区| 91久久久久久久一区二区| 国产激情欧美| 国产精品一区二区三区久久| 天堂久久午夜av| 国产精品jizz在线观看麻豆| 欧美日韩大片| 国产99视频精品免视看7| 欧美成人精品一区二区男人小说| 26uuu国产精品视频| 亚洲免费福利| 国产成人一区二区在线| 美女网站视频一区| 国产日韩精品入口| 国产精品成人3p一区二区三区| 91久久久在线| 日韩最新av| 国产精品久久久久久久久久久久冷| 视频在线一区| 国产伦精品一区二区三区在线 | 亚洲精品国产综合区久久久久久久| 日本激情一区二区三区| 日韩电影第一页| 户外极限露出调教在线视频| 中文字幕欧美日韩在线| 黄色网页在线免费看| 欧美夫妻性生活xx| 日本午夜大片a在线观看| 欧美最猛性xxxx| 国产成人精选| 国产精品二区三区四区| 欧美精品中文字幕亚洲专区| 美女三级99| 欧美成人自拍| 亚洲午夜精品一区二区| 久久爱www成人| 亚洲精品白虎| 午夜日韩视频| 久在线观看视频| 日韩二区三区四区| 下面一进一出好爽视频| 成人精品一区二区三区四区 | 久久韩国免费视频| 欧美日韩经典丝袜| 欧美在线视频观看| 亚洲伦理久久| 国产精品制服诱惑| 欧美一区二区三区高清视频| 欧洲xxxxx| 亚洲欧美日韩国产| 成人av毛片在线观看| 99久久久国产精品免费蜜臀| 女人十八毛片嫩草av| 一区二区在线观看av| 国产午夜精品久久久久| 51久久夜色精品国产麻豆| 天堂在线中文| 久热精品视频在线观看| 欧美成人a交片免费看| 91久久大香伊蕉在人线| 国产精品一在线观看| 日韩一级特黄毛片| 日本成人在线视频网站| 欧美双性人妖o0| 1区2区3区欧美| 久久亚洲精品石原莉奈| 欧美v国产在线一区二区三区| 精品影院一区| 97视频网站入口| 精品一区91| 亚洲视频小说| 久久亚洲精选| 少妇一级淫免费观看| 日韩美女视频19| 久久这里只有精品9| 精品国产免费人成在线观看| 秋霞影院午夜丰满少妇在线视频| 国产69久久精品成人| 日韩国产在线不卡视频| 视频在线观看成人| 亚洲综合国产| 完美搭档在线观看| 亚洲综合激情网| 国产剧情精品在线| www国产精品com| 国产精品原创视频| 欧美一区二区视频17c| 一级成人国产| 一边摸一边做爽的视频17国产 | 福利网在线观看| 久久国产精品无码网站| 成人性生交大免费看| 婷婷开心激情综合| 欧美熟妇交换久久久久久分类| 欧美黑人视频一区| 五月亚洲婷婷| 久久香蕉视频网站| 国产精品系列在线观看| 亚洲波多野结衣| 在线成人午夜影院| 日本不卡在线| 91日韩在线播放| 欧美成人午夜| av电影中文字幕| 亚洲无人区一区| 韩国中文字幕hd久久精品| 欧美日韩国产va另类| 一区二区三区免费在线看| 国内自拍中文字幕| 成人综合激情网| 日本一区二区欧美| 日韩电影在线观看中文字幕| 男女羞羞在线观看| 欧美福利精品| 日本亚洲天堂网| 操她视频在线观看| 欧美一级爆毛片| 国产丝袜视频在线播放| 国产综合色一区二区三区| 国产欧美成人| 国产中年熟女高潮大集合| 欧美在线免费观看亚洲| 在线播放日本| 99久久99久久精品国产片| 激情亚洲网站| 无码人妻精品一区二区中文| 在线视频国内一区二区| jizzjizz亚洲| 九九九热999| 日韩成人伦理电影在线观看| 香蕉久久久久久久| 欧美成人精品二区三区99精品| 国产激情在线播放| 天天爽天天狠久久久| 国产精品伊人色| 免费观看成人毛片| 自拍偷拍亚洲一区| 成人免费在线电影网| 欧美三级午夜理伦三级| 中文字幕日韩av资源站| 人妻与黑人一区二区三区| 国产精品com| 欧美午夜久久| 国产一级久久久久毛片精品| 制服丝袜一区二区三区| 两个人看的在线视频www| 亚洲国产婷婷香蕉久久久久久99| 国产精品18久久久久久久久久久久| 欧美成人精品欧美一级乱黄| 中日韩美女免费视频网址在线观看 | 精品人妻无码一区二区三区| 欧美日韩亚州综合| 波多野结衣精品| 一区二区不卡在线| 白白色亚洲国产精品| 亚洲无码久久久久| 7777免费精品视频| 中文字幕免费一区二区| 右手影院亚洲欧美| 日韩三级中文字幕| 99只有精品| 国产一区二区在线视频播放| 中文字幕在线一区二区三区| 香蕉av在线播放|