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

Redis詳細介紹:5種基本數據結構

開發 后端 其他數據庫 Redis
5 種是 Redis 相關知識中最基礎、最重要的部分,下面我們結合源碼以及一些實踐來給大家分別講解一下。

 一、Redis 簡介

 "Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker." —— Redis是一個開放源代碼(BSD許可)的內存中數據結構存儲,用作數據庫,緩存和消息代理。(摘自官網)

Redis 是一個開源,高級的鍵值存儲和一個適用的解決方案,用于構建高性能,可擴展的 Web 應用程序。Redis 也被作者戲稱為 數據結構服務器 ,這意味著使用者可以通過一些命令,基于帶有 TCP 套接字的簡單 服務器-客戶端 協議來訪問一組 可變數據結構 。(在 Redis 中都采用鍵值對的方式,只不過對應的數據結構不一樣罷了)

Redis 的優點

以下是 Redis 的一些優點:

  •  異???/strong> - Redis 非常快,每秒可執行大約 110000 次的設置(SET)操作,每秒大約可執行 81000 次的讀取/獲取(GET)操作。
  •  支持豐富的數據類型 - Redis 支持開發人員常用的大多數數據類型,例如列表,集合,排序集和散列等等。這使得 Redis 很容易被用來解決各種問題,因為我們知道哪些問題可以更好使用地哪些數據類型來處理解決。
  •  操作具有原子性 - 所有 Redis 操作都是原子操作,這確保如果兩個客戶端并發訪問,Redis 服務器能接收更新的值。
  •  多實用工具 - Redis 是一個多實用工具,可用于多種用例,如:緩存,消息隊列(Redis 本地支持發布/訂閱),應用程序中的任何短期數據,例如,web應用程序中的會話,網頁命中計數等。

Redis 的安裝

這一步比較簡單,你可以在網上搜到許多滿意的教程,這里就不再贅述。

給一個菜鳥教程的安裝教程用作參考:https://www.runoob.com/redis/redis-install.html

測試本地 Redis 性能

當你安裝完成之后,你可以先執行 redis-server 讓 Redis 啟動起來,然后運行命令 redis-benchmark -n 100000 -q 來檢測本地同時執行 10 萬個請求時的性能:

當然不同電腦之間由于各方面的原因會存在性能差距,這個測試您可以權當是一種 「樂趣」 就好。

二、Redis 五種基本數據結構

Redis 有 5 種基礎數據結構,它們分別是:string(字符串)、list(列表)、hash(字典)、set(集合) 和 zset(有序集合)。這 5 種是 Redis 相關知識中最基礎、最重要的部分,下面我們結合源碼以及一些實踐來給大家分別講解一下。

1)字符串 string

Redis 中的字符串是一種 動態字符串,這意味著使用者可以修改,它的底層實現有點類似于 Java 中的 ArrayList,有一個字符數組,從源碼的 sds.h/sdshdr 文件 中可以看到 Redis 底層對于字符串的定義 SDS,即 Simple Dynamic String 結構: 

  1. /* Note: sdshdr5 is never used, we just access the flags byte directly.  
  2.  * However is here to document the layout of type 5 SDS strings. */  
  3. struct __attribute__ ((__packed__)) sdshdr5 {  
  4.     unsigned char flags; /* 3 lsb of type, and 5 msb of string length */  
  5.     char buf[];  
  6. };  
  7. struct __attribute__ ((__packed__)) sdshdr8 {  
  8.     uint8_t len; /* used */  
  9.     uint8_t alloc; /* excluding the header and null terminator */  
  10.     unsigned char flags; /* 3 lsb of type, 5 unused bits */  
  11.     char buf[];  
  12. };  
  13. struct __attribute__ ((__packed__)) sdshdr16 {  
  14.     uint16_t len; /* used */  
  15.     uint16_t alloc; /* excluding the header and null terminator */  
  16.     unsigned char flags; /* 3 lsb of type, 5 unused bits */  
  17.     char buf[];  
  18. };  
  19. struct __attribute__ ((__packed__)) sdshdr32 {  
  20.     uint32_t len; /* used */  
  21.     uint32_t alloc; /* excluding the header and null terminator */  
  22.     unsigned char flags; /* 3 lsb of type, 5 unused bits */  
  23.     char buf[];  
  24. };  
  25. struct __attribute__ ((__packed__)) sdshdr64 {  
  26.     uint64_t len; /* used */  
  27.     uint64_t alloc; /* excluding the header and null terminator */  
  28.     unsigned char flags; /* 3 lsb of type, 5 unused bits */  
  29.     char buf[];  
  30. }; 

你會發現同樣一組結構 Redis 使用泛型定義了好多次,為什么不直接使用 int 類型呢?

因為當字符串比較短的時候,len 和 alloc 可以使用 byte 和 short 來表示,Redis 為了對內存做極致的優化,不同長度的字符串使用不同的結構體來表示。

SDS 與 C 字符串的區別

為什么不考慮直接使用 C 語言的字符串呢?因為 C 語言這種簡單的字符串表示方式 不符合 Redis 對字符串在安全性、效率以及功能方面的要求。我們知道,C 語言使用了一個長度為 N+1 的字符數組來表示長度為 N 的字符串,并且字符數組最后一個元素總是 '\0'。(下圖就展示了 C 語言中值為 "Redis" 的一個字符數組)

這樣簡單的數據結構可能會造成以下一些問題:

  •  獲取字符串長度為 O(N) 級別的操作 → 因為 C 不保存數組的長度,每次都需要遍歷一遍整個數組;
  •  不能很好的杜絕 緩沖區溢出/內存泄漏 的問題 → 跟上述問題原因一樣,如果執行拼接 or 縮短字符串的操作,如果操作不當就很容易造成上述問題;
  •  C 字符串 只能保存文本數據 → 因為 C 語言中的字符串必須符合某種編碼(比如 ASCII),例如中間出現的 '\0' 可能會被判定為提前結束的字符串而識別不了;

我們以追加字符串的操作舉例,Redis 源碼如下: 

  1. /* Append the specified binary-safe string pointed by 't' of 'len' bytes to the  
  2.  * end of the specified sds string 's'.  
  3.  *  
  4.  * After the call, the passed sds string is no longer valid and all the  
  5.  * references must be substituted with the new pointer returned by the call. */  
  6. sds sdscatlen(sds s, const void *t, size_t len) {  
  7.     // 獲取原字符串的長度  
  8.     size_t curlen = sdslen(s);  
  9.     // 按需調整空間,如果容量不夠容納追加的內容,就會重新分配字節數組并復制原字符串的內容到新數組中  
  10.     s = sdsMakeRoomFor(s,len);  
  11.     if (s == NULL) return NULL;   // 內存不足  
  12.     memcpy(s+curlen, t, len);     // 追加目標字符串到字節數組中  
  13.     sdssetlen(s, curlen+len);     // 設置追加后的長度  
  14.     s[curlen+len] = '\0';         // 讓字符串以 \0 結尾,便于調試打印  
  15.     return s;  
  •  注:Redis 規定了字符串的長度不得超過 512 MB。

對字符串的基本操作

安裝好 Redis,我們可以使用 redis-cli 來對 Redis 進行命令行的操作,當然 Redis 官方也提供了在線的調試器,你也可以在里面敲入命令進行操作:http://try.redis.io/#run

設置和獲取鍵值對 

  1. > SET key value  
  2. OK  
  3. > GET key  
  4. "value" 

正如你看到的,我們通常使用 SET 和 GET 來設置和獲取字符串值。

值可以是任何種類的字符串(包括二進制數據),例如你可以在一個鍵下保存一張 .jpeg 圖片,只需要注意不要超過 512 MB 的最大限度就好了。

當 key 存在時,SET 命令會覆蓋掉你上一次設置的值: 

  1. > SET key newValue  
  2. OK  
  3. > GET key  
  4. "newValue" 

另外你還可以使用 EXISTS 和 DEL 關鍵字來查詢是否存在和刪除鍵值對: 

  1. > EXISTS key  
  2. (integer) 1  
  3. > DEL key  
  4. (integer) 1  
  5. > GET key  
  6. (nil) 

批量設置鍵值對 

  1. > SET key1 value1  
  2. OK  
  3. > SET key2 value2  
  4. OK  
  5. > MGET key1 key2 key3    # 返回一個列表  
  6. 1) "value1"  
  7. 2) "value2"  
  8. 3) (nil)  
  9. > MSET key1 value1 key2 value2  
  10. > MGET key1 key2  
  11. 1) "value1"  
  12. 2) "value2" 

過期和 SET 命令擴展

可以對 key 設置過期時間,到時間會被自動刪除,這個功能常用來控制緩存的失效時間。(過期可以是任意數據結構) 

  1. > SET key value1  
  2. > GET key  
  3. "value1"  
  4. > EXPIRE name 5    # 5s 后過期  
  5. ...                # 等待 5s  
  6. > GET key  
  7. (nil) 

等價于 SET + EXPIRE 的 SETNX 命令: 

  1. > SETNX key value1  
  2. ...                # 等待 5s 后獲取  
  3. > GET key  
  4. (nil)  
  5. > SETNX key value1  # 如果 key 不存在則 SET 成功  
  6. (integer) 1  
  7. > SETNX key value1  # 如果 key 存在則 SET 失敗  
  8. (integer) 0  
  9. > GET key  
  10. "value"             # 沒有改變 

計數

如果 value 是一個整數,還可以對它使用 INCR 命令進行 原子性 的自增操作,這意味著及時多個客戶端對同一個 key 進行操作,也決不會導致競爭的情況: 

  1. > SET counter 100  
  2. > INCR count  
  3. (interger) 101  
  4. > INCRBY counter 50  
  5. (integer) 151 

返回原值的 GETSET 命令

對字符串,還有一個 GETSET 比較讓人覺得有意思,它的功能跟它名字一樣:為 key 設置一個值并返回原值: 

  1. > SET key value  
  2. > GETSET key value1  
  3. "value" 

這可以對于某一些需要隔一段時間就統計的 key 很方便的設置和查看,例如:系統每當由用戶進入的時候你就是用 INCR 命令操作一個 key,當需要統計時候你就把這個 key 使用 GETSET 命令重新賦值為 0,這樣就達到了統計的目的。

2)列表 list

Redis 的列表相當于 Java 語言中的 LinkedList,注意它是鏈表而不是數組。這意味著 list 的插入和刪除操作非常快,時間復雜度為 O(1),但是索引定位很慢,時間復雜度為 O(n)。

我們可以從源碼的 adlist.h/listNode 來看到對其的定義: 

  1. /* Node, List, and Iterator are the only data structures used currently. */  
  2. typedef struct listNode {  
  3.     struct listNode *prev;  
  4.     struct listNode *next;  
  5.     void *value;  
  6. } listNode;  
  7. typedef struct listIter {  
  8.     listNode *next;  
  9.     int direction;  
  10. } listIter;  
  11. typedef struct list {  
  12.     listNode *head;  
  13.     listNode *tail;  
  14.     void *(*dup)(void *ptr);  
  15.     void (*free)(void *ptr);  
  16.     int (*match)(void *ptr, void *key);  
  17.     unsigned long len;  
  18. } list; 

可以看到,多個 listNode 可以通過 prev 和 next 指針組成雙向鏈表:

雖然僅僅使用多個 listNode 結構就可以組成鏈表,但是使用 adlist.h/list 結構來持有鏈表的話,操作起來會更加方便:

鏈表的基本操作

  •  LPUSH 和 RPUSH 分別可以向 list 的左邊(頭部)和右邊(尾部)添加一個新元素;
  •  LRANGE 命令可以從 list 中取出一定范圍的元素;
  •  LINDEX 命令可以從 list 中取出指定下表的元素,相當于 Java 鏈表操作中的 get(int index) 操作;

示范: 

  1. > rpush mylist A  
  2. (integer) 1  
  3. > rpush mylist B  
  4. (integer) 2  
  5. > lpush mylist first  
  6. (integer) 3  
  7. > lrange mylist 0 -1    # -1 表示倒數第一個元素, 這里表示從第一個元素到最后一個元素,即所有  
  8. 1) "first"  
  9. 2) "A"  
  10. 3) "B" 

list 實現隊列

隊列是先進先出的數據結構,常用于消息排隊和異步邏輯處理,它會確保元素的訪問順序: 

  1. > RPUSH books python java golang  
  2. (integer) 3  
  3. > LPOP books  
  4. "python"  
  5. > LPOP books  
  6. "java"  
  7. > LPOP books  
  8. "golang"  
  9. > LPOP books  
  10. (nil) 

list 實現棧

棧是先進后出的數據結構,跟隊列正好相反: 

  1. > RPUSH books python java golang  
  2. > RPOP books  
  3. "golang"  
  4. > RPOP books  
  5. "java"  
  6. > RPOP books  
  7. "python"  
  8. > RPOP books  
  9. (nil) 

3)字典 hash

Redis 中的字典相當于 Java 中的 HashMap,內部實現也差不多類似,都是通過 "數組 + 鏈表" 的鏈地址法來解決部分 哈希沖突,同時這樣的結構也吸收了兩種不同數據結構的優點。源碼定義如 dict.h/dictht 定義: 

  1. typedef struct dictht {  
  2.     // 哈希表數組  
  3.     dictEntry **table;  
  4.     // 哈希表大小  
  5.     unsigned long size;  
  6.     // 哈希表大小掩碼,用于計算索引值,總是等于 size - 1  
  7.     unsigned long sizemask;  
  8.     // 該哈希表已有節點的數量  
  9.     unsigned long used;  
  10. } dictht;  
  11. typedef struct dict {  
  12.     dictType *type;  
  13.     void *privdata;  
  14.     // 內部有兩個 dictht 結構  
  15.     dictht ht[2];  
  16.     long rehashidx; /* rehashing not in progress if rehashidx == -1 */  
  17.     unsigned long iterators; /* number of iterators currently running */  
  18. } dict; 

table 屬性是一個數組,數組中的每個元素都是一個指向 dict.h/dictEntry 結構的指針,而每個 dictEntry 結構保存著一個鍵值對: 

  1. typedef struct dictEntry {  
  2.     // 鍵  
  3.     void *key;  
  4.     // 值  
  5.     union {  
  6.         void *val;  
  7.         uint64_t u64;  
  8.         int64_t s64;  
  9.         double d;  
  10.     } v;  
  11.     // 指向下個哈希表節點,形成鏈表  
  12.     struct dictEntry *next;  
  13. } dictEntry; 

可以從上面的源碼中看到,實際上字典結構的內部包含兩個 hashtable,通常情況下只有一個 hashtable 是有值的,但是在字典擴容縮容時,需要分配新的 hashtable,然后進行 漸進式搬遷 (下面說原因)。

漸進式 rehash

大字典的擴容是比較耗時間的,需要重新申請新的數組,然后將舊字典所有鏈表中的元素重新掛接到新的數組下面,這是一個 O(n) 級別的操作,作為單線程的 Redis 很難承受這樣耗時的過程,所以 Redis 使用 漸進式 rehash 小步搬遷:

漸進式 rehash 會在 rehash 的同時,保留新舊兩個 hash 結構,如上圖所示,查詢時會同時查詢兩個 hash 結構,然后在后續的定時任務以及 hash 操作指令中,循序漸進的把舊字典的內容遷移到新字典中。當搬遷完成了,就會使用新的 hash 結構取而代之。

擴縮容的條件

正常情況下,當 hash 表中 元素的個數等于第一維數組的長度時,就會開始擴容,擴容的新數組是 原數組大小的 2 倍。不過如果 Redis 正在做 bgsave(持久化命令),為了減少內存也得過多分離,Redis 盡量不去擴容,但是如果 hash 表非常滿了,達到了第一維數組長度的 5 倍了,這個時候就會 強制擴容。

當 hash 表因為元素逐漸被刪除變得越來越稀疏時,Redis 會對 hash 表進行縮容來減少 hash 表的第一維數組空間占用。所用的條件是 元素個數低于數組長度的 10%,縮容不會考慮 Redis 是否在做 bgsave。

字典的基本操作

hash 也有缺點,hash 結構的存儲消耗要高于單個字符串,所以到底該使用 hash 還是字符串,需要根據實際情況再三權衡: 

  1. > HSET books java "think in java"    # 命令行的字符串如果包含空格則需要使用引號包裹  
  2. (integer) 1  
  3. > HSET books python "python cookbook"  
  4. (integer) 1  
  5. > HGETALL books    # key 和 value 間隔出現  
  6. 1) "java"  
  7. 2) "think in java"  
  8. 3) "python"  
  9. 4) "python cookbook"  
  10. > HGET books java  
  11. "think in java"  
  12. > HSET books java "head first java"    
  13. (integer) 0        # 因為是更新操作,所以返回 0  
  14. > HMSET books java "effetive  java" python "learning python"    # 批量操作  
  15. OK 

4)集合 set

Redis 的集合相當于 Java 語言中的 HashSet,它內部的鍵值對是無序、唯一的。它的內部實現相當于一個特殊的字典,字典中所有的 value 都是一個值 NULL。

集合 set 的基本使用

由于該結構比較簡單,我們直接來看看是如何使用的: 

  1. > SADD books java  
  2. (integer) 1  
  3. > SADD books java    # 重復  
  4. (integer) 0  
  5. > SADD books python golang  
  6. (integer) 2  
  7. > SMEMBERS books    # 注意順序,set 是無序的  
  8. 1) "java"  
  9. 2) "python"  
  10. 3) "golang"  
  11. > SISMEMBER books java    # 查詢某個 value 是否存在,相當于 contains  
  12. (integer) 1  
  13. > SCARD books    # 獲取長度  
  14. (integer) 3  
  15. > SPOP books     # 彈出一個  
  16. "java" 

5)有序列表 zset

這可能使 Redis 最具特色的一個數據結構了,它類似于 Java 中 SortedSet 和 HashMap 的結合體,一方面它是一個 set,保證了內部 value 的唯一性,另一方面它可以為每個 value 賦予一個 score 值,用來代表排序的權重。

它的內部實現用的是一種叫做 「跳躍表」 的數據結構,由于比較復雜,所以在這里簡單提一下原理就好了:

想象你是一家創業公司的老板,剛開始只有幾個人,大家都平起平坐。后來隨著公司的發展,人數越來越多,團隊溝通成本逐漸增加,漸漸地引入了組長制,對團隊進行劃分,于是有一些人又是員工又有組長的身份。

再后來,公司規模進一步擴大,公司需要再進入一個層級:部門。于是每個部門又會從組長中推舉一位選出部長。

跳躍表就類似于這樣的機制,最下面一層所有的元素都會串起來,都是員工,然后每隔幾個元素就會挑選出一個代表,再把這幾個代表使用另外一級指針串起來。然后再在這些代表里面挑出二級代表,再串起來。最終形成了一個金字塔的結構。

想一下你目前所在的地理位置:亞洲 > 中國 > 某省 > 某市 > ....,就是這樣一個結構!

有序列表 zset 基礎操作 

  1. > ZADD books 9.0 "think in java"  
  2. > ZADD books 8.9 "java concurrency"  
  3. > ZADD books 8.6 "java cookbook"  
  4. > ZRANGE books 0 -1     # 按 score 排序列出,參數區間為排名范圍  
  5. 1) "java cookbook"  
  6. 2) "java concurrency"  
  7. 3) "think in java"  
  8. > ZREVRANGE books 0 -1  # 按 score 逆序列出,參數區間為排名范圍  
  9. 1) "think in java"  
  10. 2) "java concurrency"  
  11. 3) "java cookbook"  
  12. > ZCARD books           # 相當于 count()  
  13. (integer) 3  
  14. > ZSCORE books "java concurrency"   # 獲取指定 value 的 score  
  15. "8.9000000000000004"                # 內部 score 使用 double 類型進行存儲,所以存在小數點精度問題  
  16. > ZRANK books "java concurrency"    # 排名  
  17. (integer) 1  
  18. > ZRANGEBYSCORE books 0 8.91        # 根據分值區間遍歷 zset  
  19. 1) "java cookbook"  
  20. 2) "java concurrency"  
  21. > ZRANGEBYSCORE books -inf 8.91 withscores  # 根據分值區間 (-∞, 8.91] 遍歷 zset,同時返回分值。inf 代表 infinite,無窮大的意思。  
  22. 1) "java cookbook"  
  23. 2) "8.5999999999999996"  
  24. 3) "java concurrency"  
  25. 4) "8.9000000000000004"  
  26. > ZREM books "java concurrency"             # 刪除 value  
  27. (integer) 1  
  28. > ZRANGE books 0 -1  
  29. 1) "java cookbook"  
  30. 2) "think in java"  

 

責任編輯:龐桂玉 來源: Java知音
相關推薦

2019-11-11 14:55:25

Redis數據類型命令

2011-07-04 10:32:37

JAVA

2019-09-02 09:48:39

Redis數據結構對象

2020-02-03 16:52:43

Redis數據結構知道

2019-10-29 08:59:16

Redis底層數據

2023-07-04 08:41:08

Redis數據類型

2025-01-13 06:10:00

2025-05-13 08:05:00

Redis數據類型數據庫

2023-11-12 21:49:10

Redis數據庫

2024-11-04 06:20:00

Redis單線程

2023-04-11 08:00:56

Redis類型編碼

2021-03-03 10:08:40

數據算法技術

2023-03-06 08:40:43

RedisListJava

2022-04-10 23:38:33

Redis數據結構開發

2022-02-22 15:27:46

數據結構容器算法

2024-01-26 06:42:05

Redis數據結構

2020-06-29 07:44:36

Redis

2011-06-22 12:57:54

JVM

2011-07-13 15:47:58

C

2019-06-12 22:51:57

Redis軟件開發
點贊
收藏

51CTO技術棧公眾號

老司机99精品99| 欧美福利一区二区| 精品久久久久香蕉网| 久久一区二区三区欧美亚洲| 久草手机视频在线观看| 亚洲av无码乱码国产麻豆| 奇米亚洲欧美| 日本91福利区| 日韩精品免费在线视频| 青青视频免费在线观看| 国产精品sm调教免费专区| av不卡一区| 亚洲欧美日韩国产手机在线| 国产精品黄视频| 国产艳俗歌舞表演hd| av片在线观看网站| 免费观看成人av| 亚洲欧美三级伦理| 国产成人在线免费看| 亚洲第一精品网站| 三级久久三级久久| 国产亚洲日本欧美韩国| 97在线播放视频| 四虎在线免费观看| 亚洲在线国产日韩欧美| 日韩av中文在线| 91亚洲免费视频| 免费av网站在线看| 国产美女主播视频一区| 欧美大成色www永久网站婷| www.成年人| 男人天堂手机在线| 国产偷国产偷亚洲高清人白洁| 欧美一级免费看| 久久av无码精品人妻系列试探| 女厕盗摄一区二区三区| 97久久精品人人爽人人爽蜜臀| 欧美高清在线视频观看不卡| 欧美xxxx日本和非洲| 大地资源网3页在线观看| 国产最新精品精品你懂的| 日韩视频免费观看| 日本中文字幕有码| 青青国产精品| 亚洲免费电影在线| 亚洲欧洲久久| 国产wwwxxx| 亚洲国产精品一区制服丝袜| 亚洲欧洲国产精品| 在线观看岛国av| 久久香蕉av| 成人一区二区三区在线观看 | 国产风韵犹存在线视精品| 7777精品久久久大香线蕉| 一区二区三区不卡在线| 国产视频在线观看免费| 伊人激情综合| 亚洲图中文字幕| 97人妻精品一区二区三区免| www.丝袜精品| 精品毛片乱码1区2区3区| 亚洲欧美一区二区三区不卡| 久草在线资源站资源站| 一区二区三区四区不卡在线| 久久久久se| 夜夜嗨av禁果av粉嫩avhd| 欧美jizzhd精品欧美巨大免费| 亚洲国产成人91精品| 日韩亚洲在线视频| 羞羞视频在线观看免费| 久久综合狠狠综合久久综合88 | 亚洲精品美女久久| 国产男女无遮挡猛进猛出| 日韩精品卡一| 亚洲午夜免费电影| 亚洲成人一区二区三区| av播放在线| 成人精品鲁一区一区二区| 国产精品第一视频| 怡红院成永久免费人全部视频| 在线观看日韩av电影| 97av在线影院| 免费人成视频在线| 日韩一级毛片| 日韩成人在线免费观看| 黄色正能量网站| 亚洲精品在线播放| 欧美日韩精品一区二区三区蜜桃 | 99在线观看免费视频精品观看| 色婷婷综合久久久久中文字幕1| 日本一级大毛片a一| 亚洲伊人精品酒店| 色婷婷久久久久swag精品| a级黄色片网站| 国产免费av高清在线| 成人免费毛片片v| 欧美精品一区二区三区在线看午夜| av高清一区二区| 不卡的av电影在线观看| 偷拍视频一区二区| 午夜在线观看视频18| 国产成人av电影在线播放| 国产欧美久久久久久| 成人午夜视频在线播放| 欧美激情综合色综合啪啪| 丝袜情趣国产精品| 久久亚洲精品大全| 欧美 日韩 国产精品免费观看| 久久久久亚洲精品| 久久久久久国产精品免费播放| 国产精品日韩| 国产aⅴ夜夜欢一区二区三区| 日本a在线观看| 亚洲欧美综合久久久| 日韩亚洲欧美成人| 日韩特黄一级片| 一本久道久久久| 成人黄色免费片| 国产精品老熟女视频一区二区| 日韩av一级电影| 国产不卡一区二区三区在线观看 | 日韩手机在线导航| 成年人网站av| 一区二区三区四区视频免费观看| 精品亚洲国产视频| 美女爆乳18禁www久久久久久| 久久成人高清| 久久久久久久999| 少妇一级淫片免费放中国| 国产亚洲在线观看| 97av自拍| 人妻少妇精品无码专区| av中文字幕一区| 欧美二区三区| av色在线观看| 日本道精品一区二区三区| 五月婷婷丁香综合网| 亚洲图片小说区| 一区二区三欧美| 久久精品一区二区三区四区五区 | 欧美亚洲成人免费| 国精产品乱码一区一区三区四区| 成人高清在线视频| 激情五月五月婷婷| av成人影院在线| 日韩欧美一区中文| 污污免费在线观看| 久久av网址| 秋霞av国产精品一区| 在线观看国产精品视频| 国产偷v国产偷v亚洲高清| 成人一级片网站| 亚洲国产网址| 欧美成人一区二区三区电影| 亚洲在线免费观看视频| 国产精品亲子乱子伦xxxx裸| 丰满女人性猛交| 日日夜夜亚洲| 久久久www成人免费精品| 国产大片aaa| 日韩国产欧美在线视频| 奇米精品在线| 四虎av在线| 精品久久久久av影院| 精品少妇久久久久久888优播| 成人黄页在线观看| 亚洲自偷自拍熟女另类| 91成人小视频| 久久久久久久久91| 香蕉视频免费看| 91成人看片片| 亚洲麻豆一区二区三区| 亚洲精品看片| 日本成人黄色| 成人在线视频国产| 亚洲天堂男人的天堂| 青青艹在线观看| 亚洲欧美一区二区视频| 亚洲性生活网站| 精品国产一区二区三区不卡蜜臂| 中文字幕欧美日韩| 国产日产精品一区二区三区| 国产天堂亚洲国产碰碰| 极品粉嫩美女露脸啪啪| 影音先锋一区| 日韩黄色影视| 国产伦精品一区二区三区视频金莲| 91精品国产入口在线| 日韩av片在线| 亚洲欧美日韩专区| 艳色歌舞团一区二区三区| 欧美欧美在线| 日韩视频永久免费观看| 蜜臀久久精品久久久久| 在线观看日韩高清av| 看片网站在线观看| 激情久久五月天| 久久av综合网| 亚洲成av人片在线观看www| 日韩在线观看免费高清完整版| 精品人妻少妇AV无码专区| 亚洲三级在线免费观看| 手机免费av片| 亚洲视频成人| 先锋影音男人资源| 美女精品一区最新中文字幕一区二区三区 | 97天天综合网| 最新日韩中文字幕| 香蕉视频成人在线| 欧美成人a视频| 97精品人妻一区二区三区香蕉| 久久毛片高清国产| 两性午夜免费视频| 日本不卡高清视频| 自慰无码一区二区三区| 欧美精品一卡| 在线观看免费91| 亚洲资源在线| 国产成人精品亚洲精品| 91在线免费看| 日韩精品极品视频免费观看| 亚洲成人第一区| 欧美精品一二三区| 天天天天天天天干| 一本高清dvd不卡在线观看| 久久久精品91| 亚洲欧美偷拍另类a∨色屁股| www亚洲色图| 蓝色福利精品导航| 91国在线高清视频| 精品国产鲁一鲁****| 国产精品久久久久一区二区| 欧洲美女少妇精品| 亚洲三级 欧美三级| 人妻妺妺窝人体色www聚色窝| 欧美大片国产精品| 国产视频一区二区三区四区五区| 欧美日韩中文字幕一区二区| 性欧美videos| 99精品欧美一区| 香蕉在线观看视频| 国产一区二区调教| 国产精品久久久久久久99| 免费高清在线一区| 亚洲一级片免费| 男女男精品网站| 五月婷婷狠狠操| 国产精品草草| 日产中文字幕在线精品一区| 欧美天堂社区| 国产一区玩具在线观看| cao在线视频| 久久久久免费视频| 久草在线资源站资源站| 性日韩欧美在线视频| 91ph在线| 视频在线观看一区二区| 精品孕妇一区二区三区| 久热精品视频在线免费观看 | 亚洲天堂av在线免费观看| 青青草视频免费在线观看| 欧美日产国产精品| 亚洲在线观看av| 日韩欧美国产午夜精品| 亚洲国产精品suv| 亚洲国产成人精品久久久国产成人一区 | 91精品久久久久久蜜臀| 99久久精品国产一区色| 精品欧美乱码久久久久久| 污视频软件在线观看| 亚洲视屏在线播放| 超碰在线最新| 2019av中文字幕| 天然素人一区二区视频| 欧美黑人国产人伦爽爽爽| 成人bbav| 久久久久久欧美| 2022成人影院| 成人免费福利在线| 欧美激情影院| 亚洲激情一区二区| 欧美成人中文| 成人免费无码av| 国产一区二区福利| 国产精品第七页| 国产精品资源网| 亚洲综合激情视频| 福利一区福利二区| 久久精品国产亚洲AV熟女| 国产精品久久久久aaaa樱花 | 日本欧美韩国国产| 五月天久久狠狠| 狠狠爱综合网| 奇米影视四色在线| 成人a区在线观看| 超碰人人干人人| 亚州成人在线电影| 九九视频免费观看| 欧亚洲嫩模精品一区三区| 99免费在线视频| 亚洲人成绝费网站色www| 91网在线看| 国产精品黄色av| 欧美日韩大片免费观看| 中文字幕剧情在线观看一区| 宅男噜噜噜66国产日韩在线观看| 一女二男3p波多野结衣| 91看片淫黄大片一级| 欧美一区二区三区成人精品| 中文字幕综合网| 无码人妻一区二区三区线| 欧美午夜视频在线观看| 久久久精品福利| 日韩精品在线一区| 9色在线观看| 日本91av在线播放| 国产乱人伦丫前精品视频| 久久精品日产第一区二区三区乱码| 亚洲成人av| 99国产精品白浆在线观看免费| 欧美三级网页| 欧美成人福利在线观看| 2023国产一二三区日本精品2022| 久久午夜无码鲁丝片午夜精品| 8v天堂国产在线一区二区| 懂色一区二区三区| 国产99久久精品一区二区| 青青久久av| 青青草视频在线免费播放 | 午夜免费日韩视频| 精品视频在线观看免费观看| 亚洲欧洲一区二区福利| 久久亚洲风情| 亚洲一区日韩精品| 久久精品人人做人人爽97| 800av免费在线观看| 亚洲第一中文字幕| 精品精品导航| 国产精品区一区二区三含羞草| 日韩中文av| 艳母动漫在线免费观看| 蜜臀av一区二区在线免费观看| 久久亚洲无码视频| 色综合久久综合网欧美综合网| 手机看片一区二区三区| 中文字幕在线观看亚洲| 巨胸喷奶水www久久久| 日韩欧美国产二区| 日韩激情在线观看| www.日本高清视频| 欧美男男青年gay1069videost| 在线观看av黄网站永久| 欧美劲爆第一页| 粉嫩av一区二区| 日本a视频在线观看| 看片网站欧美日韩| 久久av红桃一区二区禁漫| 51精品国自产在线| 性欧美videos高清hd4k| 国产女主播一区二区| 色综合蜜月久久综合网| 911福利视频| 亚洲综合久久av| 中文字幕一区二区三区人妻四季| 中文国产成人精品久久一| 欧美一级做a| 国产91porn| 99久久精品费精品国产一区二区| 六月丁香婷婷综合| 色老头一区二区三区在线观看| 欧美a级大片在线| 青青草成人免费在线视频| 国产亚洲自拍一区| 国产又爽又黄又嫩又猛又粗| 欧美激情一级精品国产| 欧美a一欧美| 欧美三级午夜理伦三级富婆| 亚洲蜜桃精久久久久久久| 四虎在线视频免费观看| 国产不卡在线观看| 亚洲一区二区日韩| 黄色性生活一级片| 欧美另类高清zo欧美| eeuss鲁一区二区三区| 日韩黄色影视| 成人自拍视频在线观看| 91黑人精品一区二区三区| 亚洲精品美女在线观看| 成人mm视频在线观看| 台湾无码一区二区| 久久久久国产一区二区三区四区| 国产一级视频在线观看| 亚洲欧洲美洲在线综合| 美女久久精品| 欧美一级黄色影院| 亚洲一区二区欧美| av福利精品| 久久久久久久有限公司| 激情伊人五月天久久综合| 黄色在线观看国产|