亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > Redis > 正文

redis超時問題分析

2020-03-17 12:41:08
字體:
來源:轉載
供稿:網友

Redis在分布式應用中占據著越來越重要的地位,短短的幾萬行代碼,實現了一個高性能的數據存儲服務。最近dump中心的cm8集群出現過幾次redis超時的情況,但是查看redis機器的相關內存都沒有發現內存不夠,或者內存發生交換的情況,查看redis源碼之后,發現在某些情況下redis會出現超時的狀況,相關細節如下。

1. 網絡。Redis的處理與網絡息息相關,如果網絡出現閃斷則容易發生redis超時的狀況。如果出現這種狀況首先應查看redis機器網絡帶寬信息,判斷是否有閃斷情況發生。
2. 內存。redis所有的數據都放在內存里,當物理內存不夠時,linux os會使用swap內存,導致內存交換發生,這時如果有redis調用命令就會產生redis超時。這里可以通過調整/proc/sys/vm/swappiness參數,來設置物理內存使用超過多少就會進行swap。
int rdbSaveBackground(char *filename) {    pid_t childpid;    long long start;    if (server.rdb_child_pid != -1) return REDIS_ERR;    server.dirty_before_bgsave = server.dirty;    server.lastbgsave_try = time(NULL);    start = ustime();    if ((childpid = fork()) == 0) {        int retval;        /* Child */        if (server.ipfd > 0) close(server.ipfd);        if (server.sofd > 0) close(server.sofd);        retval = rdbSave(filename);        if (retval == REDIS_OK) {            size_t private_dirty = zmalloc_get_private_dirty();            if (private_dirty) {                redisLog(REDIS_NOTICE,                    "RDB: %zu MB of memory used by copy-on-write",                    private_dirty/(1024*1024));            }        }        exitFromChild((retval == REDIS_OK) ? 0 : 1);    } else {        /* Parent */        server.stat_fork_time = ustime()-start;        if (childpid == -1) {            server.lastbgsave_status = REDIS_ERR;            redisLog(REDIS_WARNING,"Can't save in background: fork: %s",                strerror(errno));            return REDIS_ERR;        }        redisLog(REDIS_NOTICE,"Background saving started by pid %d",childpid);        server.rdb_save_time_start = time(NULL);        server.rdb_child_pid = childpid;        updateDictResizePolicy();        return REDIS_OK;    }    return REDIS_OK; /* unreached */}

程序1
另外還有一些特殊情況也會導致swap發生。當我們使用rdb做為redis集群持久化時可能會發生物理內存不夠的情況(aof持久化只是保持支持不斷的追加redis集群變化操作,不太容易引起swap)。當使用rdb持久化時,如程序1所示主進程會fork一個子進程去dump redis中所有的數據,主進程依然為客戶端服務。此時主進程和子進程共享同一塊內存區域, linux內核采用寫時復制來保證數據的安全性。在這種模式下如果客戶端發來寫請求,內核將該頁賦值到一個新的頁面上并標記為寫,在將寫請求寫入該頁面。因此,在rdb持久化時,如果有其他請求,那么redis會使用更多的內存,更容易發生swap,因此在可以快速恢復的場景下盡量少使用rdb持久化可以將rdb dump的條件設的苛刻一點,當然也可以選擇aof,但是aof也有他自身的缺點。另外也可以使用2.6以后的主從結構,將讀寫分離,這樣不會出現server進程上又讀又寫的情景發生 3. Redis單進程處理命令。Redis支持udp和tcp兩種連接,redis客戶端向redis服務器發送包含redis命令的信息,redis服務器收到信息后解析命令后執行相應的操作,redis處理命令是串行的具體流程如下。首先服務端建立連接如程序2所示,在創建socket,bind,listen后返回文件描述符:

server.ipfd = anetTcpServer(server.neterr,server.port,server.bindaddr);

程序2
對于redis這種服務來說,它需要處理成千上萬個連接(最高達到655350),需要使用多路復用來處理多個連接。這里redis提供了epoll,select, kqueue來實現,這里在默認使用epoll(ae.c)。拿到listen函數返回的文件描述符fd后,redis將fd和其處理acceptTcpHandler函數加入到事件驅動的鏈表中.實際上在加入事件隊列中,程序4事件驅動程序將套接字相關的fd文件描述符加入到epoll的監聽事件中。

    if (server.ipfd > 0 && aeCreateFileEvent(server.el,server.ipfd,AE_READABLE,        acceptTcpHandler,NULL) == AE_ERR) redisPanic("Unrecoverable error creating server.ipfd file event.");int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,        aeFileProc *proc, void *clientData){    if (fd >= eventLoop->setsize) {        errno = ERANGE;        return AE_ERR;    }    aeFileEvent *fe = &eventLoop->events[fd];    if (aeApiAddEvent(eventLoop, fd, mask) == -1)        return AE_ERR;    fe->mask |= mask;    if (mask & AE_READABLE) fe->rfileProc = proc;    if (mask & AE_WRITABLE) fe->wfileProc = proc;    fe->clientData = clientData;    if (fd > eventLoop->maxfd)        eventLoop->maxfd = fd;    return AE_OK;}

程序3

static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {    aeApiState *state = eventLoop->apidata;    struct epoll_event ee;    /* If the fd was already monitored for some event, we need a MOD     * operation. Otherwise we need an ADD operation. */    int op = eventLoop->events[fd].mask == AE_NONE ?            EPOLL_CTL_ADD : EPOLL_CTL_MOD;    ee.events = 0;    mask |= eventLoop->events[fd].mask; /* Merge old events */    if (mask & AE_READABLE) ee.events |= EPOLLIN;    if (mask & AE_WRITABLE) ee.events |= EPOLLOUT;    ee.data.u64 = 0; /* avoid valgrind warning */    ee.data.fd = fd;    if (epoll_ctl(state->epfd,op,fd,&ee) == -1) return -1;    return 0;}

程序4
在初始話完所有事件驅動后,如程序5所示主進程根據numevents = aeApiPoll(eventLoop, tvp)獲得io就緒的文件描述符和其對應的處理程序,并對fd進行處理。大致流程是accept()->createclient()->readQueryFromClient()。其中readQueryFromClient()讀取信息中的redis命令-> processInputBuffer()->call()最后完成命令。

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){------------------------------- 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;            /* note the fe->mask & mask & ... code: maybe an already processed             * event removed an element that fired and we still didn't             * processed, so we check if the event is still valid. */            if (fe->mask & mask & AE_READABLE) {                rfired = 1;                fe->rfileProc(eventLoop,fd,fe->clientData,mask);            }            if (fe->mask & mask & AE_WRITABLE) {                if (!rfired || fe->wfileProc != fe->rfileProc)                    fe->wfileProc(eventLoop,fd,fe->clientData,mask);            }            processed++;        }}

程序5
從上述代碼可以看出redis利用ae事件驅動結合epoll多路復用實現了串行式的命令處理。所以一些慢命令例如sort,hgetall,union,mget都會使得單命令處理時間較長,容易引起后續命令time out.所以我們第一需要從業務上盡量避免使用慢命令,如將hash格式改為kv自行解析,第二增加redis實例個數,每個redis服務器調用盡量少的慢命令。


注:相關教程知識閱讀請移步到Redis頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品无人区太爽高潮在线播放| 亚洲天堂成人在线| 中文字幕免费精品一区高清| 亚洲日本aⅴ片在线观看香蕉| 亚洲黄在线观看| 97免费视频在线| 欧美日韩一区二区在线播放| 色诱女教师一区二区三区| 中文字幕av日韩| 韩日欧美一区二区| 国产精品久久久久99| 麻豆国产精品va在线观看不卡| 国产欧美一区二区三区久久| 欧美另类暴力丝袜| 在线日韩中文字幕| 国产欧美一区二区三区久久人妖| 亚洲第一区中文字幕| 午夜欧美大片免费观看| 亚洲色图狂野欧美| 91久久精品日日躁夜夜躁国产| 日韩成人av在线| 中文字幕亚洲综合| 中文字幕日本精品| 高清在线视频日韩欧美| 国产精品免费一区| 亚洲香蕉伊综合在人在线视看| 久久久久久亚洲精品中文字幕| 久久精品国产99国产精品澳门| 日本高清视频一区| 亚洲一区亚洲二区亚洲三区| 亚洲精品短视频| 91九色国产社区在线观看| 亚洲人成在线观看网站高清| 欧美天堂在线观看| 午夜精品理论片| 日韩欧美中文字幕在线播放| 国产一区二区黄| 日韩经典中文字幕| 欧美怡春院一区二区三区| 日本不卡视频在线播放| 精品无人区乱码1区2区3区在线| 久久久黄色av| 色老头一区二区三区在线观看| 国产精品午夜一区二区欲梦| 久久这里有精品| 超碰91人人草人人干| 国产日韩在线看| 午夜精品一区二区三区在线| 亚洲综合国产精品| 日韩精品丝袜在线| 影音先锋欧美精品| 亚洲偷欧美偷国内偷| 国内精久久久久久久久久人| 91在线看www| 亚洲人精品午夜在线观看| yellow中文字幕久久| 欧美日韩精品在线观看| 亚洲一区二区三区成人在线视频精品| 亚洲欧洲在线视频| 2019最新中文字幕| 亚洲sss综合天堂久久| 中文字幕亚洲欧美| 国产精品99久久久久久久久| 亚洲欧美一区二区三区四区| 亚洲综合色激情五月| 正在播放国产一区| 国内精品伊人久久| 欧美国产视频一区二区| 国产噜噜噜噜久久久久久久久| 亚洲人成在线播放| 欧美日本精品在线| 日韩毛片在线看| 激情亚洲一区二区三区四区| 一区二区亚洲精品国产| 久久久国产一区二区三区| 91亚洲精品久久久久久久久久久久| 国产精品久久999| 北条麻妃一区二区在线观看| 久久久噜噜噜久噜久久| 在线播放日韩欧美| 国产精国产精品| 亚洲欧美日韩一区在线| 亚洲欧美三级在线| 日本成人免费在线| 欧美综合国产精品久久丁香| 性色av一区二区三区红粉影视| 91精品美女在线| 欧美尤物巨大精品爽| 成人精品一区二区三区电影免费| 国产精品亚洲欧美导航| 亚洲精品午夜精品| 成人乱人伦精品视频在线观看| 91精品国产综合久久香蕉的用户体验| 亚洲国产精品成人va在线观看| 中文字幕亚洲欧美日韩在线不卡| 日韩av一区二区在线| 日韩免费看的电影电视剧大全| 成人免费视频网| 疯狂做受xxxx高潮欧美日本| 日韩免费观看在线观看| 亚洲美女在线视频| 国产精品美女久久久久av超清| 美日韩在线视频| 亚洲大胆人体在线| 九九热r在线视频精品| www.欧美三级电影.com| 成人欧美一区二区三区黑人孕妇| 91最新国产视频| 57pao成人国产永久免费| 国产欧美va欧美va香蕉在| 欧美激情在线狂野欧美精品| 欧美激情一区二区三区高清视频| 亚洲电影av在线| 久久久久国产精品www| 国产精品久久久999| 国产亚洲a∨片在线观看| 欧美日韩一区免费| 亚洲另类xxxx| 欧美国产日韩一区二区| 国产精品久久久久久久久久| 欧美日韩国产成人高清视频| 日本久久久a级免费| 中文日韩在线视频| 九九热这里只有精品免费看| 欧美亚洲国产日韩2020| 亚洲精品国产欧美| 久久久女人电视剧免费播放下载| 精品露脸国产偷人在视频| 日产精品99久久久久久| 理论片在线不卡免费观看| 清纯唯美日韩制服另类| 久久久成人的性感天堂| 欧美专区中文字幕| 97精品久久久| 亚洲国产成人精品一区二区| 成人免费高清完整版在线观看| 1769国产精品| 久久99热这里只有精品国产| 日韩精品极品在线观看播放免费视频| 亚洲人成在线观看网站高清| 久久成人这里只有精品| 国内精品久久久久久中文字幕| 亚洲综合第一页| 国产精品亚洲激情| 不卡中文字幕av| 久久91精品国产91久久跳| 国产精品久久久久aaaa九色| 最新日韩中文字幕| 日韩中文在线中文网三级| 国产欧美在线视频| 亚洲电影免费观看高清完整版在线观看| 久久久久久国产精品| 成人亲热视频网站| 91禁国产网站| 浅井舞香一区二区| 麻豆一区二区在线观看| 国产91亚洲精品| 最近2019中文字幕第三页视频| 少妇高潮久久久久久潘金莲| 久久av在线看| 91精品国产综合久久香蕉的用户体验| 欧美激情精品久久久久久变态| 97久久久免费福利网址| 亚洲第五色综合网|