成人性生交大片免费看视频r_亚洲综合极品香蕉久久网_在线视频免费观看一区_亚洲精品亚洲人成人网在线播放_国产精品毛片av_久久久久国产精品www_亚洲国产一区二区三区在线播_日韩一区二区三区四区区区_亚洲精品国产无套在线观_国产免费www

主頁 > 知識庫 > 詳解Redis用鏈表實(shí)現(xiàn)消息隊(duì)列

詳解Redis用鏈表實(shí)現(xiàn)消息隊(duì)列

熱門標(biāo)簽:小紅書怎么地圖標(biāo)注店 百度商家地圖標(biāo)注怎么做 太原營銷外呼系統(tǒng) 玄武湖地圖標(biāo)注 竹間科技AI電銷機(jī)器人 西藏教育智能外呼系統(tǒng)價(jià)格 地圖標(biāo)注費(fèi)用 地圖標(biāo)注如何即時生效 最簡單的百度地圖標(biāo)注

前言

Redis鏈表經(jīng)常會被用于消息隊(duì)列的服務(wù),以完成多程序之間的消息交換。個人認(rèn)為redis消息隊(duì)列有一個好處,就是可以實(shí)現(xiàn)分布式和共享,就和memcache作為mysql的緩存和mysql自帶的緩存一樣。

鏈表實(shí)現(xiàn)消息隊(duì)列

Redis鏈表支持前后插入以及前后取出,所以如果往尾部插入元素,往頭部取出元素,這就是一種消息隊(duì)列,也可以說是消費(fèi)者/生產(chǎn)者模型??梢岳胠push和rpop來實(shí)現(xiàn)。但是有一個問題,如果鏈表中沒有數(shù)據(jù),那么消費(fèi)者將要在while循環(huán)中調(diào)用rpop,這樣以來就浪費(fèi)cpu資源,好在Redis提供一種阻塞版pop命令brpop或者blpop,用法為brpop/blpop list timeout, 當(dāng)鏈表為空的時候,brpop/blpop將阻塞,直到設(shè)置超時時間到或者list插入一個元素。

用法如下:

charles@charles-Aspire-4741:~/mydir/mylib/redis$ ./src/redis-cli
127.0.0.1:6379> lpush list hello
(integer) 1
127.0.0.1:6379> brpop list 0
1) "list"
2) "hello"
127.0.0.1:6379> brpop list 0
//阻塞在這里
/* ---------------------------------------------------- */
//當(dāng)我在另一個客戶端lpush一個元素之后,客戶端輸出為
127.0.0.1:6379> brpop list 0
1) "list"
2) "world"
(50.60s)//阻塞的時間

當(dāng)鏈表為空的時候,brpop是阻塞的,等待超時時間到或者另一個客戶端lpush一個元素。接下來,看下源碼是如何實(shí)現(xiàn)阻塞brpop命令的。要實(shí)現(xiàn)客戶端阻塞,只需要服務(wù)器不給客戶端發(fā)送消息,那么客戶端就會阻塞在read調(diào)用中,等待消息到達(dá)。這是很好實(shí)現(xiàn)的,關(guān)鍵是如何判斷這個客戶端阻塞的鏈表有數(shù)據(jù)到達(dá)以及通知客戶端解除阻塞?Redis的做法是,將阻塞的鍵以及阻塞在這個鍵上的客戶端鏈表存儲在一個字典中,然后每當(dāng)向數(shù)據(jù)庫插入一個鏈表時,就判斷這個新插入的鏈表是否有客戶端阻塞,有的話,就解除這個阻塞的客戶端,并且發(fā)送剛插入鏈表元素給客戶端,客戶端就這樣解除阻塞。

先看下有關(guān)數(shù)據(jù)結(jié)構(gòu),以及server和client有關(guān)屬性

//阻塞狀態(tài)
typedef struct blockingState {
 /* Generic fields. */
 mstime_t timeout;  /* 超時時間 */
 /* REDIS_BLOCK_LIST */
 dict *keys;    /* The keys we are waiting to terminate a blocking
        * operation such as BLPOP. Otherwise NULL. */
 robj *target;   /* The key that should receive the element,
        * for BRPOPLPUSH. */
 /* REDIS_BLOCK_WAIT */
 int numreplicas;  /* Number of replicas we are waiting for ACK. */
 long long reploffset; /* Replication offset to reach. */
} blockingState;
//繼續(xù)列表
typedef struct readyList {
 redisDb *db;//就緒鍵所在的數(shù)據(jù)庫
 robj *key;//就緒鍵
} readyList;
//客戶端有關(guān)屬性
typedef struct redisClient {
 int btype;    /* Type of blocking op if REDIS_BLOCKED. */
 blockingState bpop;  /* blocking state */
}
//服務(wù)器有關(guān)屬性
struct redisServer {
  /* Blocked clients */
 unsigned int bpop_blocked_clients; /* Number of clients blocked by lists */
 list *unblocked_clients; /* list of clients to unblock before next loop */
 list *ready_keys;  /* List of readyList structures for BLPOP  co */
}
//數(shù)據(jù)庫有關(guān)屬性
typedef struct redisDb {
  //keys->redisCLient映射
  dict *blocking_keys;  /* Keys with clients waiting for data (BLPOP) */
 dict *ready_keys;   /* Blocked keys that received a PUSH */
}redisDB

必須對上述的數(shù)據(jù)結(jié)構(gòu)足夠了解,否則很難看懂下面的代碼,因?yàn)檫@些代碼需要操作上述的數(shù)據(jù)結(jié)構(gòu)。先從brpop命令執(zhí)行函數(shù)開始分析,brpop命令執(zhí)行函數(shù)為

void brpopCommand(redisClient *c) {
 blockingPopGenericCommand(c,REDIS_TAIL);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++
void blockingPopGenericCommand(redisClient *c, int where) {
 robj *o;
 mstime_t timeout;
 int j;
 if (getTimeoutFromObjectOrReply(c,c->argv[c->argc-1],timeout,UNIT_SECONDS)
  != REDIS_OK) return;//將超時時間保存在timeout中
 for (j = 1; j  c->argc-1; j++) {
  o = lookupKeyWrite(c->db,c->argv[j]);//在數(shù)據(jù)庫中查找操作的鏈表
  if (o != NULL) {//如果不為空
   if (o->type != REDIS_LIST) {//不是鏈表類型
    addReply(c,shared.wrongtypeerr);//報(bào)錯
    return;
   } else {
    if (listTypeLength(o) != 0) {//鏈表不為空
     /* Non empty list, this is like a non normal [LR]POP. */
     char *event = (where == REDIS_HEAD) ? "lpop" : "rpop";
     robj *value = listTypePop(o,where);//從鏈表中pop出一個元素
     redisAssert(value != NULL);
     //給客戶端發(fā)送pop出來的元素信息
     addReplyMultiBulkLen(c,2);
     addReplyBulk(c,c->argv[j]);
     addReplyBulk(c,value);
     decrRefCount(value);
     notifyKeyspaceEvent(REDIS_NOTIFY_LIST,event,
          c->argv[j],c->db->id);
     if (listTypeLength(o) == 0) {//如果鏈表為空,從數(shù)據(jù)庫刪除鏈表
      dbDelete(c->db,c->argv[j]);
      notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,"del",
           c->argv[j],c->db->id);
     }
     /* 省略一部分 */
    }
   }
  }
 }
  /* 如果鏈表為空,則阻塞客戶端 */
  blockForKeys(c, c->argv + 1, c->argc - 2, timeout, NULL);
}

從源碼可以看出,brpop可以操作多個鏈表變量,例如brpop list1 list2 0,但是只能輸出第一個有元素的鏈表。如果list1沒有元素,而list2有元素,則輸出list2的元素;如果兩個都有元素,則輸出list1的元素;如果都沒有元素,則等待其中某個鏈表插入一個元素,之后在2返回。最后調(diào)用blockForyKeys阻塞

void blockForKeys(redisClient *c, robj **keys, int numkeys, mstime_t timeout, robj *target) {
 dictEntry *de;
 list *l;
 int j;
 c->bpop.timeout = timeout;//超時時間賦值給客戶端blockingState屬性
 c->bpop.target = target;//這屬性適用于brpoplpush命令的輸入對象,如果是brpop, //則target為空
 if (target != NULL) incrRefCount(target);//不為空,增加引用計(jì)數(shù)
 for (j = 0; j  numkeys; j++) {
  /* 將阻塞的key存入c.bpop.keys字典中 */
  if (dictAdd(c->bpop.keys,keys[j],NULL) != DICT_OK) continue;
  incrRefCount(keys[j]);
  /* And in the other "side", to map keys -> clients */
  //將阻塞的key和客戶端添加進(jìn)c->db->blocking_keys
  de = dictFind(c->db->blocking_keys,keys[j]);
  if (de == NULL) {
   int retval;
   /* For every key we take a list of clients blocked for it */
   l = listCreate();
   retval = dictAdd(c->db->blocking_keys,keys[j],l);
   incrRefCount(keys[j]);
   redisAssertWithInfo(c,keys[j],retval == DICT_OK);
  } else {
   l = dictGetVal(de);
  }
  listAddNodeTail(l,c);//添加到阻塞鍵的客戶點(diǎn)鏈表中
 }
 blockClient(c,REDIS_BLOCKED_LIST);//設(shè)置客戶端阻塞標(biāo)志
}

blockClient函數(shù)只是簡單的設(shè)置客戶端屬性,如下

void blockClient(redisClient *c, int btype) {
 c->flags |= REDIS_BLOCKED;//設(shè)置標(biāo)志
 c->btype = btype;//阻塞操作類型
 server.bpop_blocked_clients++;
}

由于這個函數(shù)之后,brpop命令執(zhí)行函數(shù)就結(jié)束了,由于沒有給客戶端發(fā)送消息,所以客戶端就阻塞在read調(diào)用中。那么如何解開客戶端的阻塞了?

插入一個元素解阻塞

任何指令的執(zhí)行函數(shù)都是在processCommand函數(shù)中調(diào)用call函數(shù),然后在call函數(shù)中調(diào)用命令執(zhí)行函數(shù),lpush也一樣。當(dāng)執(zhí)行完lpush之后,此時鏈表不為空,回到processCommand調(diào)用中,執(zhí)行以下語句

if (listLength(server.ready_keys))
   handleClientsBlockedOnLists();

這兩行代碼是先檢查server.ready_keys是否為空,如果不為空,說明已經(jīng)有一些就緒的鏈表,此時可以判斷是否有客戶端阻塞在這個鍵值上,如果有,則喚醒;現(xiàn)在問題又來了,這個server.ready_keys在哪更新鏈表了?

原來是在dbAdd函數(shù)中,當(dāng)往數(shù)據(jù)庫中添加的值類型為REDIS-LIST時,這時就要調(diào)用signalListAsReady函數(shù)將鏈表指針添加進(jìn)server.ready_keys:

//db.c
void dbAdd(redisDb *db, robj *key, robj *val) {
 sds copy = sdsdup(key->ptr);
 int retval = dictAdd(db->dict, copy, val);//將數(shù)據(jù)添加進(jìn)數(shù)據(jù)庫
 redisAssertWithInfo(NULL,key,retval == REDIS_OK);
 //判斷是否為鏈表類型,如果是,調(diào)用有鏈表已經(jīng)ready函數(shù)
 if (val->type == REDIS_LIST) signalListAsReady(db, key);
 if (server.cluster_enabled) slotToKeyAdd(key);
 }
//t_list.c
void signalListAsReady(redisDb *db, robj *key) {
 readyList *rl;
 /* 沒有客戶端阻塞在這個鍵上,則直接返回. */
 if (dictFind(db->blocking_keys,key) == NULL) return;
 /* 這個鍵已近被喚醒了,所以沒必要重新入隊(duì) */
 if (dictFind(db->ready_keys,key) != NULL) return;
 /* Ok, 除了上述兩情況,把這個鍵放入server.ready_keys */
 rl = zmalloc(sizeof(*rl));
 rl->key = key;
 rl->db = db;
 incrRefCount(key);
 listAddNodeTail(server.ready_keys,rl);//添加鏈表末尾
 /* We also add the key in the db->ready_keys dictionary in order
  * to avoid adding it multiple times into a list with a simple O(1)
  * check. */
 incrRefCount(key);
 //同時將這個阻塞鍵放入db->ready_keys
 redisAssert(dictAdd(db->ready_keys,key,NULL) == DICT_OK);
}

OK,這時server.ready_keys上已經(jīng)有就緒鍵了,這時就調(diào)用processCommand函數(shù)中的handleClientsBlockedOnLists()函數(shù)來處理阻塞客戶端,在這個函數(shù)中,

void handleClientsBlockedOnLists(void) {
 while(listLength(server.ready_keys) != 0) {
  list *l;
  /* 將server.ready_keys賦給一個新的list,再將server.ready_keys清空 */
  l = server.ready_keys;
  server.ready_keys = listCreate();
  /* 迭代每一個就緒的每一個readyList */
  while(listLength(l) != 0) {
   listNode *ln = listFirst(l);//獲取第一個就緒readyList
   readyList *rl = ln->value;
   /* 從rl所屬的數(shù)據(jù)庫中刪除rl */
   dictDelete(rl->db->ready_keys,rl->key);
   /* 查詢r(jià)l所屬的數(shù)據(jù)庫查找rl->key ,給阻塞客戶端回復(fù)rl->key鏈表中的第一個元素*/
   robj *o = lookupKeyWrite(rl->db,rl->key);
   if (o != NULL  o->type == REDIS_LIST) {
    dictEntry *de;
    /* 在rl->db->blocking_keys查找阻塞在rl->key的客戶端鏈表 */
    de = dictFind(rl->db->blocking_keys,rl->key);
    if (de) {
     list *clients = dictGetVal(de);//轉(zhuǎn)換為客戶端鏈表
     int numclients = listLength(clients);
     while(numclients--) {//給每個客戶端發(fā)送消息
      listNode *clientnode = listFirst(clients);
      redisClient *receiver = clientnode->value;//阻塞的客戶端
      robj *dstkey = receiver->bpop.target;//brpoplpush命令目的鏈表
      int where = (receiver->lastcmd 
          receiver->lastcmd->proc == blpopCommand) ?
         REDIS_HEAD : REDIS_TAIL;//獲取取出的方向
      robj *value = listTypePop(o,where);//取出就緒鏈表的元素
      if (value) {
       /* Protect receiver->bpop.target, that will be
        * freed by the next unblockClient()
        * call. */
       if (dstkey) incrRefCount(dstkey);
       unblockClient(receiver);//設(shè)置客戶端為非阻塞狀態(tài)
       if (serveClientBlockedOnList(receiver,
        rl->key,dstkey,rl->db,value,
        where) == REDIS_ERR)
       {
        /* If we failed serving the client we need
         * to also undo the POP operation. */
         listTypePush(o,value,where);
       }//給客戶端回復(fù)鏈表中的元素內(nèi)容
       if (dstkey) decrRefCount(dstkey);
       decrRefCount(value);
      } else {
       break;
      }
     }
    }
    //如果鏈表為空,則從數(shù)據(jù)庫中刪除
    if (listTypeLength(o) == 0) dbDelete(rl->db,rl->key);
    /* We don't call signalModifiedKey() as it was already called
     * when an element was pushed on the list. */
   }
   /* 回收rl */
   decrRefCount(rl->key);
   zfree(rl);
   listDelNode(l,ln);
  }
  listRelease(l); /* We have the new list on place at this point. */
 }
}

從這個源碼可知,如果有兩個客戶端,同時阻塞在一個鏈表上面,那么如果鏈表插入一個元素之后,只有先阻塞的那個客戶端收到消息,后面阻塞的那個客戶端繼續(xù)阻塞,這也是先阻塞先服務(wù)的思想。handleClientsBlockedOnLists函數(shù)調(diào)用了unblockClient(receiver) ,該函數(shù)功能為接觸客戶端阻塞標(biāo)志,以及找到db阻塞在key上的客戶端鏈表,并將接觸阻塞的客戶端從鏈表刪除。然后調(diào)用serveClientBlockOnList給客戶端回復(fù)剛在鏈表插入的元素。

int serveClientBlockedOnList(redisClient *receiver, robj *key, robj *dstkey, redisDb *db, robj *value, int where)
{
 robj *argv[3];
 if (dstkey == NULL) {
  /* Propagate the [LR]POP operation. */
  argv[0] = (where == REDIS_HEAD) ? shared.lpop :
           shared.rpop;
  argv[1] = key;
  propagate((where == REDIS_HEAD) ?
   server.lpopCommand : server.rpopCommand,
   db->id,argv,2,REDIS_PROPAGATE_AOF|REDIS_PROPAGATE_REPL);
  /* BRPOP/BLPOP */
  addReplyMultiBulkLen(receiver,2);
  addReplyBulk(receiver,key);
  addReplyBulk(receiver,value);
 } else {
  /* BRPOPLPUSH */
   /* 省略 */
 }
}

propagate函數(shù)主要是將命令信息發(fā)送給aof和slave。函數(shù)中省略部分是brpoplpush list list1 0命令的目的鏈表list1非空時,將從list鏈表pop出來的元素插入list1中。當(dāng)給客戶端發(fā)送消息之后,客戶端就從read函數(shù)調(diào)用中返回,變?yōu)椴蛔枞?/p>

通過超時時間解阻塞

如果鏈表一直沒有數(shù)據(jù)插入,那么客戶端將會一直阻塞下去,這肯定是不行的,所以brpop還支持超時阻塞,即阻塞時間超過一定值之后,服務(wù)器返回一個空值,這樣客戶端就解脫阻塞了。

對于時間超時,都放在了100ms執(zhí)行一次的時間事件中;超時解脫阻塞函數(shù)也在serverCron中;在serverCron->clientsCron->clientsCronHandleTimeout

int clientsCronHandleTimeout(redisClient *c, mstime_t now_ms) {
 time_t now = now_ms/1000;
 //..........
 else if (c->flags  REDIS_BLOCKED) {
  /* Blocked OPS timeout is handled with milliseconds resolution.
   * However note that the actual resolution is limited by
   * server.hz. */
  if (c->bpop.timeout != 0  c->bpop.timeout  now_ms) {
   /* Handle blocking operation specific timeout. */
   replyToBlockedClientTimedOut(c);
   unblockClient(c);
  }
 }
 //.............

把這個函數(shù)不相干的代碼刪除,主要部分先判斷這個客戶端是否阻塞,如果是,超時時間是否到期,如果是,則調(diào)用replyToBlockedClientTimedOut給客戶端回復(fù)一個空回復(fù),以及接觸客戶端阻塞。

總結(jié)

鏈表消息隊(duì)列實(shí)現(xiàn)暫時分析到這了,大家都學(xué)會了嗎?希望這篇文章給大家能帶來一定的幫助,如果有疑問可以留言交流。

您可能感興趣的文章:
  • SpringBoot利用redis集成消息隊(duì)列的方法
  • PHP使用php-resque庫配合Redis實(shí)現(xiàn)MQ消息隊(duì)列的教程
  • Java利用Redis實(shí)現(xiàn)消息隊(duì)列的示例代碼
  • phpredis提高消息隊(duì)列的實(shí)時性方法(推薦)
  • PHP基于Redis消息隊(duì)列實(shí)現(xiàn)發(fā)布微博的方法
  • php+redis消息隊(duì)列實(shí)現(xiàn)搶購功能
  • 深入理解redis分布式鎖和消息隊(duì)列
  • 詳解redis是如何實(shí)現(xiàn)隊(duì)列消息的ack
  • PHP+Redis 消息隊(duì)列 實(shí)現(xiàn)高并發(fā)下注冊人數(shù)統(tǒng)計(jì)的實(shí)例
  • redis中隊(duì)列消息實(shí)現(xiàn)應(yīng)用解耦的方法

標(biāo)簽:香港 澳門 贛州 唐山 林芝 景德鎮(zhèn) 廣東 揚(yáng)州

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《詳解Redis用鏈表實(shí)現(xiàn)消息隊(duì)列》,本文關(guān)鍵詞  詳解,Redis,用鏈,表,實(shí)現(xiàn),;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《詳解Redis用鏈表實(shí)現(xiàn)消息隊(duì)列》相關(guān)的同類信息!
  • 本頁收集關(guān)于詳解Redis用鏈表實(shí)現(xiàn)消息隊(duì)列的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    四虎影视免费看电影| 久久日免费视频| 欧美aaaaaa午夜精品| 免费成人黄色| 日韩视频免费在线| 在线观看国产原创自拍视频| 欧美日韩国产色综合一二三四| 久久伊人资源站| 欧美大片专区| 亚洲一区高清| 亚洲区综合中文字幕日日| 欧美性猛交xxxx偷拍洗澡| 懂色av影视一区二区三区| 久久久国产精品午夜一区ai换脸| 91在线高清视频| 精品人妻互换一区二区三区| 欧美sm精品调教视频| 9.1成人看片免费版| 国产精品中文久久久久久久| 美女久久久久久久久久久| 99热这里只有精品99| 日韩激情一区二区| 色综合久久精品| 97影院理论片在线播放| 精品国产人成亚洲区| 极品少妇一区二区| 欧美日韩免费观看视频| 伊人网在线综合| 精品一区二区三区欧美| 日韩黄色动漫| 青青草娱乐视频| 欧美一区二区三区小说| 欧美人狂配大交3d怪物一区| 国产精品毛片一区视频| 国产一区免费视频| 免费人成a大片在线观看动漫| 中国女人内谢25xxxxx| 性欧美hd调教| 欧美中文字幕亚洲一区二区va在线| 三级在线视频| 日韩最新中文字幕电影免费看| 任你操精品视频| 欧美性猛交xxxx富婆| 亚洲男人第一天堂| 7777kkkk成人观看| 亚洲综合网站| 一本一道久久a久久精品蜜桃| 亚洲色图另类小说| 成人午夜免费福利| 老熟妇高潮一区二区高清视频| 自拍偷在线精品自拍偷无码专区| 人人超在线公开视频| 国模吧精品视频| 在线精品国产成人综合| 国产日韩欧美综合在线| 亚洲夂夂婷婷色拍ww47| 亚洲国产天堂av| 亚洲欧美日韩国产手机在线| 18黄暴禁片在线观看| 亚洲福利在线看| 一区二区视频免费看| 成人羞羞视频在线看网址| 亚洲日本精品国产第一区| 伊人网在线免费| 五月天综合视频| 久久久久久久久久久久久久久久久久久| 老师让我她我爽了好久视频| 欧美a级在线| 国产成人精品实拍在线| 国产成人啪精品视频免费网| 精品在线观看入口| 美日韩精品免费| 欧美日韩高清在线一区| 久久五月天综合| 天堂网一区二区三区| 欧美福利视频导航| 精品国产乱码久久久久久影片| 麻豆精品一区二区| 99热免费精品| 男人的天堂一区| 久久国产人妖系列| 免费看黄色一级大片| 91免费观看在线| 少妇真人直播免费视频| 国产69精品久久久久毛片| 久久久久久久国产精品| 白白色视频在线| 日韩一级免费| 国产精品国产对白熟妇| 91黑人精品一区二区三区| 《视频一区视频二区| 久久国产视频网| 4438x全国最大成人| 91肉色超薄丝袜脚交一区二区| jizzjizz少妇亚洲水多| 九七影院理伦片| 久久精品免费网站| 7777精品伊人久久久大香线蕉经典版下载| 黄色三级在线| 国产精品亚洲美女av网站| 91在线精品播放| jizzjizz16| 日韩欧美在线综合| 日韩av地址| 9色国产精品| 黄色激情网址| 91精品国产经典在线观看| 亚洲日本视频| 男女无套免费视频网站动漫| 精品中文字幕不卡在线视频| 亚洲欧洲日韩女同| 国产99久久久久久免费看农村| 国产综合免费视频| zzzwww在线看片免费| 99色这里只有精品| 久久久综合av| 日本在线不卡一区| 毛片基地黄久久久久久天堂| 高清一区在线观看| 91精品国产乱码久久久久久| 四虎在线免费观看| 青青草国产免费自拍| 国产精品18久久久久久久网站| 国产精品入口麻豆| 全黄性性激高免费视频| 青春草在线观看视频| 大陆极品少妇内射aaaaaa| 天堂а√在线官网| 神马午夜伦理不卡| 欧美福利在线| 亚洲3p在线观看| 在线成人福利| 日韩欧美精品在线| 欧美成人免费高清视频| 欧美一级大片免费看| 国产欧美在线播放| 亚洲aⅴ天堂av在线电影软件| 国产又黄又爽免费视频| 99在线首页视频| 国产精品99久| av成人免费看| 艳母动漫在线看| 久久久久久久久久久影视| 自拍偷拍中文字幕| 99国产牛牛视频在线网站| 欧美变态视频| 中文字字幕在线中文乱码电影| 人妻夜夜爽天天爽| 欧美精品亚洲二区| 亚洲综合av在线播放| 欧美 日韩精品| 国产精品视频一区二区三区,| 精品人妻一区二区色欲产成人| 亚洲精品偷拍视频| 久久亚洲综合色一区二区三区| 久久一区二区三区视频| 国产视色精品亚洲一区二区| 国产精品一二三四区| 亚洲美女激情视频| 日韩一级欧美一级| 欧美日韩一区精品| 日韩精品在线私人| 情se视频网在线观看| 亚洲成人网av| 一本色道久久综合亚洲精品不卡| 国产精品网站大全| 欧美自拍偷拍网| 日韩欧美高清一区| 国产日韩欧美在线观看视频| 欧美黄色免费影院| 成人黄色免费网站| 久久国产精品国语对白| 色婷婷视频在线| 国产suv精品一区二区69| 天堂网www天堂在线网| 欧洲亚洲一区二区三区四区五区| 中文字幕精品一区二区精品| 欧美精品欧美精品| 欧美mv和日韩mv的网站| 紧缚捆绑精品一区二区| 日韩精品免费一区二区三区竹菊| 蜜桃精品一区二区三区| 国产高清精品在线| 日韩视频在线视频| 亚洲女同一区二区| 国产富婆一级全黄大片| 欧美mv日韩mv国产| 成人免费视频97| 精品综合久久久久久8888| 亚洲成人久久一区| 亚洲一级二级| 日本网站在线免费观看视频| 欧美日韩国产乱码电影| 国产精品国产三级国产传播| 国产精品女上位| 国产剧情久久久| 日韩西西人体444www| 国产精品福利电影一区二区三区四区| 嫩草av久久伊人妇女超级a| www.美色吧.com| 亚洲精品无人区| www.亚洲视频| 国产探花在线观看| 91福利资源站| 午夜国产一区| 久久高清视频免费| 97在线看福利| 久久99热狠狠色一区二区| 国产99精品一区| 欧美日韩国产成人在线观看| 亚洲AV无码乱码国产精品牛牛| 国产精品二区三区四区| 大肉大捧一进一出好爽动态图| 国产一级免费观看| 一区二区三区在线资源| 不卡的av在线播放| 无码人妻一区二区三区一| 天天看天天操| 国产va免费精品观看精品视频| a毛片在线观看| 国产黄色小视频网站| 尤物视频免费在线观看| 91麻豆国产精品| 中文字幕日本一区| 1区2区视频| 正在播放国产精品| 久久一区91| 日韩在线 中文字幕| brazzers在线观看| 成人影院在线观看视频| 亚洲成熟丰满熟妇高潮xxxxx| 国产精品一区二区资源| 九九热精品视频国产| 六月婷婷一区| 国产精品色在线观看| 99香蕉国产精品偷在线观看| 猛男gaygay欧美视频| 影音先锋国产资源| 国产超碰精品在线观看| 日韩在线视频中文字幕| 久久香蕉国产线看观看99| www视频网站| 色网在线免费观看| 凹凸成人精品亚洲精品密奴| 91在线视频官网| 国内外成人免费激情在线视频| 亚洲大香人伊一本线| 国产精品免费99久久久| 欧美性精品220| 欧美视频第二页| 99re视频这里只有精品| 欧洲高清一区二区| 黄色在线免费播放| 超碰在线caoporn| 亚洲午夜网未来影院| 国产精品久久久久久久久久久久久久久久久| 91tv亚洲精品香蕉国产一区7ujn| 亚洲人和日本人hd| 日本簧片在线观看| 国产美女视频免费| 亚洲影院在线看| **精品中文字幕一区二区三区| 亚洲免费视频一区二区| 欧美在线xxx| 波多野结衣中文字幕在线| 国产在线88av| 激情五月婷婷综合| 日韩亚洲欧美一区二区三区| 欧美日韩综合高清一区二区| 欧美性生交大片免费| 日韩理论片av| 国产高清无密码一区二区三区| 美女被黑人40厘米进入| 五月天婷婷丁香网| 农村妇女精品一二区| 欧美aaaaa喷水| 中文字幕一区二区三区视频| 麻豆久久久久久久久久| 日韩精品视频在线观看网址| 国产亚洲欧美另类一区二区三区| 这里只有精品电影| 亚洲人xxxx| 色一情一区二区三区四区| 欧美精品乱码久久久久久| 精品国精品国产尤物美女| 亚洲精品网站在线| 一区二区三区四区视频免费观看| 日韩av在线电影观看| 中国一级片黄色一级片黄| 国产三级在线免费观看| 黄页网址大全在线播放| 国产最新自拍视频| 电影久久久久久| 老熟妇高潮一区二区高清视频| 亚洲国产日韩在线观看| 久久精品一区二区免费播放| jizzjizzjizz孕妇| 日韩欧美国产一二三区| 国产igao激情在线入口| 中文字幕一区电影| 久久久久久成人网| 麻豆一区二区三区精品视频| 日本一二三区不卡| 国产福利久久精品| 欧美久久久网站| 欧美一区二区在线视频观看| 成人a视频在线观看| 国产日韩欧美大片| 亚洲综合五月天婷婷丁香| 亚洲精品无码国产| 日韩伦理一区二区| 国产精品亚洲精品| 美女一区二区三区在线观看| 51国偷自产一区二区三区| 男女啪啪无遮挡| 女生裸体无遮挡天堂网站免费| 久久综合伊人77777尤物| 精品美女久久久久久免费| 欧美老女人性生活视频| 精品国产导航| 国产专区精品| 日韩影片在线观看| 日本三日本三级少妇三级66| 亚洲欧洲一区二区在线观看| 国产在线播放一区二区三区| 菠萝菠萝蜜在线视频免费观看| 波多野结衣电影在线播放| 成人激情视频小说免费下载|