成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

七種分布式全局 ID 生成策略,你更愛哪種?

網(wǎng)絡(luò) 通信技術(shù) 分布式
當(dāng)數(shù)據(jù)庫分庫分表之后,原本的主鍵自增就不方便繼續(xù)使用了,需要找到一個(gè)新的合適的方案,松哥的需求就是在這樣的情況下提出的。

[[415300]]

上了微服務(wù)之后,很多原本很簡單的問題現(xiàn)在都變復(fù)雜了,例如全局 ID 這事!

松哥最近工作中剛好用到這塊內(nèi)容,于是調(diào)研了市面上幾種常見的全局 ID 生成策略,稍微做了一下對比,供小伙伴們參考。

當(dāng)數(shù)據(jù)庫分庫分表之后,原本的主鍵自增就不方便繼續(xù)使用了,需要找到一個(gè)新的合適的方案,松哥的需求就是在這樣的情況下提出的。

接下來我們一起來捋一捋。

1. 兩種思路

整體上來說,這個(gè)問題有兩種不同的思路:

  • 讓數(shù)據(jù)庫自己搞定
  • Java 代碼來處理主鍵,然后直接插入數(shù)據(jù)庫中即可

這兩種思路又對應(yīng)了不同的方案,我們一個(gè)一個(gè)來看。

2. 數(shù)據(jù)庫自己搞定

數(shù)據(jù)庫自己搞定,就是說我在數(shù)據(jù)插入的時(shí)候,依然不考慮主鍵的問題,希望繼續(xù)使用數(shù)據(jù)庫的主鍵自增,但是很明顯,原本默認(rèn)的主鍵自增現(xiàn)在沒法用了,我們必須有新的方案。

2.1 修改數(shù)據(jù)庫配置

數(shù)據(jù)庫分庫分表之后的結(jié)構(gòu)如下圖(假設(shè)數(shù)據(jù)庫中間件用的 MyCat):

此時(shí)如果原本的 db1、db2、db3 繼續(xù)各自主鍵自增,那么對于 MyCat 而言,主鍵就不是自增了,主鍵就會(huì)重復(fù),用戶從 MyCat 中查詢到的數(shù)據(jù)主鍵就有問題。

找到問題的原因,那么剩下的就好解決了。

我們可以直接修改 MySQL 數(shù)據(jù)庫主鍵自增的起始值和步長。

首先我們可以通過如下 SQL 查看與此相關(guān)的兩個(gè)變量的取值:

  1. SHOW VARIABLES LIKE 'auto_increment%' 

可以看到,主鍵自增的起始值和步長都是 1。

起始值好改,在定義表的時(shí)候就可以設(shè)置,步長我們可以通過修改這個(gè)配置實(shí)現(xiàn):

  1. set @@auto_increment_increment=9; 

修改后,再去查看對應(yīng)的變量值,發(fā)現(xiàn)已經(jīng)變了:

此時(shí)我們再去插入數(shù)據(jù),主鍵自增就不是每次自增 1,而是每次自增 9 了。

至于自增起始值其實(shí)很好設(shè)置,創(chuàng)建表的時(shí)候就可以設(shè)置了。

  1. create table test01(id integer PRIMARY KEY auto_increment,username varchar(255)) auto_increment=8; 

既然 MySQL 可以修改自增的起始值和每次增長的步長,現(xiàn)在假設(shè)我有 db1、db2 和 db3,我就可以分別設(shè)置這三個(gè)庫中表的自增起始值為 1、2、3,然后自增步長都是 3,這樣就可以實(shí)現(xiàn)自增了。

但是很明顯這種方式不夠優(yōu)雅,而且處理起來很麻煩,將來擴(kuò)展也不方便,因此不推薦。

2.2 MySQL+MyCat+ZooKeeper

如果大家分庫分表工具恰好使用的是 MyCat,那么結(jié)合 Zookeeper 也能很好的實(shí)現(xiàn)主鍵全局自增。

MyCat 作為一個(gè)分布式數(shù)據(jù)庫中間,屏蔽了數(shù)據(jù)庫集群的操作,讓我們操作數(shù)據(jù)庫集群就像操作單機(jī)版數(shù)據(jù)庫一樣,對于主鍵自增,它有自己的方案:

  • 通過本地文件實(shí)現(xiàn)
  • 通過數(shù)據(jù)庫實(shí)現(xiàn)
  • 通過本地時(shí)間戳實(shí)現(xiàn)
  • 通過分布式 ZK ID 生成器實(shí)現(xiàn)
  • 通過 ZK 遞增方式實(shí)現(xiàn)

這里我們主要來看方案 4。

配置步驟如下:

  • 首先修改主鍵自增方式為 4 ,4 表示使用 zookeeper 實(shí)現(xiàn)主鍵自增。

server.xml

  • 配置表自增,并且設(shè)置主鍵

schema.xml

設(shè)置主鍵自增,并且設(shè)置主鍵為 id 。

  • 配置 zookeeper 的信息

在 myid.properties 中配置 zookeeper 信息:

  • 配置要自增的表

sequence_conf.properties

注意,這里表名字要大寫。

  1. TABLE.MINID 某線程當(dāng)前區(qū)間內(nèi)最小值
  2. TABLE.MAXID 某線程當(dāng)前區(qū)間內(nèi)最大值
  3. TABLE.CURID 某線程當(dāng)前區(qū)間內(nèi)當(dāng)前值
  4. 文件配置的MAXID以及MINID決定每次取得區(qū)間,這個(gè)對于每個(gè)線程或者進(jìn)程都有效
  5. 文件中的這三個(gè)屬性配置只對第一個(gè)進(jìn)程的第一個(gè)線程有效,其他線程和進(jìn)程會(huì)動(dòng)態(tài)讀取 ZK
  • 重啟 MyCat 測試

最后重啟 MyCat ,刪掉之前創(chuàng)建的表,然后創(chuàng)建新表進(jìn)行測試即可。

這種方式就比較省事一些,而且可擴(kuò)展性也比較強(qiáng),如果選擇了 MyCat 作為分庫分表工具,那么這種不失為一種最佳方案。

前面介紹這兩種都是在數(shù)據(jù)庫或者數(shù)據(jù)庫中間件層面來處理主鍵自增,我們 Java 代碼并不需要額外工作。

接下來我們再來看幾種需要在 Java 代碼中進(jìn)行處理的方案。

3. Java 代碼處理

3.1 UUID

最容易想到的就是 UUID (Universally Unique Identifier) 了, UUID 的標(biāo)準(zhǔn)型式包含 32 個(gè) 16 進(jìn)制數(shù)字,以連字號分為五段,形式為 8-4-4-4-12 的 36 個(gè)字符,這個(gè)是 Java 自帶的,用著也簡單,最大的優(yōu)勢就是本地生成,沒有網(wǎng)絡(luò)消耗,但是但凡在公司做開發(fā)的小伙伴都知道這個(gè)東西在公司項(xiàng)目中使用并不多。原因如下:

  1. 字符串太長,對于 MySQL 而言,不利于索引。
  2. UUID 的隨機(jī)性對于 I/O 密集型的應(yīng)用非常不友好!它會(huì)使得聚簇索引的插入變得完全隨機(jī),使得數(shù)據(jù)沒有任何聚集特性。
  3. 信息不安全:基于 MAC 地址生成 UUID 的算法可能會(huì)造成 MAC 地址泄露,這個(gè)漏洞曾被用于尋找梅麗莎病毒的制作者位置。

因此,UUID 并非最佳方案。

3.2 SNOWFLAKE

雪花算法是由 Twitter 公布的分布式主鍵生成算法,它能夠保證不同進(jìn)程主鍵的不重復(fù)性,以及相同進(jìn)程主鍵的有序性。在同一個(gè)進(jìn)程中,它首先是通過時(shí)間位保證不重復(fù),如果時(shí)間相同則是通過序列位保證。

同時(shí)由于時(shí)間位是單調(diào)遞增的,且各個(gè)服務(wù)器如果大體做了時(shí)間同步,那么生成的主鍵在分布式環(huán)境可以認(rèn)為是總體有序的,這就保證了對索引字段的插入的高效性。

例如 MySQL 的 Innodb 存儲(chǔ)引擎的主鍵。使用雪花算法生成的主鍵,二進(jìn)制表示形式包含 4 部分,從高位到低位分表為:1bit 符號位、41bit 時(shí)間戳位、10bit 工作進(jìn)程位以及 12bit 序列號位。

  • 符號位 (1bit)

預(yù)留的符號位,恒為零。

  • 時(shí)間戳位 (41bit)

41 位的時(shí)間戳可以容納的毫秒數(shù)是 2 的 41 次冪,一年所使用的毫秒數(shù)是:365 * 24 * 60 * 60 * 1000。通過計(jì)算可知:Math.pow(2, 41) / (365 * 24 * 60 * 60 * 1000L);結(jié)果約等于 69.73 年。

ShardingSphere 的雪花算法的時(shí)間紀(jì)元從 2016 年 11 月 1 日零點(diǎn)開始,可以使用到 2086 年,相信能滿足絕大部分系統(tǒng)的要求。

  • 工作進(jìn)程位 (10bit)

該標(biāo)志在 Java 進(jìn)程內(nèi)是唯一的,如果是分布式應(yīng)用部署應(yīng)保證每個(gè)工作進(jìn)程的 id 是不同的。該值默認(rèn)為 0,可通過屬性設(shè)置。

  • 序列號位 (12bit)

該序列是用來在同一個(gè)毫秒內(nèi)生成不同的 ID。如果在這個(gè)毫秒內(nèi)生成的數(shù)量超過 4096 (2 的 12 次冪),那么生成器會(huì)等待到下個(gè)毫秒繼續(xù)生成。

注意:該算法存在 時(shí)鐘回?fù)? 問題,服務(wù)器時(shí)鐘回?fù)軙?huì)導(dǎo)致產(chǎn)生重復(fù)序列,因此默認(rèn)分布式主鍵生成器提供了一個(gè)最大容忍的時(shí)鐘回?fù)芎撩霐?shù)。如果時(shí)鐘回?fù)艿臅r(shí)間超過最大容忍的毫秒數(shù)閾值,則程序報(bào)錯(cuò);如果在可容忍的范圍內(nèi),默認(rèn)分布式主鍵生成器會(huì)等待時(shí)鐘同步到最后一次主鍵生成的時(shí)間后再繼續(xù)工作。最大容忍的時(shí)鐘回?fù)芎撩霐?shù)的默認(rèn)值為 0,可通過屬性設(shè)置。

下面松哥給出一個(gè)雪花算法的工具類,大家可以參考:

  1. public class IdWorker { 
  2.     // 時(shí)間起始標(biāo)記點(diǎn),作為基準(zhǔn),一般取系統(tǒng)的最近時(shí)間(一旦確定不能變動(dòng)) 
  3.     private final static long twepoch = 1288834974657L; 
  4.     // 機(jī)器標(biāo)識位數(shù) 
  5.     private final static long workerIdBits = 5L; 
  6.     // 數(shù)據(jù)中心標(biāo)識位數(shù) 
  7.     private final static long datacenterIdBits = 5L; 
  8.     // 機(jī)器ID最大值 
  9.     private final static long maxWorkerId = -1L ^ (-1L << workerIdBits); 
  10.     // 數(shù)據(jù)中心ID最大值 
  11.     private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); 
  12.     // 毫秒內(nèi)自增位 
  13.     private final static long sequenceBits = 12L; 
  14.     // 機(jī)器ID偏左移12位 
  15.     private final static long workerIdShift = sequenceBits; 
  16.     // 數(shù)據(jù)中心ID左移17位 
  17.     private final static long datacenterIdShift = sequenceBits + workerIdBits; 
  18.     // 時(shí)間毫秒左移22位 
  19.     private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; 
  20.  
  21.     private final static long sequenceMask = -1L ^ (-1L << sequenceBits); 
  22.     /* 上次生產(chǎn)id時(shí)間戳 */ 
  23.     private static long lastTimestamp = -1L; 
  24.     // 0,并發(fā)控制 
  25.     private long sequence = 0L; 
  26.  
  27.     private final long workerId; 
  28.     // 數(shù)據(jù)標(biāo)識id部分 
  29.     private final long datacenterId; 
  30.  
  31.     public IdWorker(){ 
  32.         this.datacenterId = getDatacenterId(maxDatacenterId); 
  33.         this.workerId = getMaxWorkerId(datacenterId, maxWorkerId); 
  34.     } 
  35.  
  36.     /** 
  37.      * @param workerId 
  38.      *            工作機(jī)器ID 
  39.      * @param datacenterId 
  40.      *            序列號 
  41.      */ 
  42.     public IdWorker(long workerId, long datacenterId) { 
  43.         if (workerId > maxWorkerId || workerId < 0) { 
  44.             throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); 
  45.         } 
  46.         if (datacenterId > maxDatacenterId || datacenterId < 0) { 
  47.             throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); 
  48.         } 
  49.         this.workerId = workerId; 
  50.         this.datacenterId = datacenterId; 
  51.     } 
  52.  
  53.     /** 
  54.      * 獲取下一個(gè)ID 
  55.      * 
  56.      * @return 
  57.      */ 
  58.     public synchronized long nextId() { 
  59.         long timestamp = timeGen(); 
  60.         if (timestamp < lastTimestamp) { 
  61.             throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); 
  62.         } 
  63.  
  64.         if (lastTimestamp == timestamp) { 
  65.             // 當(dāng)前毫秒內(nèi),則+1 
  66.             sequence = (sequence + 1) & sequenceMask; 
  67.             if (sequence == 0) { 
  68.                 // 當(dāng)前毫秒內(nèi)計(jì)數(shù)滿了,則等待下一秒 
  69.                 timestamp = tilNextMillis(lastTimestamp); 
  70.             } 
  71.         } else { 
  72.             sequence = 0L; 
  73.         } 
  74.         lastTimestamp = timestamp
  75.         // ID偏移組合生成最終的ID,并返回ID 
  76.         long nextId = ((timestamp - twepoch) << timestampLeftShift) 
  77.                 | (datacenterId << datacenterIdShift) 
  78.                 | (workerId << workerIdShift) | sequence
  79.  
  80.         return nextId; 
  81.     } 
  82.  
  83.     private long tilNextMillis(final long lastTimestamp) { 
  84.         long timestamp = this.timeGen(); 
  85.         while (timestamp <= lastTimestamp) { 
  86.             timestamp = this.timeGen(); 
  87.         } 
  88.         return timestamp
  89.     } 
  90.  
  91.     private long timeGen() { 
  92.         return System.currentTimeMillis(); 
  93.     } 
  94.  
  95.     /** 
  96.      * <p> 
  97.      * 獲取 maxWorkerId 
  98.      * </p> 
  99.      */ 
  100.     protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) { 
  101.         StringBuffer mpid = new StringBuffer(); 
  102.         mpid.append(datacenterId); 
  103.         String name = ManagementFactory.getRuntimeMXBean().getName(); 
  104.         if (!name.isEmpty()) { 
  105.             /* 
  106.              * GET jvmPid 
  107.              */ 
  108.             mpid.append(name.split("@")[0]); 
  109.         } 
  110.         /* 
  111.          * MAC + PID 的 hashcode 獲取16個(gè)低位 
  112.          */ 
  113.         return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1); 
  114.     } 
  115.  
  116.     /** 
  117.      * <p> 
  118.      * 數(shù)據(jù)標(biāo)識id部分 
  119.      * </p> 
  120.      */ 
  121.     protected static long getDatacenterId(long maxDatacenterId) { 
  122.         long id = 0L; 
  123.         try { 
  124.             InetAddress ip = InetAddress.getLocalHost(); 
  125.             NetworkInterface network = NetworkInterface.getByInetAddress(ip); 
  126.             if (network == null) { 
  127.                 id = 1L; 
  128.             } else { 
  129.                 byte[] mac = network.getHardwareAddress(); 
  130.                 id = ((0x000000FF & (long) mac[mac.length - 1]) 
  131.                         | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6; 
  132.                 id = id % (maxDatacenterId + 1); 
  133.             } 
  134.         } catch (Exception e) { 
  135.             System.out.println(" getDatacenterId: " + e.getMessage()); 
  136.         } 
  137.         return id; 
  138.     } 

用法如下:

  1. IdWorker idWorker = new IdWorker(0, 0); 
  2. for (int i = 0; i < 1000; i++) { 
  3.     System.out.println(idWorker.nextId()); 

3.3 LEAF

Leaf 是美團(tuán)開源的分布式 ID 生成系統(tǒng),最早期需求是各個(gè)業(yè)務(wù)線的訂單 ID 生成需求。在美團(tuán)早期,有的業(yè)務(wù)直接通過 DB 自增的方式生成 ID,有的業(yè)務(wù)通過 Redis 緩存來生成 ID,也有的業(yè)務(wù)直接用 UUID 這種方式來生成 ID。以上的方式各自有各自的問題,因此美團(tuán)決定實(shí)現(xiàn)一套分布式 ID 生成服務(wù)來滿足需求目前 Leaf 覆蓋了美團(tuán)點(diǎn)評公司內(nèi)部金融、餐飲、外賣、酒店旅游、貓眼電影等眾多業(yè)務(wù)線。在4C8G VM 基礎(chǔ)上,通過公司 RPC 方式調(diào)用,QPS 壓測結(jié)果近 5w/s,TP999 1ms(TP=Top Percentile,Top 百分?jǐn)?shù),是一個(gè)統(tǒng)計(jì)學(xué)里的術(shù)語,與平均數(shù)、中位數(shù)都是一類。TP50、TP90 和 TP99 等指標(biāo)常用于系統(tǒng)性能監(jiān)控場景,指高于 50%、90%、99% 等百分線的情況)。

目前 LEAF 的使用有兩種不同的思路,號段模式和 SNOWFLAKE 模式,你可以同時(shí)開啟兩種方式,也可以指定開啟某種方式(默認(rèn)兩種方式為關(guān)閉狀態(tài))。

我們從 GitHub 上 Clone LEAF 之后,它的配置文件在 leaf-server/src/main/resources/leaf.properties 中,各項(xiàng)配置的含義如下:

可以看到,如果使用號段模式,需要數(shù)據(jù)庫支持;如果使用 SNOWFLAKE 模式,需要 Zookeeper 支持。

3.3.1 號段模式

號段模式還是基于數(shù)據(jù)庫,但是思路有些變化,如下:

  • 利用 proxy server 從數(shù)據(jù)庫中批量獲取 id,每次獲取一個(gè) segment (step 決定其大小) 號段的值,用完之后再去數(shù)據(jù)庫獲取新的號段,可以大大的減輕數(shù)據(jù)庫的壓力。
  • 各個(gè)業(yè)務(wù)不同的發(fā)號需求用 biz_tag 字段來區(qū)分,每個(gè) biz-tag 的 ID 獲取相互隔離,互不影響。
  • 如果有新的業(yè)務(wù)需要擴(kuò)區(qū) ID,只需要增加表記錄即可。

如果使用號段模式,我們首先需要?jiǎng)?chuàng)建一張數(shù)據(jù)表,腳本如下:

  1. CREATE DATABASE leaf 
  2. CREATE TABLE `leaf_alloc` ( 
  3.   `biz_tag` varchar(128)  NOT NULL DEFAULT ''
  4.   `max_id` bigint(20) NOT NULL DEFAULT '1'
  5.   `step` int(11) NOT NULL
  6.   `description` varchar(256)  DEFAULT NULL
  7.   `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
  8.   PRIMARY KEY (`biz_tag`) 
  9. ) ENGINE=InnoDB; 
  10.  
  11. insert into leaf_alloc(biz_tag, max_id, step, description) values('leaf-segment-test', 1, 2000, 'Test leaf Segment Mode Get Id'

這張表中各項(xiàng)字段的含義如下:

  • biz_tag:業(yè)務(wù)標(biāo)記(不同業(yè)務(wù)可以有不同的號段序列)
  • max_id:當(dāng)前號段下的最大 id
  • step:每次取號段的步長
  • description:描述信息
  • update_time:更新時(shí)間

配置完成后,啟動(dòng)項(xiàng)目,訪問 http://localhost:8080/api/segment/get/leaf-segment-test 路徑(路徑最后面的 leaf-segment-test 是業(yè)務(wù)標(biāo)記),即可拿到 ID。

可以通過如下地址訪問到號段模式的監(jiān)控頁面 http://localhost:8080/cache。

號段模式優(yōu)缺點(diǎn):

優(yōu)點(diǎn)

  • Leaf 服務(wù)可以很方便的線性擴(kuò)展,性能完全能夠支撐大多數(shù)業(yè)務(wù)場景。
  • ID 號碼是趨勢遞增的 8byte 的 64 位數(shù)字,滿足上述數(shù)據(jù)庫存儲(chǔ)的主鍵要求。
  • 容災(zāi)性高:Leaf 服務(wù)內(nèi)部有號段緩存,即使 DB 宕機(jī),短時(shí)間內(nèi) Leaf 仍能正常對外提供服務(wù)。
  • 可以自定義 max_id 的大小,非常方便業(yè)務(wù)從原有的 ID 方式上遷移過來。

缺點(diǎn)

  • ID 號碼不夠隨機(jī),能夠泄露發(fā)號數(shù)量的信息,不太安全。
  • DB 宕機(jī)會(huì)造成整個(gè)系統(tǒng)不可用。

3.3.2 SNOWFLAKE 模式

SNOWFLAKE 模式需要配合 Zookeeper 一起,不過 SNOWFLAKE 對 Zookeeper 的依賴是弱依賴,把 Zookeeper 啟動(dòng)之后,我們可以在 SNOWFLAKE 中配置 Zookeeper 信息,如下:

  1. leaf.snowflake.enable=true 
  2. leaf.snowflake.zk.address=192.168.91.130 
  3. leaf.snowflake.port=2183 

然后重新啟動(dòng)項(xiàng)目,啟動(dòng)成功后,通過如下地址可以訪問到 ID:

  1. http://localhost:8080/api/snowflake/get/test 

3.4 Redis 生成

這個(gè)主要是利用 Redis 的 incrby 來實(shí)現(xiàn),這個(gè)我覺得沒啥好說的。

3.5 Zookeeper 處理

zookeeper 也能做,但是比較麻煩,不推薦。

4. 小結(jié)

綜上,如果項(xiàng)目中恰好使用了 MyCat,那么可以使用 MyCat+Zookeeper,否則建議使用 LEAF,兩種模式皆可。

本文轉(zhuǎn)載自微信公眾號「江南一點(diǎn)雨」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系江南一點(diǎn)雨公眾號。

 

責(zé)任編輯:武曉燕 來源: 江南一點(diǎn)雨
相關(guān)推薦

2024-03-28 10:01:38

2021-03-07 16:11:26

Redis分布式

2017-07-01 16:02:39

分布式ID生成器

2021-06-28 14:45:07

分布式框架操作

2019-09-05 13:06:08

雪花算法分布式ID

2024-09-18 00:00:10

UUID識別碼標(biāo)志符

2025-06-10 08:30:50

2024-02-22 17:02:09

IDUUID雪花算法

2016-11-29 09:12:21

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

2023-02-14 08:32:41

Ribbon負(fù)載均衡

2021-06-05 07:33:09

ID分布式架構(gòu)

2024-11-13 00:57:36

2021-05-08 08:01:05

Session登錄瀏覽器

2022-02-23 07:09:30

分布式ID雪花算法

2022-03-14 07:40:14

RibbonSpringNacos

2014-01-10 10:42:33

2022-12-30 17:52:44

分布式容錯(cuò)架構(gòu)

2023-12-12 07:13:39

雪花算法分布式ID

2024-12-02 13:08:28

2022-05-18 09:01:31

JavaScriptEvalErrorURIError
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 天天干天天操天天看 | 久久伊人影院 | 亚洲第一在线视频 | 久在线| 91综合网| 337p日韩 | 日韩精品一 | 亚洲欧美在线免费观看 | 中文字幕av一区二区三区 | 国产午夜精品久久久久 | 美女高潮网站 | 欧美日在线 | 亚洲成人精品久久久 | 男人的天堂中文字幕 | 久久国产一区 | 日韩中文字幕在线观看 | 涩涩视频在线观看 | 三级成人在线 | 国产亚洲欧美在线视频 | 一区二区三区视频在线观看 | 99国内精品久久久久久久 | 欧美一级在线观看 | 久久国产一区二区 | 久久这里只有 | 精品欧美一区二区久久久伦 | 色婷婷综合网站 | 最新av中文字幕 | 久久国产精99精产国高潮 | 国产欧美日韩久久久 | 一道本不卡 | av永久| 一区二区在线免费播放 | 欧美日韩一区在线播放 | 色综合桃花网 | 国产成人精品一区二区三区网站观看 | 午夜欧美一区二区三区在线播放 | 国产精品欧美一区二区三区不卡 | 亚洲国产成人精品女人久久久 | 日韩高清av| 欧美成人一区二区 | 国产视频一区二区在线观看 |