博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Redis windows 2.6版本并发出错解决方法
阅读量:7089 次
发布时间:2019-06-28

本文共 2361 字,大约阅读时间需要 7 分钟。

在使用MS opentech开发的redis 2.6 windows版本时,会出现在连接数过多(在我的机器上是超过800)时,会出现如下错误

"Error registering fd event for the new client: Result too large (fd=xxxxx)"

在网上却收不到任何结果.在看过代码之后,发现windows版本的redis的实现是有问题的.

原版的redis是使用accept来获取一个新的连接的fd,然后使用这个fd作为aeEventLoop->events的index来存储并获取events的值,从而处理事件.而MS OpenTech使用IOCP模型实现了一个aeWinAccept来获取fd.关键代码如下:

int aeWinQueueAccept(SOCKET listensock) {    aeSockState *sockstate;    aeSockState *accsockstate;    DWORD result, bytes;    SOCKET acceptsock;    aacceptreq * areq;    if ((sockstate = aeGetSockState(iocpState, (int)listensock)) == NULL) {        errno = WSAEINVAL;        return -1;    }    //这里使用了socket的返回值来初始化aeEventLoop中的fd值    acceptsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);    if (acceptsock == INVALID_SOCKET) {        errno = WSAEINVAL;        return -1;    }    accsockstate = aeGetSockState(iocpState, (int)acceptsock);    if (accsockstate == NULL) {        errno = WSAEINVAL;        return -1;    }    ...
int aeWinAccept(int fd, struct sockaddr *sa, socklen_t *len) {    aeSockState *sockstate;    int acceptsock;    int result;    SOCKADDR *plocalsa;    SOCKADDR *premotesa;    int locallen, remotelen;    aacceptreq * areq;    SOCKET listenSock = (SOCKET)fd;    if ((sockstate = aeGetSockState(iocpState, fd)) == NULL) {        errno = WSAEINVAL;        return SOCKET_ERROR;    }   //在这里取回之前存在aeEventLoop中的socket句柄作为fd    areq = sockstate->reqs;    if (areq == NULL) {        errno = WSAEINVAL;        return SOCKET_ERROR;    }    sockstate->reqs = areq->next;    acceptsock = (int)areq->accept;    ...
int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,        aeFileProc *proc, void *clientData){    aeFileEvent *fe;    if (fd >= eventLoop->setsize) {        errno = ERANGE;        return AE_ERR;    }    //在这里判断fd是否超过pool的size,并通过fd的值来取得事件    fe = &eventLoop->events[fd];    ...

Windows版本的redis和原版的redis的实现是一样的,重要的是accept的返回值和aeWinAccept所返回的socket句柄逻辑不一样导致windows版本的redis出现了bug.在Linux中,accept的返回是递增的,因此linux版本的redis是可以处理eventLoop->setsize个连接的,而在windows上socket返回的句柄会以大概12的步进增长,所以windows版本的redis就只能处理约eventLoop->setsize/12个连接了.

 

解决方法:

我的解决方法比较hack,我在aeEventLoop中添加一个fd_map的数组,用于把fd映射到0到eventLoop->setsize的值,这样每次从events中存取数据就通过查询fd_map来获取index,从而达到让redis能处理eventLoop->setsize个连接的效果.

 不过由于这个方法比较猥琐,我就没有提交patch了,而是提交了一个issue,不知道下一个版本会不会解决这个问题.

 

 

 

转载于:https://www.cnblogs.com/triStoneL/p/3277709.html

你可能感兴趣的文章
5G全球统一标准有望形成 中国话语权提升
查看>>
天龙光电毛利率异常 数千万元预收不知从何而来
查看>>
双态IT时代,你需要什么样的IT咨询服务?
查看>>
iOS9.3激活失败 疑似激活服务器被挤爆
查看>>
最低调的恶意软件之Dimnie瞄准GitHub开发人员
查看>>
运营商发展大数据的四大误区
查看>>
Facebook新的图搜索?效果不是很理想
查看>>
Google公司致力发展企业云市场
查看>>
日媒称黑客组织瞄上中企:目标企业被迫停牌3年
查看>>
Fortinet实验室提醒用户注意Office高危漏洞
查看>>
10年后全球智慧城市市场规模将达到3.5万亿美元
查看>>
雅虎高管解读财报 将在今年完成阿里资产剥离
查看>>
大数据时代安全难题:个人信息保护立法紧迫
查看>>
国家发改委:资金支持大数据重大建设项目
查看>>
青海省公安厅部署科达至臻高清视频会议系统
查看>>
最新的swoole视频上线
查看>>
说一下你的思考过程 Tell me what you think(编程测试)
查看>>
勒索病毒后的反思:开放的NFV/SDN安全吗?
查看>>
Appium滑动问题研究
查看>>
美国国家情报总监个人邮箱被黑
查看>>