精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

亚洲专区一区二区三区| 综合欧美精品| 久久影院午夜论| 国产精品久久99久久| 一二三四国产精品| 久久丁香四色| 狠狠色狠色综合曰曰| 视频一区二区在线| 超碰在线观看99| 久久国产免费| 欧美日本中文字幕| 欧美偷拍一区二区三区| 国产精一区二区| 日韩欧美综合在线视频| 51xx午夜影福利| 噜噜噜在线观看播放视频| 国产一区二区三区在线观看免费| 97在线看福利| 我要看一级黄色录像| 精品淫伦v久久水蜜桃| 在线视频你懂得一区| 男人天堂av片| 日韩黄色影院| 久久青草国产手机看片福利盒子| 91网站在线看| 成人免费视频国产免费| 伊人久久综合| www.日韩av.com| 波多野结衣中文字幕在线播放| 国产伦精品一区二区三区视频金莲| 亚洲精品国产一区二区精华液 | 日本不卡一区视频| 色婷婷综合久久久久久| 亚洲第一区在线| 污污视频在线免费| 日韩有码欧美| 欧美日韩一区二区三区高清| 亚洲熟妇av一区二区三区| 黄网站在线观| 亚洲免费观看在线观看| 超碰免费在线公开| 紧身裙女教师波多野结衣| 成人亚洲视频| 在线一区二区观看| 欧美丰满熟妇xxxxx| 欧美gay视频| 第一福利永久视频精品| 99在线精品免费视频| 国模私拍视频在线播放| 国产亚洲欧美激情| 欧美精品videosex极品1| 免费看毛片的网站| 国产精品极品| 精品电影一区二区三区| 日本中文字幕精品| 99久久免费精品国产72精品九九| 久久99高清| 亚洲一区二区欧美日韩| 欧美一级爱爱视频| 人人九九精品| 欧美大片网址| 欧美日韩中文另类| 久久综合伊人77777麻豆最新章节| 亚洲日本天堂| 婷婷综合在线观看| 日本成人在线免费视频| jvid一区二区三区| 欧美精品久久久久久久久老牛影院| 欧美一级特黄a| 亚洲国产天堂| 日韩欧美一二区| 国产原创剧情av| www.久久99| 欧美美女黄视频| 欧美日韩理论片| 成人三级毛片| 亚洲片在线资源| 99re久久精品国产| 水蜜桃在线视频| 欧美亚洲日本一区| 亚洲制服在线观看| 久久资源综合| 亚洲成人1234| 久久aaaa片一区二区| 美日韩黄色大片| 中文字幕亚洲一区二区三区五十路| 永久免费看片视频教学| 红桃视频欧美| 国产97在线视频| 99精品在线视频观看| www.色精品| 神马影院午夜我不卡| 美女精品视频| 欧美系列日韩一区| 东京热av一区| 日韩国产欧美| 国自在线精品视频| 国产又大又粗又长| 97se亚洲国产综合在线| 一区二区精品在线观看| а√在线天堂官网| 在线成人小视频| aa片在线观看视频在线播放| 性xxxx欧美老肥妇牲乱| 国产69久久精品成人| 国产又黄又大又粗的视频| 成人av电影在线| 综合久久国产| 成人免费看黄| 精品国产乱码久久久久久牛牛 | 国产精品爽爽久久久久久| 成年人国产精品| 特级毛片在线免费观看| 亚洲第一二三四区| 欧美精品一区二区不卡| 尤物在线免费视频| 日韩和的一区二区| 精选一区二区三区四区五区| a级片国产精品自在拍在线播放| 91久久国产综合久久| 一边摸一边做爽的视频17国产 | 蜜臀久久99精品久久久久久宅男| 波多野结衣 久久| 国产91在线观看丝袜| 亚洲国产精品久久久久久女王| 麻豆蜜桃在线观看| 欧美成人vps| 国产精品 欧美激情| 蜜臀av性久久久久av蜜臀妖精| 久久久综合亚洲91久久98| 青青青国内视频在线观看软件| 911精品国产一区二区在线| 亚洲理论片在线观看| 亚洲一区二区毛片| 国产区一区二区三区| 国产丝袜视频在线播放| 欧美日韩精品三区| 老熟妇精品一区二区三区| 午夜精品婷婷| 亚洲xxxxx| 日本蜜桃在线观看| 欧美性大战久久| 成人无码av片在线观看| 久久国产精品亚洲77777| 国产伦精品一区二区三区四区免费| 久操免费在线| 91精品在线免费| 色偷偷www8888| 国内成人精品2018免费看| 亚洲精品久久区二区三区蜜桃臀| 欧美成人h版| 亚洲精品成人久久久| 国产精品18p| 成人晚上爱看视频| 嫩草影院中文字幕| 福利片一区二区| 午夜精品一区二区三区在线视频| 亚洲精品久久久久久动漫器材一区| 一区二区三区国产豹纹内裤在线| 老女人性生活视频| 国产综合精品| 精品国产乱码久久久久久丨区2区| √天堂8资源中文在线| 日韩av网站导航| 中文字幕国产在线观看| 国产女人aaa级久久久级| 国产精品久久久毛片| 超碰成人久久| 亚洲在线免费看| 成年人视频免费在线播放| 亚洲国产成人一区| 男人天堂2024| 国产精品久久久久永久免费观看| 国产原创精品在线| 欧美国产91| 国产女人水真多18毛片18精品 | 欧美一级大片在线观看| 欧美女优在线观看| 欧美日韩国产高清一区二区三区 | 欧美孕妇性xxxⅹ精品hd| 日本韩国一区二区三区视频| 日本精品久久久久中文| 精品夜夜嗨av一区二区三区| 亚洲精品蜜桃久久久久久| 香蕉久久夜色精品国产使用方法 | 色婷婷综合网站| 欧美国产先锋| 欧美午夜精品久久久久久蜜| 日韩毛片免费视频一级特黄| 久久久人成影片一区二区三区观看| 人成免费电影一二三区在线观看| 欧美酷刑日本凌虐凌虐| 在线观看亚洲欧美| 亚洲日本护士毛茸茸| 中文字幕丰满孑伦无码专区| 韩国成人在线视频| 国产一区二区在线视频播放| 久久美女视频| 久久精品国产综合精品| 999久久久国产999久久久| 欧美一二三视频| 亚洲小说区图片区都市| 亚洲午夜女主播在线直播| 国模私拍视频在线| 欧美日本在线播放| 伦av综合一区| 午夜精品久久久久久久蜜桃app| 天堂网中文在线观看| 91在线国产福利| 无套内谢丰满少妇中文字幕| 日本在线不卡一区| 亚洲熟妇国产熟妇肥婆| 久久久人成影片免费观看| 日本在线观看一区二区| 国产欧美自拍一区| 成人国产精品久久久久久亚洲| 中文字幕21页在线看| 久久久久久网站| 中文在线手机av| www欧美日韩| av资源种子在线观看| 亚洲免费视频网站| 特级丰满少妇一级aaaa爱毛片| 欧美精品一二三四| 正在播放亚洲精品| 日韩欧美大尺度| 奇米影视第四色777| 怡红院av一区二区三区| 国产精品一区二区亚洲| 欧美极品少妇xxxxⅹ高跟鞋 | 国产又黄又猛的视频| 日韩高清一区二区| 日本三级免费观看| 国产毛片欧美毛片久久久| 蜜桃免费网站一区二区三区| 日本www在线播放| 亚洲精选国产| 国产真人做爰毛片视频直播| 欧美国产精品| 国产视频在线观看网站| 好吊一区二区三区| 成人在线播放网址| 亚洲国产专区校园欧美| 久久男人资源站| 亚洲国产一区二区三区高清| 国产一二三在线视频| 91久久午夜| 久久国产亚洲精品无码| 久久狠狠婷婷| 久久精品视频91| 奇米777欧美一区二区| 无限资源日本好片| 久久9热精品视频| 999在线精品视频| 国产电影一区在线| 日韩少妇一区二区| 91蝌蚪porny| 日韩视频在线观看免费视频| 国产精品网站一区| 欧美日韩一区综合| 天天操夜夜操视频| 久久精品女人天堂| 一级特黄性色生活片| 日本不卡视频在线| 图片区乱熟图片区亚洲| 欧美激情视频一区二区三区在线播放 | 亚洲精品国产美女| 亚洲日本香蕉视频| 国产一区二区黄| 巨大荫蒂视频欧美大片| 日韩成人在线免费观看| а天堂8中文最新版在线官网| 视频直播国产精品| 欧美xxxx视频| 91成人精品网站| 日韩毛片久久久| 久久久欧美精品| 刘亦菲毛片一区二区三区| 成人激情av网| 卡一卡二卡三在线观看| 亚洲精品国久久99热| 国产又大又黄又粗| 亚洲视频每日更新| 国产一级做a爰片在线看免费| 狠狠久久亚洲欧美专区| 国产麻豆91视频| 日韩精品在线播放| 麻豆传媒视频在线观看免费| 成人高清av在线| 成年人午夜免费视频| 日韩av中文在线观看| 亚洲在线观看网站| 2023国产精品自拍| 午夜啪啪小视频| 国产一区欧美日韩| 男人的天堂最新网址| wwww国产精品欧美| 69xx绿帽三人行| 欧美亚洲图片小说| 天堂在线中文网| 久久精品夜夜夜夜夜久久| 天堂在线中文网官网| 亚洲va男人天堂| 亚洲精品456| www.一区二区.com| 免费成人av在线播放| 97免费公开视频| 国产精品久久综合| 欧美国产成人精品一区二区三区| 欧美日韩一区二区三区免费看| 婷婷色在线观看| 欧美日韩xxx| 国产视频一区二| 亚洲欧美久久234| 久久人人精品| 99久久人妻精品免费二区| 亚洲欧美另类久久久精品| 天堂av免费在线观看| 亚洲精品国产精品自产a区红杏吧 亚洲精品国产精品乱码不99按摩 亚洲精品国产精品久久清纯直播 亚洲精品国产精品国自产在线 | 日韩精品极品| 国产成人免费观看| 一本一道久久a久久精品蜜桃| 亚洲性生活网站| 久久嫩草精品久久久久| 日本一级一片免费视频| 日韩精品一区二| 成人在线观看免费网站| 国产精品一区二区三区久久久| 欧美男男gaytwinkfreevideos| 欧美变态另类刺激| 不卡视频一二三| 国产精品9191| 精品国产免费一区二区三区香蕉| h片在线免费| 亚洲一区二区中文字幕| 希岛爱理av一区二区三区| 亚洲综合婷婷久久| 国产精品伦一区| 一级黄色大片免费观看| 中文字幕亚洲综合| 日本精品久久| 亚洲免费av网| 国产精品系列在线播放| 九九热只有精品| 亚洲第一福利网站| free性护士videos欧美| 成人激情直播| 亚洲黄色一区| a级在线观看视频| 色狠狠av一区二区三区| 国产高清视频在线| 国产欧美中文字幕| 911精品美国片911久久久| 无人码人妻一区二区三区免费| 亚洲精品久久久久久国产精华液| 亚洲精品一区二区三区蜜桃| 午夜精品久久久久久久久久久久| 欧美三级自拍| 成人性视频欧美一区二区三区| 国产三级欧美三级| 91国内精品视频| 欧美黄色片免费观看| 日韩在线你懂的| 日本va中文字幕| 亚洲欧美一区二区久久 | 欧美一卡二卡在线| www中文字幕在线观看| 美乳视频一区二区| 美女尤物国产一区| 麻豆国产尤物av尤物在线观看| 亚洲成色777777在线观看影院| 中文字幕高清在线播放| 亚洲精品视频一区二区三区| 国产米奇在线777精品观看| 日本少妇全体裸体洗澡| 一区二区三区视频观看| 精品成人18| 国产一区二区在线视频播放| 中文字幕欧美日本乱码一线二线| 国产欧美久久久精品免费| 久久人人爽人人爽人人片av高请| 国产亚洲一卡2卡3卡4卡新区 | 国内精品久久久久久99蜜桃| 性欧美1819| 午夜精品久久久久久久99樱桃| 9191在线| 国产原创精品| 看电视剧不卡顿的网站| 日本网站免费观看| 日日骚av一区| 日韩av黄色在线| 杨幂一区二区国产精品| 色菇凉天天综合网| 色婷婷av在线| 亚洲免费精品视频| 成人av综合一区| 国产免费不卡av| 国产精品第3页| 亚洲国产一区二区精品专区| 久久一级免费视频|