我在多线程环境中使用Redis,并对其运行方式有疑问。我在我的c ++应用程序中使用hiredis c库。
我的问题是:如果我在触发回调时使用异步模式,那么回调是否会在Redis客户端创建的另一个线程中处理?因为创建调用的线程不会受到回调处理的影响吗?谢谢!
答案 0 :(得分:1)
Redis客户端不会创建任何其他的线程,并且可以在现有线程中工作。
Redis在另一个(主要)流程中工作。您使用的redis API在本地进程中工作,并使用进程间通信到主进程。异步请求意味着您的进程或线程将任务放到另一个,之后可能会执行任何其他任务或等待事件。一段时间后,异步回复到达您的应用程序并可供使用。您的应用程序必须使用https://en.wikipedia.org/wiki/Event_loop或任何异步管理系统,通过调用回调来通知您处理事件(在本例中为redis answer)。
Asyncronous体系结构意味着您运行事件循环,为每个事件调用回调处理程序。当回调调用时,您可以创建多个异步任务。一旦创建任务,它应该比完成任务或发生错误时调用回调事件处理程序。可以分配回叫以启动应用程序或显示新的Web连接。当回调调用时,您可以创建redis任务,稍后将调用结果事件回调。当前线程中的所有内容。我有多个线程,合理的是期望每个线程都有一个事件循环。
Redis的单线程特性:http://redis.io/topics/latency#single-threaded-nature-of-redis
由于Redis使用多路复用和非阻塞I / O,因此客户端套接字处于非阻塞状态。 http://redis.io/topics/clients这意味着您的客户永远不会被阻止。
Redis中的Redis 2.4线程仅用于在后台执行一些慢速I / O操作,主要与磁盘I / O有关,但这并没有改变Redis使用单个线程提供所有请求的事实
答案 1 :(得分:0)
当您调用redisAsyncHandlerRead()时,Hiredis会调用回调。因此,在您用来调用redisAsyncHandlerRead()的任何线程上调用回调。
我相信Linux-ish C中的最小Redis异步示例看起来像这样(为清晰起见,错误检查已删除):
#include "async.h"
#include <unistd.h>
#include <stdio.h>
void myRedisCallback(redisAsyncContext *c, void *typeless_reply, void *priv_data) {
redisReply *r = (redisReply *)typeless_reply;
if (r->type == REDIS_REPLY_STRING)
printf("foo is %s\n", r->str);
}
int main() {
redisAsyncContext *c = redisAsyncConnect("localhost", 6379);
redisAsyncCommand(c, myRedisCallback, NULL, "GET foo");
for (int i = 0; i < 100; i++) {
redisAsyncHandleWrite(c); // This sends the command.
redisAsyncHandleRead(c); // This calls the callback if the reply has been received.
usleep(10000); // A real app would do something here.
}
return 0;
}
答案 2 :(得分:0)
redisAsyncHandleRead() 或 redisAsyncHandleWrite() 将调用您之前注册的任何回调。每次看到它都不会“火”。文档和 async.h 文件都没有明确说明如何获取文件描述符 (ac->c.fd) 以实现 epoll 事件循环:
#define MAX_EVENTS 10
int epfd;
if((epfd = epoll_create1(0)) == -1) {
// handle error
};
redisAsyncContext *ac = redisAsyncConnect("127.0.0.1", 6379);
if(epoll_ctl(epfd, EPOLL_CTL_ADD, ac->c.fd, &(struct epoll_event) { .events = EPOLLIN | EPOLLOUT | EPOLLET }) == -1) {
// handle error
}
int nfds;
struct epoll_event events[MAX_EVENTS];
for(;;) {
if((nfds = epoll_wait(epfd, events, MAX_EVENTS, -1) == -1) {
// handle error
}
for(int i = 0; i < nfds; i++) {
if(events[i].events & EPOLLIN) redisAsyncHandleRead(ac);
if(events[i].events & EPOLLOUT) redisAsyncHandleWrite(ac);
}
}