午夜视频免费看_日韩三级电影网站_国产精品久久一级_亚洲一级在线播放_人妻体内射精一区二区三区_91夜夜揉人人捏人人添红杏_91福利在线导航_国产又粗又猛又黄又爽无遮挡_欧美日韩一区在线播放_中文字幕一区二区三区四区不卡 _日日夜夜精品视频免费观看_欧美韩日一区二区三区

主頁 > 知識庫 > redis源碼分析教程之壓縮鏈表ziplist詳解

redis源碼分析教程之壓縮鏈表ziplist詳解

熱門標簽:百度商家地圖標注怎么做 最簡單的百度地圖標注 太原營銷外呼系統 小紅書怎么地圖標注店 竹間科技AI電銷機器人 玄武湖地圖標注 西藏教育智能外呼系統價格 地圖標注費用 地圖標注如何即時生效

前言

壓縮列表(ziplist)是由一系列特殊編碼的內存塊構成的列表,它對于Redis的數據存儲優化有著非常重要的作用。這篇文章總結一下redis中使用非常多的一個數據結構壓縮鏈表ziplist。該數據結構在redis中說是無處不在也毫不過分,除了鏈表以外,很多其他數據結構也是用它進行過渡的,比如前面文章提到的SortedSet。下面話不多說了,來一起看看詳細的介紹吧。

一、壓縮鏈表ziplist數據結構簡介

首先從整體上看下ziplist的結構,如下圖:

壓縮鏈表ziplist結構圖

可以看出字段很多,字節大小也不同,但這也就是壓縮鏈表的精髓所在了,我們依次總結一下。

 

字段 含義
zlbytes 該字段是壓縮鏈表的第一個字段,是無符號整型,占用4個字節。用于表示整個壓縮鏈表占用的字節數(包括它自己)。
zltail 無符號整型,占用4個字節。用于存儲從壓縮鏈表頭部到最后一個entry(不是尾元素zlend)的偏移量,在快速跳轉到鏈表尾部的場景使用。
zllen 無符號整型,占用2個字節。用于存儲壓縮鏈表中包含的entry總數。
zlend 特殊的entry,用來表示壓縮鏈表的末尾。占用一個字節,值恒為255。

總結為ziplist的頭跟尾,下面再總結一下重中之重的entry字段。

一般來說,一個entry由prevlen,encoding,entry-data三個字段組成,但當entry是個很小的整數時,會根據編碼省略掉entry-data字段。下面依次進行總結:

首先是字段prevlen:表示前一個entry的長度,有兩種編碼方式。

  • 當長度小于255字節時,用一個字節存儲。
  • 當長度大于等于255時,用五個字節進行存儲,其中第一個字節會被設置為255表示前一個entry的長度由后面四個字節表示。

然后是字段encoding:它會根據當前元素內容的不同會采用不同的編碼方式,如下:

1、如果元素內容為字符串,encoding的值分別為:

00xx xxxx :00開頭表示該字符串的長度用6個bit表示。

01xx xxxx | xxxx xxxx :01開頭表示字符串的長度由14bit表示,這14個bit采用大端存儲。

1000 0000 | xxxx xxxx | xxxx xxxx | xxxx xxxx | xxxx xxxx :10開頭表示后續的四個字節為字符串長度,這32個bit采用大端存儲。

2、如果元素內容為數字,encoding的值分別為:

1100 0000:表示數字占用后面2個字節。

1101 0000:表示數字占用后面4個字節。

1110 0000:表示數字占用后面8個字節。

1111 0000 :表示數字占用后面3個字節。

1111 1110 :表示數字占用后面1個字節。

1111 1111 :表示壓縮鏈表中最后一個元素(特殊編碼)。

1111 xxxx :表示只用后4位表示0~12的整數,由于0000,1110跟1111三種已經被占用,也就是說這里的xxxx四位只能表示0001~1101,轉換成十進制就是數字1~13,但是redis規定它用來表示0~12,因此當遇到這個編碼時,我們需要取出后四位然后減1來得到正確的值。

最后是字段entry-data:如果元素的值為字符串,則保存元素本身的值。如果元素的值為很小的數字(按上面編碼規則即0~12),則沒有該字段。

壓縮鏈表的編碼非常復雜,但這也正是該數據結構的精髓所在,一起來看一個例子吧:

注:這個例子是redis源碼中提到的

//由元素2,5組成的壓縮鏈表
[0f 00 00 00] [0c 00 00 00] [02 00] [00 f3] [02 f6] [ff]
 |  |  | | | |
 zlbytes zltail entries "2" "5" end
//字符串"Hello World"編碼后的內容
[02] [0b] [48 65 6c 6c 6f 20 57 6f 72 6c 64]

上面是一段用十六進制表示2,5兩個元素組成的壓縮鏈表。

  • 首先前四個字節表示整個ziplist占用的字節數,因為redis采用小端存儲,所以15個字節表示為0f 00 00 00。
  • 接下來的4個字節表示末尾元素偏移量,是從ziplist頭(zlbytes)開始到最后一個元素(注:不是尾節點)的偏移量,也是采用小端存儲,因此表示為0c 00 00 00。
  • 再后面是由兩個字節組成的表示元素個數的zllen字段,在我們這個例子中有兩個元素,加上小端存儲,所以表示為02 00。
  • 接下來是元素本身,首先由一個變長的字端表示前一個元素的長度,2作為第一個元素,它前一個元素的大小就是0,因此占用一個字節00。按照我們上面說的編碼規則,元素2跟5屬于0~12之間的數字,需要使用1111 xxxx格式進行編碼,2轉成二進制為0010,再加上1就是0011(加1的原因上面已經說明),組合起來元素2就表示為00 f3。同理元素5表示為02 f6。
  • 最后就是尾元素,使用未被占用的編碼1111 1111即255。

接下來我們在這個壓縮鏈表末尾插入一個字符串元素Hello World,先看看該如何編碼該字符串,按照約定的編碼規則,首先要用字節表示前一個元素的長度,這里前一個元素時5,總共占用了兩個字節,因此首先用一個字節表示前一個元素的長度02,接下來是字符串的編碼,我們要加入的字符串長度為11(空格也算),轉換成二進制就是1011,按照字符串的編碼規則,使用0000 1011表示,轉為十六進制就是0b,最后再加上我們字符串本身的ASCII碼,綜合起來就得出該字符串的編碼:[02] [0b] [48 65 6c 6c 6f 20 57 6f 72 6c 64]。

此時整個壓縮鏈表就變為:

[0f 00 00 00] [0c 00 00 00] [02 00] [00 f3] [02 f6] [02 0b 48 65 6c 6c 6f 20 57 6f 72 6c 64] [ff]
 |  |  | | |   |   |
 zlbytes zltail entries "2" "5"   "Hello World"  end

二、壓縮鏈表ziplist命令源碼分析

搞明白上面的編碼規則以后,我們再來看下壓縮鏈表ziplist的部分操作源碼,本文就創建壓縮鏈表,插入元素,刪除元素,查找元素四個操作來總結一下壓縮鏈表的基本原理。

首先是創建:

//定義由zlbytes,zltail跟zllen組成的壓縮鏈表的頭大小
#define ZIPLIST_HEADER_SIZE (sizeof(uint32_t)*2+sizeof(uint16_t))
//創建一個壓縮鏈表,并且返回指向該鏈表的指針
unsigned char *ziplistNew(void) {
 //這里之所以+1是因為尾元素占用一個字節,這也是一個壓縮鏈表最小尺寸
 unsigned int bytes = ZIPLIST_HEADER_SIZE+1;
 //分配內存
 unsigned char *zl = zmalloc(bytes);
 //設置鏈表大小
 ZIPLIST_BYTES(zl) = intrev32ifbe(bytes);
 //設置最后一個元素的偏移量
 ZIPLIST_TAIL_OFFSET(zl) = intrev32ifbe(ZIPLIST_HEADER_SIZE);
 //設置元素個數
 ZIPLIST_LENGTH(zl) = 0;
 //設置尾元素(上面只是申請空間)
 zl[bytes-1] = ZIP_END;
 return zl;
}

創建壓縮鏈表的邏輯很簡單,就是申請固定的包含頭尾節點的空間,然后初始化鏈表上下文。

與創建相比,添加元素的源碼就非常冗長了,為了便于理解,在看源碼之前我們先自己梳理一下添加元素的邏輯。

  • 首先我們要找到指定插入位置的前一個元素的大小,因為該屬性是新元素的組成部分之一。
  • 然后我們要對當前元素進行編碼來獲得相應的encoding字段跟實際元素值的字段。
  • 新插入元素的后繼元素的prevlen字段要更新,因為它前面的元素已經改變。這里可能引起級聯更新(刪除元素也有該問題),原因就是prevlen字段大小是可變的。

上面三步是核心步驟,其余的還有更新尾節點偏移量,修改鏈表元素個數等操作。當然,由于壓縮鏈表是基于數組實現的,因此在插入或刪除元素的時候內存拷貝也是必不可少的。

總結好上面的步驟以后,我們開始一步一步分析源碼,比較長,慢慢看:

//四個參數依次是:壓縮鏈表,插入位置(新元素插入p元素后面),元素值,元素長度
unsigned char *__ziplistInsert(unsigned char *zl, unsigned char *p, unsigned char *s, unsigned int slen) {
 //這里是保存當前鏈表的長度
 size_t curlen = intrev32ifbe(ZIPLIST_BYTES(zl)), reqlen;
 unsigned int prevlensize, prevlen = 0;
 size_t offset;
 int nextdiff = 0;
 unsigned char encoding = 0;
 long long value = 123456789;
 zlentry tail;

 //1. 這段邏輯目的就是獲取前置元素的長度
 if (p[0] != ZIP_END) {
 //如果插入位置的元素不是尾元素,則獲取該元素的長度
 //這里為了后面使用方便進行了拆分,prevlensize保存encoding字段的長度,prevlen保存元素本身的長度
 ZIP_DECODE_PREVLEN(p, prevlensize, prevlen);
 } else {
 //如果插入位置的元素是尾元素,那么需要把新元素插入鏈表尾端
 //獲取到鏈表最后一個元素(注:最后一個元素不等于尾元素)
 unsigned char *ptail = ZIPLIST_ENTRY_TAIL(zl);

 if (ptail[0] != ZIP_END) {
  //如果最后一個元素不是尾元素,則該元素為新元素的前置元素,獲取該元素長度
  prevlen = zipRawEntryLength(ptail);
 }
 //否則說明鏈表還沒有任何元素,即新元素的前置元素長度為0
 }

 //2. 對新元素進行編碼,獲取新元素的總大小
 if (zipTryEncoding(s,slen,value,encoding)) {
 //如果是數字,則按數字進行編碼
 reqlen = zipIntSize(encoding);
 } else {
 //元素長度即為字符串長度
 reqlen = slen;
 }
 //新元素總長度為值的長度加上前置元素跟encoding元素的長度
 reqlen += zipStorePrevEntryLength(NULL,prevlen);
 reqlen += zipStoreEntryEncoding(NULL,encoding,slen);

 //如果插入的位置不是鏈表尾,則要對新元素的后續元素的prevlen字段進行判斷
 //根據上面的編碼規則,該字段可能需要擴容
 int forcelarge = 0;
 nextdiff = (p[0] != ZIP_END) ? zipPrevLenByteDiff(p,reqlen) : 0;
 if (nextdiff == -4  reqlen  4) {
 nextdiff = 0;
 forcelarge = 1;
 }
 //按照新計算出的數組大小進行擴容,由于新數組的地址可能會改變,因此這里記錄舊的偏移量
 offset = p-zl;
 zl = ziplistResize(zl,curlen+reqlen+nextdiff);
 //在新數組上計算插入位置
 p = zl+offset;
 //如果新插入的元素不是在鏈表末尾
 if (p[0] != ZIP_END) {
 //把新元素后繼元素復制到新的數組中,-1為尾元素
 memmove(p+reqlen,p-nextdiff,curlen-offset-1+nextdiff);
 //新元素的后繼元素的prevlen字段
 if (forcelarge)
  zipStorePrevEntryLengthLarge(p+reqlen,reqlen);
 else
  zipStorePrevEntryLength(p+reqlen,reqlen);

 //更新最后一個元素的偏移量
 ZIPLIST_TAIL_OFFSET(zl) = intrev32ifbe(intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl))+reqlen);
 //當新元素的后繼元素不止有一個時,新的尾元素偏移量需要加上nextdiff
 zipEntry(p+reqlen, tail);
 if (p[reqlen+tail.headersize+tail.len] != ZIP_END) {
  ZIPLIST_TAIL_OFFSET(zl) =
  intrev32ifbe(intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl))+nextdiff);
 }
 } else {
 //新元素插入到鏈表尾端,更新尾端偏移量
 ZIPLIST_TAIL_OFFSET(zl) = intrev32ifbe(p-zl);
 }
 //nextdiff !=0表示后繼元素的長度發生變化,因此我們需要級聯更新后繼元素的后繼元素
 if (nextdiff != 0) {
 offset = p-zl;
 zl = __ziplistCascadeUpdate(zl,p+reqlen);
 p = zl+offset;
 }
 //把新元素寫入鏈表
 p += zipStorePrevEntryLength(p,prevlen);
 p += zipStoreEntryEncoding(p,encoding,slen);
 if (ZIP_IS_STR(encoding)) {
 memcpy(p,s,slen);
 } else {
 zipSaveInteger(p,value,encoding);
 }
 //壓縮鏈表存儲元素數量+1
 ZIPLIST_INCR_LENGTH(zl,1);
 return zl;
}

分析完插入元素的邏輯,長舒一口氣,真的很長,細節也很多。

接下來在再看下刪除元素的過程,與添加相比,刪除相對要簡單一些,清空當前元素以后,需要把后繼元素一個一個拷貝上來(這也是數組跟鏈表兩個數據結構的差別),然后注意是否需要級聯更新,上代碼:

//參數依次為:壓縮鏈表,刪除元素的其實位置,刪除元素的個數
unsigned char *__ziplistDelete(unsigned char *zl, unsigned char *p, unsigned int num) {
 unsigned int i, totlen, deleted = 0;
 size_t offset;
 int nextdiff = 0;
 zlentry first, tail;
 //讀取p指向的元素保存在first中
 zipEntry(p, first);
 for (i = 0; p[0] != ZIP_END  i  num; i++) {
  //統計總共刪除的長度
  p += zipRawEntryLength(p);
  //統計實際刪除元素的個數
  deleted++;
 }
 //需要刪除元素的字節數
 totlen = p-first.p;
 if (totlen > 0) {
  if (p[0] != ZIP_END) {
   //判斷元素大小是否有改變
   nextdiff = zipPrevLenByteDiff(p,first.prevrawlen);
   //修改刪除元素之后的元素的prevlen字段
   p -= nextdiff;
   zipStorePrevEntryLength(p,first.prevrawlen);
   //更新末尾元素的偏移量
   ZIPLIST_TAIL_OFFSET(zl) =intrev32ifbe(intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl))-totlen);
   //當刪除元素的后繼元素不止有一個時,新的末尾元素偏移量需要加上nextdiff
   zipEntry(p, tail);
   if (p[tail.headersize+tail.len] != ZIP_END) {
    ZIPLIST_TAIL_OFFSET(zl) =
     intrev32ifbe(intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl))+nextdiff);
   }
   //把后面剩余的元素移動至前面
   memmove(first.p,p,
    intrev32ifbe(ZIPLIST_BYTES(zl))-(p-zl)-1);
  } else {
   //直接刪除到鏈表末尾,因此不需要內存拷貝,只需修改最后一個元素的偏移量
   ZIPLIST_TAIL_OFFSET(zl) =
    intrev32ifbe((first.p-zl)-first.prevrawlen);
  }
  //resize數組大小
  offset = first.p-zl;
  zl = ziplistResize(zl, intrev32ifbe(ZIPLIST_BYTES(zl))-totlen+nextdiff);
  //修改鏈表元素個數
  ZIPLIST_INCR_LENGTH(zl,-deleted);
  p = zl+offset;
  //nextdiff != 0表示元素大小發生變化,需要進行級聯更新
  if (nextdiff != 0)
   zl = __ziplistCascadeUpdate(zl,p);
 }
 return zl;
}

最后我們看下元素的查找操作:

//參數依次為:壓縮鏈表,要查找元素的值,要查找元素的長度,每次比較之間跳過的元素個數
unsigned char *ziplistFind(unsigned char *p, unsigned char *vstr, unsigned int vlen, unsigned int skip) {
 int skipcnt = 0;
 unsigned char vencoding = 0;
 long long vll = 0;
 //只要還沒到尾元素就不斷循環
 while (p[0] != ZIP_END) {
  unsigned int prevlensize, encoding, lensize, len;
  unsigned char *q;
  //查詢鏈表當前元素的prevlen字段
  ZIP_DECODE_PREVLENSIZE(p, prevlensize);
  //查詢鏈表當前元素的encoding字段
  ZIP_DECODE_LENGTH(p + prevlensize, encoding, lensize, len);
  q = p + prevlensize + lensize;
  //已到達需要比較的元素位置
  if (skipcnt == 0) {
   //如果鏈表中的當前元素時字符串
   if (ZIP_IS_STR(encoding)) {
    //跟要查找的字符串進行比較
    if (len == vlen  memcmp(q, vstr, vlen) == 0) {
     //匹配成功,則要查找元素的指針
     return p;
    }
   } else {
    //如果當前元素為數字且vencoding為0
    if (vencoding == 0) {
     //嘗試對要查找的值進行數字編碼
     if (!zipTryEncoding(vstr, vlen, vll, vencoding)) {
      //如果編碼失敗,則說明要查找的元素根本不是數字
      //然后把vencoding設置為最大值,起一個標記作用
      //也就是說后面就不用嘗試把要查找的值編碼成數字了
      vencoding = UCHAR_MAX;
     }
     assert(vencoding);
    }
    //如果vencoding != UCHAR_MAX,則說明要查找的元素成功編碼為數字
    if (vencoding != UCHAR_MAX) {
     //按數字取出當前鏈表中的元素
     long long ll = zipLoadInteger(q, encoding);
     if (ll == vll) {
      //如果兩個數字相等,則返回元素指針
      return p;
     }
    }
   }
   //重置需要跳過的元素個數
   skipcnt = skip;
  } else {
   //跳過元素
   skipcnt--;
  }
  //遍歷下個元素
  p = q + len;
 }
 //遍歷完整個鏈表,沒有找到元素
 return NULL;
}

到這里就把壓縮鏈表的創建,添加,刪除,查找四個基本操作原理總結完了。

三、壓縮鏈表ziplist數據結構總結

壓縮鏈表ziplist在redis中的應用非常廣泛,它算是redis中最具特色的數據結構了。該數據結構的精髓其實就在于文章第一部分總結的編碼規則,先理清楚這部分內容,后面的源碼可以簡單看下加深理解。

不得不說源碼部分著實有點冗長,確實需要耐心,我自己在讀的過程中也很頭大。如果對源碼感興趣的話,建議按我的方法,先自己梳理某個操作(例如上面提到的插入元素)需要做哪些事情,然后再看代碼可能會更好理解一些。

最后留一個小問題,既然redis中的ziplist對內存利用率如此之高,那為什么還要提供普通的鏈表結構供用戶使用呢?
這個問題沒有標準答案,仁者見仁智者見智吧~

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

您可能感興趣的文章:
  • 詳解Redis中的List類型
  • Python操作redis實例小結【String、Hash、List、Set等】
  • 解決Spring session(redis存儲方式)監聽導致創建大量redisMessageListenerContailner-X線程問題
  • Redis List列表的詳細介紹
  • redis 獲取 list 中的所有元素操作

標簽:景德鎮 贛州 林芝 廣東 香港 澳門 揚州 唐山

巨人網絡通訊聲明:本文標題《redis源碼分析教程之壓縮鏈表ziplist詳解》,本文關鍵詞  redis,源碼,分析,教程,之,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《redis源碼分析教程之壓縮鏈表ziplist詳解》相關的同類信息!
  • 本頁收集關于redis源碼分析教程之壓縮鏈表ziplist詳解的相關信息資訊供網民參考!
  • 推薦文章
    日本高清不卡一区| 日韩一区二区三区在线视频| 欧美日韩最好看的视频| 日韩av一区二区在线影视| 狠狠操精品视频| 欧美日韩成人免费视频| 最新中文字幕2018| 日批免费观看视频| 少妇精品无码一区二区免费视频| 在线观看黄网址| 日本午夜精品理论片a级app发布| 国产天堂第一区| 成人黄色在线观看视频| 麻豆精品一区二区综合av| 高清日韩电视剧大全免费| 国产亚洲va综合人人澡精品| 亚洲精品你懂的| 欧美综合视频在线观看| 亚洲成色www8888| 中文字幕日韩在线播放| 91超碰中文字幕久久精品| 成人天堂噜噜噜| 品久久久久久久久久96高清| 97免费视频观看| 免费看污污网站| 中文字幕一区二区久久人妻网站| 免费在线观看一级片| 欧美日韩在线视频播放| 欧美一级淫片aaaaaa| 国产精品一区在线| 国产欧美久久久精品影院| 婷婷久久综合九色综合绿巨人| 91精品视频网| 播播国产欧美激情| 国产精品久久久久aaaa九色| 久久久神马电影| 国产3p露脸普通话对白| 性色av浪潮av| 午夜激情福利电影| 波多野结衣电车痴汉| 久久性色av| 成人99免费视频| 亚洲激情自拍偷拍| 日韩一区二区中文字幕| 久久影视电视剧免费网站| 国产精品一区二区三区久久久 | av网站免费在线看| 日本黄色片视频| 三级小视频在线观看| 97精品久久久午夜一区二区三区 | 精品无码人妻一区二区三区品| 国产精品九九九九| 国产精品一区二区果冻传媒| 亚洲女性喷水在线观看一区| 7777精品伊人久久久大香线蕉| 日韩亚洲在线观看| 成人国产精品一区| 亚洲欧美日韩不卡| 韩国三级与黑人| 欧美成人aaa片一区国产精品| 国产乱色精品成人免费视频| 国产成人综合视频| 亚洲香蕉伊在人在线观| 亚洲国产欧美在线成人app| 91精品国产777在线观看| 精品一区二区视频| 日韩中文字幕组| 91无套直看片红桃在线观看| 国产精品无码白浆高潮| 成人午夜私人影院| 欧美午夜无遮挡| 中文字幕国产精品久久| 91最新国产视频| 免费看毛片的网址| 四虎影成人精品a片| 国产美女www爽爽爽| 国内成人免费视频| 午夜视频在线观看一区二区 | 欧美一卡二卡在线观看| 欧美国产日韩xxxxx| 国产精品久久一区二区三区| 北条麻妃在线观看| 无码人妻精品中文字幕| 免费看av毛片| 国产精品夫妻自拍| 精品人伦一区二区色婷婷| 奇米影视亚洲狠狠色| 在线视频不卡一区二区| 日韩大尺度视频| 日日摸天天添天天添破| 国产一区视频导航| 亚洲国产成人va在线观看天堂| 国产视频精品一区二区三区| 成人欧美在线视频| 黄色片久久久久| 欧美国产日韩在线观看成人| 久久三级视频| 一卡二卡三卡日韩欧美| 亚洲视频在线视频| 高清av免费一区中文字幕| 一本久道中文无码字幕av| 日本天堂中文字幕| 毛片av中文字幕一区二区| 亚洲第一搞黄网站| 日韩视频欧美视频| 免费观看成人在线| 91精品人妻一区二区三区四区| 日韩熟女一区二区| 成人av在线电影| 欧美日本高清视频在线观看| 日本成人在线视频网址| www.男人天堂网| 黄色免费一级视频| 日韩影院免费视频| 黄色一区二区三区| 色综合老司机第九色激情| 视频在线观看成人| jjzzjjzz欧美69巨大| 一级片视频播放| 国产精品拍天天在线| 亚洲女人被黑人巨大进入al| 国产精品区一区| 日韩在线一区视频| 中文字幕一区二区三区四区免费看 | 欧美激情成人网| 久久精品免费在线| 成人一区二区视频| 91精品国产91久久久久久一区二区| 国产精品福利观看| 成人综合视频在线| 国产成人无码一区二区三区在线| 成人黄色网址在线观看| 日韩你懂的在线观看| 成人a免费视频| 亚洲36d大奶网| 久久午夜鲁丝片| 中文字幕av一区二区三区| 亚洲人成电影在线播放| 久久影院理伦片| 日韩片在线观看| 五月婷婷开心中文字幕| 亚洲高清三级视频| 欧美精品videosex牲欧美| 成人小视频在线观看免费| 欧美激情一区二区视频| 国产99久久久精品| 精品卡一卡二卡三卡四在线| 国产精品 日韩| 国产吃瓜黑料一区二区| 丰满少妇被猛烈进入| 婷婷亚洲久悠悠色悠在线播放 | 色偷偷888欧美精品久久久| 日本成人黄色| 国产精品久久久久久成人| 国精产品一区一区三区mba视频 | 一本久久a久久免费精品不卡| 欧美一区亚洲一区| 逼特逼视频在线| 波多野结衣一区二区三区在线| 国产精品久久久久9999吃药| 久久久极品av| 加勒比成人在线| 亚洲 欧美 成人| 中文av字幕一区| 久久国产精品网站| 阿v天堂2018| 99超碰在线观看| 亚洲天堂成人在线观看| 久久久久日韩精品久久久男男| www.好吊操| 亚洲午夜18毛片在线看| 国产精品免费看片| 欧美第一淫aaasss性| 日日摸日日碰夜夜爽无码| 天堂网中文字幕| 亚洲精品视频在线观看网站| 欧美亚洲另类在线| 国内国产精品天干天干| 黄频网站在线观看| 欧美日韩在线播放三区四区| 91九色在线免费视频| 久久精品一区二区免费播放| 国产一区二区剧情av在线| 亚洲国内高清视频| 亚洲精品在线视频观看| 精品视频久久久久| 国产精品护士白丝一区av| 国产69精品久久久久9999| 亚欧在线免费观看| 亚洲av无码乱码国产精品久久| 性做久久久久久免费观看| 国产精品夜间视频香蕉| 亚洲高清无码久久| 黄页视频在线91| 亚洲精品在线不卡| 亚洲精品国产suv一区88| 波多野结衣不卡| 亚洲福利一二三区| 成人免费网站在线观看| 黄色录像a级片| 国产精品综合一区二区| 一本一道久久a久久精品逆3p | 日韩精品中文字幕在线| 一区二区三区一级片| 一级片免费在线播放| 亚洲一区二区成人在线观看| 国产精自产拍久久久久久| 久久偷拍免费视频| thepron国产精品| 欧美成人sm免费视频| 麻豆三级在线观看| 久久久xxx| 亚洲国产第一页| 亚洲五码在线观看视频| 亚洲一级视频在线观看| 欧美在线观看视频在线| 快播日韩欧美| 国产精品suv一区二区| 一区二区三区在线播放| 91精品啪在线观看麻豆免费| 伊人影院综合网| 国产片一区二区| 日本国产欧美一区二区三区| 国产不卡一二三| av电影天堂一区二区在线观看| 欧美精品一区在线播放| 亚洲成人手机在线观看| 国产米奇在线777精品观看| 日韩中文字幕在线| 中文字幕 91| 美女www一区二区| 在线播放国产精品| 丰满少妇在线观看| 美国三级日本三级久久99| 最近2019中文字幕在线高清| 美女黄色片视频| 精品午夜一区二区三区在线观看| 色老头一区二区三区| 99re精彩视频| 经典一区二区三区| 久久久精品国产一区二区| 天天综合网久久| 狠狠色丁香婷婷综合久久片| 久久精品亚洲94久久精品| 亚洲国产午夜精品| 成人午夜免费电影| 高清欧美性猛交xxxx黑人猛交| 国产免费一区二区三区最新6| 99精品视频一区| 日本中文字幕久久看| 黄色片在线观看免费| 成人免费小视频| 3d动漫精品啪啪一区二区三区免费| 欧美日韩午夜视频| 亚洲一二三区不卡| 欧美激情专区| 中文字幕在线观看你懂的| 4438x成人网最大色成网站| 9色视频在线观看| 日本激情视频网站| 国产一区二区免费| 欧美视频国产视频| 成人手机电影网| 91国语精品自产拍在线观看性色 | 黄色免费看视频| 国产亚洲精久久久久久| 国产欧美一区二区三区视频| 男女羞羞免费视频| 日韩欧美中文字幕在线观看| 亚洲欧洲精品在线观看| 精品国产99久久久久久宅男i| 日韩禁在线播放| 欧美日韩一区二区三区69堂| www.欧美.com| 国产精品爽黄69天堂a| 欧美精品入口蜜桃| 日本高清成人免费播放| 日韩视频在线观看视频| 污污视频在线观看网站| 精品国模在线视频| 午夜不卡久久精品无码免费| 中文字幕av一区二区三区| 国产aⅴ精品一区二区三区黄| 免费看日批视频| 日韩免费性生活视频播放| 国产无套内射久久久国产| 国产呦精品一区二区三区网站| 97免费视频在线| 黄色裸体一级片| 欧美小视频在线观看| 国产又黄又爽免费视频| 日韩一区精品视频| 久久久久国产精品www| 国产精品久久免费观看| 性感美女极品91精品| 久久久久亚洲av无码专区喷水| 老司机精品视频网站| 欧美丰满少妇xxxxx做受| 日本一道本视频| 福利一区福利二区微拍刺激| 青青草影院在线观看| 日本女优在线视频一区二区| 97碰碰碰免费色视频| 一区视频免费观看| 欧美色图天堂网| 日韩免费在线观看av| 韩国精品在线观看| 国产成人精品在线视频| 成年人免费看毛片| 精品欧美一区二区三区精品久久| 精品日韩久久久| 久久精品一区二区三区四区| 国产日韩三区| 成人av手机在线| 色偷偷综合社区| 国产av自拍一区| 欧美日韩中文在线观看| 青青草国产免费| 粉嫩aⅴ一区二区三区四区五区| 国产日韩在线视频| 少妇一级淫片日本| 亚洲天堂av在线免费观看| 久久久久国产精品无码免费看| 亚洲一区二区三区三| 日韩video| 国产裸体歌舞团一区二区| 国产一区二区视频在线观看| 中日精品一色哟哟| 国产午夜精品理论片a级探花| 国产大学生视频| 午夜亚洲福利老司机| 免费国产黄色网址| 99这里都是精品| 精品综合久久| 亚洲 欧美 激情 另类| 97在线日本国产| 丰满少妇乱子伦精品看片| 亚洲国产日韩一区| 97精品人妻一区二区三区蜜桃| 天天操天天干天天综合网| 99久久国产综合精品五月天喷水| 成人h版在线观看| 国产亚洲欧美另类一区二区三区| 欧美在线 | 亚洲| 欧美一级片一区| 精品国产xxx| 中文亚洲视频在线| 欧美一区二区三区观看| 日韩一区二区中文字幕| 岛国av免费观看| 无码av中文一区二区三区桃花岛| av免费观看网| 国产欧美一区二区精品性| 亚洲国产精品视频一区| 国产真实乱子伦精品视频| 91久久精品国产91久久性色tv | 一区二区三区蜜桃| 国产美女永久无遮挡| 91一区二区在线| 日韩视频专区| 国产成人综合在线观看| 久久爱av电影| 久久国产三级精品| 91手机在线播放| 少妇一区二区三区四区| 国产精品久久久精品| av加勒比在线| 欧美亚洲激情在线| 91久久久久久久久久久久| 欧美极品少妇xxxxⅹ免费视频| www.伊人久久| 久久综合五月天| 亚洲欧美在线视频免费| 在线观看久久久久久| 欧美国产日韩在线观看成人 | 国产精品大全| 久久久久久久欧美精品| 91亚洲精品一区二区| 午夜小视频在线播放| 国产日韩欧美日韩大片| 污视频网站在线播放| 亚洲一区二区三区视频| 亚洲av成人无码网天堂| 91精品在线影院| 久久综合狠狠| 亚洲综合自拍一区| 日韩电影在线免费| 福利视频一区二区三区| 美美哒免费高清在线观看视频一区二区| av激情久久| 久久国产麻豆精品| 久久久久久久久一区| 激情亚洲综合在线| 久久免费99精品久久久久久| 国产精品资源在线看| 欧美在线播放一区| 成人免费毛片高清视频| 亚洲制服中文| 久久精品亚洲精品国产欧美kt∨ | 日韩欧美一区二区在线观看| 成人国产精品视频| 手机成人av在线| 国产日本亚洲高清| 日韩中字在线观看| 一卡二卡欧美日韩| 国产三级精品三级在线| 色天天综合久久久久综合片| 人妻激情偷乱频一区二区三区| 69堂成人精品免费视频| 精品人妻中文无码av在线|