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

如何理解 Redis 是單線程的

開發 Redis
本文我們會直接通過 3.0.0 源碼分析的角度來剖析一下 Redis 單線程的設計與實現。

一、在文章開頭

你剛剛說redis是單線程的,那你能不能告訴我它是如何基于單個線程完成指令處理與客戶端連接接?

基于這個問題,筆者會直接通過3.0.0源碼分析的角度來剖析一下redis單線程的設計與實現。

二、詳解redis的單線程模型

1. 單線程處理核心任務

當我們通過./redis-server啟動redis時,如果我們配置了后臺啟動,那么shell進程線程就會調用系統函數即fork方法創建一個子進程,再通過execve方法將子進程主體替換成redis可執行文件也就是我們的redis-server,而子進程執行時會保持從父進程集成過來的標準輸入和輸出,最后redis就會調用main方法開始執行自己的啟動邏輯了。

到這為止,我們不難看出,在啟動階段redis的啟動并不是多線程的,它會根據我們的配置來決定啟動邏輯,以我們上文所說的后臺啟動,它本質是通過父進程fork的方式完成創建與初始化的,這一點我們也可以直接從redis的main方法印證:

int main(int argc, char **argv) {
   //命令參數解析與初始化
   //......
   //如果配置后臺啟動,則調用daemonize從父進程中fork出來執行
    if (server.daemonize) daemonize();
    //......
}

我們步入daemonize方法,可以看到其內部如果子進程fork成功,后續的標準輸入、輸出、錯誤都會重定向到/dev/null,此后的各項工作也都是交由我們的redis server的主線程進行負責處理:

void daemonize(void) {
    int fd;
    //fork返回0說明fork成功,創建新會話,然后父進程exit(0)直接退出
    if (fork() != 0) exit(0); /* parent exits */
    setsid(); /* create a new session */

   
    //將標準輸入、輸出、錯誤重定向寫到/dev/null中,由此和終端分離
    if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
        dup2(fd, STDIN_FILENO);
        dup2(fd, STDOUT_FILENO);
        dup2(fd, STDERR_FILENO);
        if (fd > STDERR_FILENO) close(fd);
    }
}

此時,主線程的socket就會注冊到epoll中,通過非阻塞調用epoll函數獲取就緒的連接和指令完成與多個客戶端的交互:

而上述所說這種工作模式,也就是我們的aeMain函數,這里筆者也給出的對應的的代碼實現,如下所示,aeMain的本質邏輯就是調用無限循環,在循環中調用aeApiPoll即epoll非阻塞輪詢獲取就緒的事件并交給對應的讀寫事件處理器(rfileProc/wfileProc)進行處理:

//無限循環調用aeProcessEvents處理讀寫事件
void aeMain(aeEventLoop *eventLoop) {
    eventLoop->stop = 0;
    //輪詢標識沒有停止則無限循環
    while (!eventLoop->stop) {
        if (eventLoop->beforesleep != NULL)
            eventLoop->beforesleep(eventLoop);
         //輪詢并處理事件
        aeProcessEvents(eventLoop, AE_ALL_EVENTS);
    }
}


int aeProcessEvents(aeEventLoop *eventLoop, int flags)
{
     //......
  //通過epoll完成非阻塞調用
        numevents = aeApiPoll(eventLoop, tvp);
        //遍歷拿到的事件將其交給讀寫處理器處理
        for (j = 0; j < numevents; j++) {
         //解析出該文件對應的類型
            aeFileEvent *fe = &eventLoop->events[eventLoop->fired[j].fd];
            int mask = eventLoop->fired[j].mask;
            int fd = eventLoop->fired[j].fd;
            int rfired = 0;

      //如果事件fe是讀事件則交給rfileProc
            if (fe->mask & mask & AE_READABLE) {
                rfired = 1;
                fe->rfileProc(eventLoop,fd,fe->clientData,mask);
            }
            //如果事件包含寫標志,則交給wfileProc處理器處理
            if (fe->mask & mask & AE_WRITABLE) {
                if (!rfired || fe->wfileProc != fe->rfileProc)
                    fe->wfileProc(eventLoop,fd,fe->clientData,mask);
            }
            processed++;
        }
    }
   //......
 //返回處理事件數
    return processed; /* return the number of processed file/time events */
}

2. 多線程執行IO事件

截至到上述的片段,redis大體上我們可以認為是單線程執行,但是在3.0.0之后源碼中,為了避免某些IO任務對主線程的執行效率的影響,redis還是創建了一些異步線程處理這些任務。

如下圖所示,我們以aof為例,redis主線程會通過定時任務的方法serverCron會按照用戶的配置檢查當前是否需要進行aof寫入,如果需要則通過bioCreateBackgroundJob提交一個任務到AOF異步刷盤的任務列表中,此時redis創建的io線程就會無限循環調用bioProcessBackgroundJobs從該列表中取出自己綁定的任務進行異步消費,通過這種簡單的多線程模式,保證了耗時的IO操作不會阻塞主線程:

這里我們先給出對應的事件宏定義,可以看到事件總數為REDIS_BIO_NUM_OPS 即2,然后0是文件關閉事件,1的AOF異步刷盤事件,通過這樣的順序完成了事件的類型碼和總量的定義:

/* Background job opcodes */
#define REDIS_BIO_CLOSE_FILE    0 /* Deferred close(2) syscall. */
#define REDIS_BIO_AOF_FSYNC     1 /* Deferred AOF fsync. */
#define REDIS_BIO_NUM_OPS       2

對應的這些線程的初始化工作我們可以在main方法調用的initServer中可以看到這樣一段調用,其內部的調用bioInit本質就是完成上述IO任務的線程的創建:

void initServer(void) {
    int j;

    //......
    //創建bio任務線程
    bioInit();
}

bioInit它會初始化2個線程以及棧大小(最大不會超過4M),為每個線程各自分配一個隊列,分配隊列這一步就會按照循環遍歷得到的值進行分配,遍歷時用REDIS_BIO_NUM_OPS作為范圍控制,遍歷到0的處理文件關閉事件,1則是AOF刷盤事件。 完成事件類型隊列分配之后,redis會為每個線程分配消費任務的方法指針bioProcessBackgroundJobs,后續的線程的任務消費和處理都是調用這個方法執行的:

void bioInit(void) {
    pthread_attr_t attr;
    pthread_t thread;
    size_t stacksize;
    int j;

 //循環2次,剛剛好對應2個事件即0是文件關閉事件、1是aof刷盤事件
    for (j = 0; j < REDIS_BIO_NUM_OPS; j++) {
        //互斥數組初始化
        pthread_mutex_init(&bio_mutex[j],NULL);
        //條件數組初始化
        pthread_cond_init(&bio_condvar[j],NULL);
        //bio任務數組初始化,每個數組元素都是一個任務列表
        bio_jobs[j] = listCreate();
        //表示每種任務列表待處理的任務數為0
        bio_pending[j] = 0;
    }
    //設置線程最大的棧屬性大小,默認為1,若小于REDIS_THREAD_STACK_SIZE即4M則乘2
    pthread_attr_init(&attr);
    pthread_attr_getstacksize(&attr,&stacksize);
    if (!stacksize) stacksize = 1; 
    while (stacksize < REDIS_THREAD_STACK_SIZE) stacksize *= 2;
    pthread_attr_setstacksize(&attr, stacksize);

  
    //創建線程并,為每一個線程分配一個任務列表
    for (j = 0; j < REDIS_BIO_NUM_OPS; j++) {
     //循環兩次 j為0即代表文件關閉事件、1是aof刷盤事件,這個arg會作為事件類型綁定到線程pthread上
        void *arg = (void*)(unsigned long) j;
        //調用pthread_create完成線程屬性初始化和事件類型的綁定
        if (pthread_create(&thread,&attr,bioProcessBackgroundJobs,arg) != 0) {
            redisLog(REDIS_WARNING,"Fatal: Can't initialize Background Jobs.");
            exit(1);
        }
        bio_threads[j] = thread;
    }
}

這里我們也給出bioProcessBackgroundJobs邏輯可以看到,每個線程調用該方法時,會在無限循環中根據任務的type按需消費處理:

void *bioProcessBackgroundJobs(void *arg) {
    struct bio_job *job;
    //每個線程都會根據自己傳入的arg決定任務的type,0為文件關閉事件、1為aof刷盤事件
    unsigned long type = (unsigned long) arg;
    sigset_t sigset;

    //......
    //按照類型到bio_jobs取任務執行
    while(1) {
        listNode *ln;

       //......
       //取出自己需要處理的類型的隊列任務
        ln = listFirst(bio_jobs[type]);
        job = ln->value;
       //上互斥鎖
        pthread_mutex_unlock(&bio_mutex[type]);

       //線程按照自己的類型進行消費
        if (type == REDIS_BIO_CLOSE_FILE) {
            close((long)job->arg1);
        } else if (type == REDIS_BIO_AOF_FSYNC) {
            aof_fsync((long)job->arg1);
        } else {
            redisPanic("Wrong job type in bioProcessBackgroundJobs().");
        }
        //完成后釋放任務對象
        zfree(job);

      //線程解鎖 任務移除
        pthread_mutex_lock(&bio_mutex[type]);
        //任務處理完成后的收尾工作
        listDelNode(bio_jobs[type],ln);
        bio_pending[type]--;
    }
}

了解的任務消費的源碼之后,我們再來看看任務的投遞的邏輯,我們以aof文件刷盤的任務為例,從定時任務函數serverCron,其內部會判斷aof_child_pid的pid不為-1,若不為-1說明當前存在aof子進程,對此redis-server就會獲取當前aof子進程的pid,調用backgroundRewriteDoneHandler提交一個aof重寫完成的回調任務,等待aof重寫完成后該任務就會被消費,從而完成aof緩沖區刷盤:

這里我們直接從serverCron為入口查看上述邏輯,可以看到其內部會查看rdb_child_pid 或者aof_child_pid 的值,這兩個變量分別記錄rdb或者aof異步持久化進程的id值,若達到以下兩個條件則說明存在aof重寫任務,需要提交一個aof重寫后的刷盤任務:

  • aof_child_pid 不是-1
  • wait3獲取到的pid也為aof重寫的子進程id

符合上述條件則調用backgroundRewriteDoneHandler提交一個aof重寫完成后的異步刷盤任務:

int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
    int j;
    REDIS_NOTUSED(eventLoop);
    REDIS_NOTUSED(id);
    REDIS_NOTUSED(clientData);

   //......
  

   //檢查后臺的aof重寫進程是否結束,若結束的步入循環
    if (server.rdb_child_pid != -1 || server.aof_child_pid != -1) {
        int statloc;
        pid_t pid;
  //獲取當前子進程pid
        if ((pid = wait3(&statloc,WNOHANG,NULL)) != 0) {
          //......
            if (pid == server.rdb_child_pid) {
                //......
            } else if (pid == server.aof_child_pid) {//如果pid為aof的子進程值則調用backgroundRewriteDoneHandler     
                backgroundRewriteDoneHandler(exitcode,bysignal);
            } else {
                redisLog(REDIS_WARNING,
                    "Warning, detected child with unmatched pid: %ld",
                    (long)pid);
            }
            updateDictResizePolicy();
        }
    } else {
       //......
    }


 //......
}

步入backgroundRewriteDoneHandler可以看到,如果AOF刷盤策略是AOF_FSYNC_EVERYSEC即異步刷盤則會調用aof_background_fsync進行文件刷盤,而該方法內部的邏輯就是調用我們上文的所說的提交后臺任務方法bioCreateBackgroundJob:

void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
     //......

        if (server.aof_fd == -1) {
           //......
        } else {
            /* AOF enabled, replace the old fd with the new one. */
            oldfd = server.aof_fd;
            server.aof_fd = newfd;
            
            if (server.aof_fsync == AOF_FSYNC_ALWAYS)
                aof_fsync(newfd);
            else if (server.aof_fsync == AOF_FSYNC_EVERYSEC)//如果是異步刷盤則將任務提交到對應的隊列中
             //提交異步刷盤任務到REDIS_BIO_AOF_FSYNC隊列中
                aof_background_fsync(newfd);
            //......
        }

        server.aof_lastbgrewrite_status = REDIS_OK;

      //......
    } else if (!bysignal && exitcode != 0) {
     //......
    } else {
     //......
    }

 //......
}

//調用bioCreateBackgroundJob提交任務到AOF刷盤隊列中
void aof_background_fsync(int fd) {
    bioCreateBackgroundJob(REDIS_BIO_AOF_FSYNC,(void*)(long)fd,NULL,NULL);
}

最終,我們就可以在bioCreateBackgroundJob看到aof異步刷盤的任務提交核心步驟:

  • 獲取任務參數,以我們aof異步刷盤的邏輯第一個參數就是aof子進程的文件句柄。
  • 線程上鎖。
  • 任務入隊。
  • 喚醒相應線程。
  • 釋放互斥鎖。

對應源碼如下,讀者可參考上述說明和注釋了解邏輯:

void bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3) {
    struct bio_job *job = zmalloc(sizeof(*job));

    job->time = time(NULL);
    //獲取aof子進程的fd
    job->arg1 = arg1;
    //以本文為例都說null
    job->arg2 = arg2;
    job->arg3 = arg3;
    //上鎖
    pthread_mutex_lock(&bio_mutex[type]);
    //追加任務到對應job的數組中
    listAddNodeTail(bio_jobs[type],job);
    bio_pending[type]++;
    //通知相關線程消費
    pthread_cond_signal(&bio_condvar[type]);
    //釋放互斥鎖
    pthread_mutex_unlock(&bio_mutex[type]);
}

三、小結

自此我們把redis中主線程和IO任務的線程都以圖解和源碼印證的方式分析完成了,以筆者的理解,設計者所說的redis是單線程的本質上的是強調對于核心的連接建立和指令處理是通過極致壓榨單個線程高效完成,而其余的一些非核心的IO耗時邏輯還是需要多個線程進行異步處理。

責任編輯:趙寧寧 來源: 寫代碼的SharkChili
相關推薦

2025-06-17 00:22:00

2019-06-17 14:20:51

Redis數據庫Java

2022-01-04 11:11:32

Redis單線程Reactor

2019-05-06 11:12:18

Redis高并發單線程

2021-08-10 07:00:01

Redis單線程并發

2022-07-18 13:59:43

Redis單線程進程

2009-07-10 09:05:20

SwingWorker

2020-10-26 08:55:52

Redis單線程模型

2023-10-15 12:23:10

單線程Redis

2019-11-25 10:13:52

Redis單線程I

2021-08-16 15:49:31

開發框架單線程異步

2024-09-27 11:51:33

Redis多線程單線程

2021-06-11 11:28:22

多線程fork單線程

2019-05-07 09:44:45

Redis高并發模型

2024-08-21 10:28:54

Redis數據結構內存

2020-06-11 09:35:39

Redis單線程Java

2020-10-30 16:20:38

Redis單線程高并發

2023-08-17 14:12:17

2020-11-09 09:33:37

多線程

2023-03-21 08:02:36

Redis6.0IO多線程
點贊
收藏

51CTO技術棧公眾號

调教视频免费在线观看| 国产免费www| 久久综合另类图片小说| 欧美午夜电影在线| 特级西西444www大精品视频| 国产精品久久久久精| 欧美在线免费一级片| 亚洲缚视频在线观看| 看欧美ab黄色大片视频免费| 国产成人午夜| 91免费国产在线观看| 国产精品一区专区欧美日韩| 久久久久亚洲av片无码下载蜜桃| 杨幂一区二区三区免费看视频| 精品视频在线免费观看| 亚洲精品无码国产| 素人av在线| 99re亚洲国产精品| 成人精品久久av网站| 亚洲欧美在线观看视频| 亚洲自拍偷拍网| 亚洲精品中文字幕av| 精品国产乱码久久久久久1区二区| 国产精品电影| 亚洲精品视频免费观看| 蜜桃91精品入口| 性欧美videos另类hd| 久久婷婷久久| 韩国福利视频一区| 尤物在线免费视频| 第一sis亚洲原创| 亚洲黄色av女优在线观看| 一区二区在线免费看| 樱桃视频成人在线观看| 亚洲国产成人高清精品| 中文字幕综合在线观看| 精品视频二区| 99久久国产综合精品色伊| 亚洲精品免费在线视频| 伊人精品一区二区三区| 老**午夜毛片一区二区三区| 久久乐国产精品| 黑人巨大精品一区二区在线| 日韩精品久久| 国产一区二区三区在线看| 最近日本中文字幕| 久久久久观看| 亚洲国产成人爱av在线播放| 在线播放av网址| 在线免费成人| 日韩一区二区中文字幕| 中文字幕精品一区二区三区在线| 成人福利一区二区| 欧美偷拍一区二区| 欧美日韩亚洲自拍| 精品欧美一区二区三区在线观看 | 日本精品在线中文字幕| 一本一道久久a久久精品综合蜜臀| 欧美视频在线观看网站| 黄网在线免费看| 亚洲一区二区黄色| 丰满的少妇愉情hd高清果冻传媒| 超碰在线97国产| 午夜久久久久久久久久一区二区| 欧洲精品一区二区三区久久| 国产网红在线观看| 午夜不卡av免费| av免费中文字幕| 韩国三级一区| 欧美久久一二三四区| 免费在线观看污网站| 精品国产18久久久久久二百| 日韩三级.com| 亚洲男女在线观看| 国产亚洲一卡2卡3卡4卡新区 | 成年网站在线视频网站| 亚洲大片免费看| 日本毛片在线免费观看| 亚洲欧美在线成人| 欧美男人的天堂一二区| 亚洲成人av免费观看| 看全色黄大色大片免费久久久| 日韩高清免费观看| 蜜桃av免费观看| 欧美日韩精品| 欧美一级电影久久| 中文字幕+乱码+中文字幕明步| 国产综合久久久久久鬼色| 不卡日韩av| 极品白浆推特女神在线观看| 国产精品电影院| 国产真实老熟女无套内射| 性欧美又大又长又硬| 欧美日本免费一区二区三区| 亚洲一二三四五| 欧美久久精品一级c片| 欧美美最猛性xxxxxx| 久久精品视频1| 国产精品白丝jk白祙喷水网站| 精品国产免费一区二区三区 | 亚洲国产精品视频在线| 久久亚洲影视婷婷| 国产精品av免费观看| 高潮一区二区| 日韩欧美高清在线| 欧美黄色高清视频| 亚洲精品欧美| 亚洲aⅴ日韩av电影在线观看 | 香港三级韩国三级日本三级| 激情中国色综合| 亚洲国产精久久久久久| 午夜激情福利电影| 久久精品卡一| 国产精品午夜av在线| 日本中文字幕在线观看| 欧美日韩亚洲91| 亚洲制服在线观看| 成人午夜国产| 全球成人中文在线| 黄色一级a毛片| 日韩理论片网站| 国产三级三级看三级| 日本韩国欧美超级黄在线观看| 欧美剧在线观看| 中文字幕你懂的| 久久亚区不卡日本| 免费观看美女裸体网站| 日本在线成人| 久久久av一区| 中文字幕制服诱惑| 久久免费午夜影院| 欧美精品久久久久久久免费| 91免费精品国偷自产在线在线| 日韩视频―中文字幕| 欧美一级做a爰片免费视频| 91色porny在线视频| 青青草精品视频在线| 欧美视频二区欧美影视| 久久精品精品电影网| 亚洲影视一区二区| 国产精品美女www爽爽爽| 亚洲国产精品毛片av不卡在线| 蜜桃久久久久| 136fldh精品导航福利| 日韩一区二区三区不卡| 午夜欧美一区二区三区在线播放| 韩国三级hd中文字幕有哪些| 亚洲一区 二区 三区| 91久久夜色精品国产网站| 天堂中文8资源在线8| 欧美精品日韩综合在线| 亚洲a∨无码无在线观看| 久久黄色级2电影| 一区二区日本伦理| 精品一区二区三区中文字幕| 蜜臀久久99精品久久久无需会员| 97精品人妻一区二区三区| 中文字幕亚洲欧美在线不卡| 亚洲涩涩在线观看| 欧美在线三区| 精品久久精品久久| 中文在线аv在线| 国产亚洲免费的视频看| 伊人免费在线观看| 亚洲天堂av一区| 男人添女人荫蒂国产| 亚洲毛片一区| 欧洲精品在线一区| 91精品网站在线观看| 欧美巨猛xxxx猛交黑人97人| 日本毛片在线观看| 色婷婷综合在线| 中文字幕91视频| 国产成人精品影院| 日日鲁鲁鲁夜夜爽爽狠狠视频97| 欧美性感美女一区二区| 91精品视频免费| 91资源在线观看| 国产一区二区三区丝袜| 国产精品久久影视| 午夜精品久久久久| 久久久久亚洲AV成人无在| 国产酒店精品激情| 国内性生活视频| 99久久99久久精品国产片桃花| 91嫩草国产在线观看| 少妇视频在线观看| www.亚洲免费视频| 少妇精品高潮欲妇又嫩中文字幕| 色老综合老女人久久久| 日韩女优一区二区| 久久久久国产精品免费免费搜索| 亚洲欧美日本一区二区三区| 激情av一区| 视频在线观看成人| 第一区第二区在线| 国产狼人综合免费视频| 超免费在线视频| 最近中文字幕日韩精品| 蜜桃在线一区二区| 欧美日韩视频不卡| 91精品国产乱码久久久张津瑜| 国产精品热久久久久夜色精品三区| 91传媒理伦片在线观看| 六月丁香综合在线视频| 精品视频免费在线播放| 97在线精品| 欧美在线一区二区三区四区| 4438全国亚洲精品观看视频| 国产成人在线视频| 波多野结衣精品| yellow中文字幕久久| 你懂的在线网址| 日韩三级精品电影久久久| 又骚又黄的视频| 欧美性感美女h网站在线观看免费| 精品欧美一区二区久久久久| 国产精品天美传媒沈樵| www.超碰97| 国产91精品欧美| 三日本三级少妇三级99| 热久久一区二区| 国产成人a亚洲精v品无码| 国内精品久久久久久久97牛牛| 一区二区三区观看| 欧美一站二站| 欧美一区视久久| 亚洲精品合集| 久久偷窥视频| 极品束缚调教一区二区网站| 国产成人精品日本亚洲11| 国产免费区一区二区三视频免费 | 国产日韩欧美不卡在线| 少妇户外露出[11p]| 成人久久18免费网站麻豆| 日本特黄在线观看| 国产一区二区三区久久久 | 日韩成人一区| 国产精品国产自产拍高清av水多 | 欧美三级欧美一级| 波多野结衣在线观看视频| 欧美日韩视频免费播放| 国产成人在线免费观看视频| 亚洲第一搞黄网站| 日韩免费在线视频观看| 精品欧美一区二区三区| 亚洲精品午夜国产va久久成人| 午夜电影网一区| 成人精品在线看| 五月激情综合网| 日本韩国欧美中文字幕| 欧美性xxxx| 日本三级一区二区三区| 欧美亚洲国产bt| 这里只有精品999| 欧美日韩成人在线一区| 国产熟女一区二区三区四区| 欧美成人伊人久久综合网| 亚洲国产精品视频在线| 日韩国产高清污视频在线观看| 日韩av资源站| 亚洲性日韩精品一区二区| av资源网站在线观看| 日韩中文综合网| www.在线视频| 午夜精品一区二区三区在线播放| 成人爱爱网址| 国产日产欧美精品| 日韩视频一二区| 久久精品成人一区二区三区蜜臀| 亚洲涩涩av| 欧美日韩亚洲国产成人| 黄色成人av网站| 国产成人无码一二三区视频| 美腿丝袜亚洲色图| 下面一进一出好爽视频| 99r国产精品| 来吧亚洲综合网| 亚洲电影在线播放| 夜夜爽妓女8888视频免费观看| 欧美色电影在线| 亚洲精品第五页| 亚洲一级黄色av| 在线观看午夜av| 欧美综合第一页| 最新亚洲国产| 久久久久无码国产精品一区| 日韩在线理论| 精品少妇一区二区三区在线| 青青草国产成人av片免费| 26uuu国产| 日本一区二区三区高清不卡| 久久久国产成人| 欧美性猛交一区二区三区精品| 亚洲第一页在线观看| 亚洲人成免费电影| 欧洲在线视频| 国产精品黄视频| 欧美变态挠脚心| a级网站在线观看| 久久国产日韩| 男人添女人荫蒂国产| 国产精品欧美一级免费| 日韩三级小视频| 欧美一区二区日韩| 99青草视频在线播放视| 91精品国产91久久久久| 国产一区二区视频在线看| 欧美在线视频二区| av成人天堂| 永久免费看片在线观看| 欧美国产日韩亚洲一区| 久久久久久久99| 欧美一级高清片| 欧美日韩在线资源| 日本一区二区三区在线播放| 凹凸成人在线| 欧美精品一区二区性色a+v| 视频一区视频二区中文| 自拍视频一区二区| 艳妇臀荡乳欲伦亚洲一区| 国产精品嫩草影院精东| 夜夜嗨av一区二区三区四区 | 国产精品自产拍在线观看| 伊甸园亚洲一区| 97国产精东麻豆人妻电影| 国产一区高清在线| 亚洲 欧美 国产 另类| 欧美性猛片xxxx免费看久爱| 91精品91久久久中77777老牛| 亚洲毛片在线免费| 日韩高清av电影| 亚洲欧美日韩精品一区二区| 91九色蝌蚪porny| 亚洲一区自拍偷拍| 国产999久久久| 理论片在线不卡免费观看| 久久久免费人体| 亚洲精品中字| 精品中文字幕一区二区| 亚洲不卡的av| 欧美日韩另类一区| 在线激情网站| 91精品国产综合久久香蕉| 99久久精品费精品国产| 中日韩av在线播放| 亚洲欧美成人一区二区三区| 国产精品国产三级国产aⅴ | 国产真实乱人偷精品人妻| 欧美日韩在线免费观看| 日韩a在线观看| 国产精品999999| 色无极亚洲影院| 香蕉视频xxx| 亚洲一区二区三区三| 香蕉视频黄色片| 日本免费在线精品| 欧美一二区在线观看| 国产日韩欧美久久| 亚洲人成亚洲人成在线观看图片| 国产精品久久久久久免费免熟 | 日韩在线影院| 亚洲丰满在线| 国产乱一区二区| 国产午夜福利一区二区| 亚洲男女性事视频| 超碰这里只有精品| 国产人妻互换一区二区| 9l国产精品久久久久麻豆| 综合激情网五月| 日韩一区二区久久久| 日本精品视频| 黄色免费视频大全| 中文在线一区二区| 国产高清视频免费观看| 78m国产成人精品视频| 欧美伦理在线视频| 天天爽夜夜爽视频| 欧美午夜无遮挡| 毛片激情在线观看| 国产一区二区无遮挡| 日韩1区2区日韩1区2区| 欧美卡一卡二卡三| 亚洲人成电影在线播放| 日韩欧美一级| 别急慢慢来1978如如2| 亚洲美女免费视频| 色网站在线免费观看| 国产深夜精品福利| 99视频+国产日韩欧美| 91大神福利视频| 亚洲国模精品私拍| 国产精品一区二区三区av| 日韩中文字幕在线视频观看| 国产精品国产三级国产有无不卡 | 国产视频在线视频| 亚洲精品国产a| 国产免费av在线| 国产经品一区二区| 久久精品国产99|