radix icon indicating copy to clipboard operation
radix copied to clipboard

Does pool's connection number can be adjusted dynamically based on different RPS?

Open ningyougang opened this issue 1 year ago • 1 comments

How does radix's pool work

I checked the source codes, it works as below

  • The pool will create all connections initial with pool.size number: https://github.com/mediocregopher/radix/blob/v3/pool.go#L359
  • When use redis connection to get data, if some crtical network happens, the connection will be removed from the pool
    • This is test case for it: https://github.com/mediocregopher/radix/blob/v3/pool_test.go#L210
  • refill operation will be executed periodically to add connection:
    • When do refill operation, allow some overflow
      • https://github.com/mediocregopher/radix/blob/v3/pool.go#L485
      • https://github.com/mediocregopher/radix/blob/v3/pool.go#L343
  • doOverflowDrain operation will be executed periodically to delete the redundant connection:
    • If current connection number is greater than pool.size, the redundant connection will be deleted: https://github.com/mediocregopher/radix/blob/v3/pool.go#L520

(If i miss something, please tell me)

Does the pool work as below?

We expect the pool feature like below

  • There should have minConnectionNumber and maxConnectionNumber configuration.
  • Normally, the init connection number should be minConnectionNumber
  • The connection number should be adjusted automatically according to how much the RPS against redis server
    • Under higher RPS, the connections should be created, but can't exceed maxConnectionNumber
    • Under lower RPS, the connections should be removed, but cannot be lower than the minConnectionNumber

Is it possible to make radix pool to support adjust the connection number dynamically based on RPS in future? (If already support, can share how to implement?)

ningyougang avatar Sep 27 '24 09:09 ningyougang

Hi @ningyougang , I think you understand the Pool implementation pretty well, just a minor clarification:

When do refill operation, allow some overflow

The refill operation will not create a new connection if totalConns is greater-than/equal-to size (not totalSize). This means the refill operation never adds a connection into the overflow, but it will not remove it either. Removing from the overflow is only done by doOverflowDrain.

Based on your two links here I think you may have confused totalConns and totalSize. totalSize is the "idle" size of the pool plus the overflow, it does not change for the lifetime of the pool. totalConns is the number of connections currently existing, and it does change during the lifetime of the pool.


As for your question:

Does the pool work as below?

There should have minConnectionNumber and maxConnectionNumber configuration.

Let's be precise and call minConnectionNumber the idleConnectionNumber, since the minimum connection number is always zero (for example, if there is a network failure and all connections are killed). The idleConnectionNumber is the number of connections that Pool will attempt to maintain when there are no commands being executed, and is equal to the size parameter passed into NewPool.

Under higher RPS, the connections should be created, but can't exceed maxConnectionNumber

In the current implementation this requirement is not possible. You can have either:

  • maxConnectionNumber == idleConnectionNumber, by using PoolOnEmptyWait or PoolOnEmptyErrAfter.
  • maxConnectionNumber == infinity, by using PoolOnEmptyCreateAfter and PoolOnFullBuffer.

This limitation is mentioned in the documentation of PoolOnFullBuffer. Removing this limitation would require some kind of mechanism added before this line which only allows totalSize - totalConns new connections to be created concurrently. Adding a mechanism like this would be tricky and prone to impacting performing in the rest of the Pool, but I'm open to suggestions on how to implement it.


Some final notes on this subject:

In general relying on creating connections on the fly to handle commands has proven to be a poor strategy, as redis does not deal with connection churn very efficiently (or at least, it didn't in the past). The overflow buffer was introduced partially to combat this, but implicit pipelining is a much better solution, as it allows multiple concurrent commands to share a single connection in most cases.

radix/v4 expanded this mechanism to support all situations where it's theoretically possible, and so the radix/v4 Pool is drastically simpler than the v3, not supporting any dynamic sizing at all.

I hope this is helpful, please let me know if you have any further questions.

mediocregopher avatar Sep 29 '24 10:09 mediocregopher

@mediocregopher thank you for your detail explanation

ningyougang avatar Oct 08 '24 01:10 ningyougang

Closed

ningyougang avatar Oct 09 '24 00:10 ningyougang