summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzhaozhao.zz <zhaozhao.zz@alibaba-inc.com>2023-04-24 14:01:40 +0800
committerGitHub <noreply@github.com>2023-04-24 14:01:40 +0800
commitbedecec786767b84215f4002a02d18110585915a (patch)
treecc08dba33d666d2fa32eb4247f91f57c9b247ee4
parent78202f843f44e057722bec6f86b5863a9e4d4418 (diff)
downloadredis-bedecec786767b84215f4002a02d18110585915a.tar.gz
iterate clients fairly in clientsCron() (#12025)
Every time when accept a connection, we add the client to `server.clients` list's tail, but in `clientsCron` we rotate the tail to head at first, and then process the head. It means that the "new" client would be processed before "old" client, moreover if connections established and then freed frequently, the "old" client may have no chance to be processed. To fix it, we need take a fair way to iterate the list, that is take the current head and process, and then rotate the head to tail, thus we can make sure all clients could be processed step by step. p.s. client has `client_list_node` pointer, we don't need put the current client to head to avoid O(N) when remove it.
-rw-r--r--src/server.c7
1 files changed, 3 insertions, 4 deletions
diff --git a/src/server.c b/src/server.c
index 401f63293..fff6c7082 100644
--- a/src/server.c
+++ b/src/server.c
@@ -1015,12 +1015,11 @@ void clientsCron(void) {
client *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. */
- listRotateTailToHead(server.clients);
+ /* Take the current head, process, and then rotate the head to tail.
+ * This way we can fairly iterate all clients step by step. */
head = listFirst(server.clients);
c = listNodeValue(head);
+ listRotateHeadToTail(server.clients);
/* The following functions do different service checks on the client.
* The protocol is that they return non-zero if the client was
* terminated. */