mirror of
https://github.com/fluencelabs/redis
synced 2025-06-15 10:11:21 +00:00
Process async client checks like client timeouts and BLPOP timeouts incrementally using a circular list.
This commit is contained in:
49
src/redis.c
49
src/redis.c
@ -641,6 +641,50 @@ long long getOperationsPerSecond(void) {
|
||||
return sum / REDIS_OPS_SEC_SAMPLES;
|
||||
}
|
||||
|
||||
void closeTimedoutClient(redisClient *c) {
|
||||
time_t now = time(NULL);
|
||||
|
||||
if (server.maxidletime &&
|
||||
!(c->flags & REDIS_SLAVE) && /* no timeout for slaves */
|
||||
!(c->flags & REDIS_MASTER) && /* no timeout for masters */
|
||||
!(c->flags & REDIS_BLOCKED) && /* no timeout for BLPOP */
|
||||
dictSize(c->pubsub_channels) == 0 && /* no timeout for pubsub */
|
||||
listLength(c->pubsub_patterns) == 0 &&
|
||||
(now - c->lastinteraction > server.maxidletime))
|
||||
{
|
||||
redisLog(REDIS_VERBOSE,"Closing idle client");
|
||||
freeClient(c);
|
||||
} else if (c->flags & REDIS_BLOCKED) {
|
||||
if (c->bpop.timeout != 0 && c->bpop.timeout < now) {
|
||||
addReply(c,shared.nullmultibulk);
|
||||
unblockClientWaitingData(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clientsCron(void) {
|
||||
/* Make sure to process at least 1/100 of clients per call.
|
||||
* Since this function is called 10 times per second we are sure that
|
||||
* in the worst case we process all the clients in 10 seconds.
|
||||
* In normal conditions (a reasonable number of clients) we process
|
||||
* all the clients in a shorter time. */
|
||||
int iterations = listLength(server.clients)/100;
|
||||
if (iterations < 50) iterations = 50;
|
||||
|
||||
while(listLength(server.clients) && iterations--) {
|
||||
redisClient *c;
|
||||
listNode *head;
|
||||
|
||||
/* Rotate the list, take the current head, process.
|
||||
* This way if the client must be removed from the list it's the
|
||||
* first element and we don't incur into O(N) computation. */
|
||||
listRotate(server.clients);
|
||||
head = listFirst(server.clients);
|
||||
c = listNodeValue(head);
|
||||
closeTimedoutClient(c);
|
||||
}
|
||||
}
|
||||
|
||||
int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
|
||||
int j, loops = server.cronloops;
|
||||
REDIS_NOTUSED(eventLoop);
|
||||
@ -712,9 +756,8 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
|
||||
zmalloc_used_memory());
|
||||
}
|
||||
|
||||
/* Close connections of timedout clients */
|
||||
if ((server.maxidletime && !(loops % 100)) || server.bpop_blocked_clients)
|
||||
closeTimedoutClients();
|
||||
/* We need to do a few operations on clients asynchronously. */
|
||||
clientsCron();
|
||||
|
||||
/* Start a scheduled AOF rewrite if this was requested by the user while
|
||||
* a BGSAVE was in progress. */
|
||||
|
Reference in New Issue
Block a user