简单描述下,在最近的这个项目中的一个分项目中,有数据存储在Redis中,数据要推荐给用户,前台是通过nginx来接收http请求,解析key,通过一致性hash算法去实现分布式部署redis而非只是主从模式,通过这去访问redis组中的某一组,这样去读取正确的value。
使用环境:
redis.2.4.7
hiredis.0.10
g++4.1.2
问题描述
nginx的work进程如果采用同步方式去访问redis,那么在高并发情况下,有可能当前这个request在访问redis去取value的时候,
没有获取到或者是由于其他错误,网络阻塞等原因,造成了当前处理堵塞在get阶段,那么后面的一大堆request就会造成处理时间过长。现在要解决这个问题,将采用异步方式去访问redis。
解决方式
在实际环境去试了3个不同异步的api,使用libevent和libev异步的api,都会由这两个库的异步方式,都会由这些网络库去异步去生成线程,并在某个事件响应的时候调用在预先执行命令的时候设置的回调函数,如:
redisAsyncContext *ac = ..
redisAsyncCommand(ac,getCallback,inbuffer,"GET %b %b",key,strlen(key),value,strlen(value));
这样的话,线程的控制不是有我们自己控制,并且会在项目中引入更多的第三方库,因此,我们决定使用作者自己写的的ae.c去封装这个异步访问操作。
如果是只下个redis.2.4.7,并使用自带的deps/hiredis。去做封装是编译不过去的。因为在adapters/ae.h里面有些回调接口设置
是错误的,应该是作者很久没有更新这里面的代码了。而在hiredis.0.10版本,一些文件都是最新更新过的,试过是正确的。
在编译自己封装的异步lib是在编译.o的时候会发现一些函数找不到。而这些文件时在redis.2.4.7/src/中的一些文件:
ae.h ae.c ae_epoll.c config.h zmalloc.h zmalloc.c
因此将这些文件copy到你的工程的目录,去生成.o文件加入到生成的libXXX.a中。
其他:
需要注意,如果在redis-sever运行时候的使用的redis.conf中的timeout参数设置为0,则client 起的connect,sever端是
不会由server端去关闭的。如果timeout设置非0,那么需要对起的connect进行控制,去监控是否有效,如果无效那需要对这进行处理。若果是server close connect的时候,那么需要设置去设置disconnect的时候去重建连接。
还有一些其他的东西我认为文档描述的,在这里,我就没有去重复累赘的写出来