question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Reference documentation could be more beginner friendly in some areas

See original GitHub issue

Hello @mp911de.

I’ve read the lettuce’s reference documentation and found a few paragraphs I do not understand correctly. Can you please provide answers to my questions or possibly update the documentation so it is more “lettuce beginner friendly”?

  1. Lettuce is using sort of pipelining even if sync commands are used (because it just passes the command down the pipe to another thread to be send with using netty). This means I can use single connection within multiple threads and do not experience any kind of blocking because, for example, another thread is just waiting for response to GET command. From Pipelining and command flushing:

Using the synchronous API, in general, the program flow is blocked until the response is accomplished. The underlying connection is busy with sending the request and receiving its response. Blocking, in this case, applies only from a current Thread perspective, not from a global perspective.

  1. Nr 1. is possible because of the fact that ClienrtResources uses multiple I/O threads and those threads are responsible for physical connection with the Redis instance. Am I right?

  2. Reference documentation says that ClientResources#ioThreadPoolSize is

The number of threads in the I/O thread pools. … The number does not reflect the actual number of I/O threads because the client requires different thread pools for Network (NIO) and Unix Domain Socket (EPoll) connections.

a) What does ClientResources#ioThreadPoolSize actually represent? b) How many I/O threads (physical connections) Netty use in relation to ClientResources#ioThreadPoolSize property?

  1. Reference documentation also talks about ClientResources#computationThreadPoolSize:

The number of threads in the computation thread pool. … Every thread represents an internal event loop where all computation tasks are run.

a) What computations is the documentation talking about? b) Is it somehow related to ClientResources#ioThreadPoolSize?

  1. How is the lettuce’s shared connection related/bounded to Netty's transport I/O thread?

And a few questions related to connection pooling.

  1. Syncrhonous connections: If I set GenericObjectPoolConfig#setMaxTotal(int) to 20 and set ClientResources#ioThreadPoolSize (from nr. 3) to 5. a) Does it mean that if I try to obtain 6th connection from the pool and send a command using that connection (assuming that all 5 I/O threads from ClientResources are busy and waiting for response), that the command will be queued on the client side waiting for free I/O thread to process it? b) If YES the proper way to use pooling is to set maxTotal > ioThreadPoolSize?

  2. Asyncrhonous connections: The very same questions like in nr. 5) but with using BoundedPoolConfig.builder().maxTotal(int).

  3. Command flushing is not allowed on pooled connections: ref:

The AutoFlushCommands state is set per connection and therefore affects all threads using the shared connection.

I understand that.

If you want to omit this effect, use dedicated connections.

Dedicated connection is actually a pooled connection - I can obtain a connection from a pool, disable autoFlushCommands, process a batch request, enable autoFlushCommands and return the connection.

The AutoFlushCommands state cannot be set on pooled connections by the lettuce connection pooling.

a) So pooled connection is NOT dedicated? b) How should one use batch processing with pooled connections?

Thank you very much for your time. Best Regards,

Martin

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
mp911decommented, May 27, 2020

Feel free to edit the wiki directly.

Lettuce is using sort of pipelining even if sync commands are used (because it just passes the command down the pipe to another thread to be send with using netty). This means I can use single connection within multiple threads and do not experience any kind of blocking because, for example, another thread is just waiting for response to

Lettuce uses pipelining as default mode of operation. Your understanding is correct. Note that there is an extension to pipelining as outlined in the Pipelining/Flushing page. You can basically pipeline more aggressively by collecting a batch of commands that is attempted to send in as little TCP packages and with as little flushes as possible. Compared to “regular” pipelining, manual flushing has a 5x to 10x performance gain.

Nr 1. is possible because of the fact that

No. Netty’s threading model assigns a thread per transport connection. So if you dispatch commands from multiple application threads on a single connection, all I/O (read and write operations) are handled by a single EventLoop thread. You can increase the number of effectively used I/O threads by using multiple connections but that style of use makes rarely sense for the sake of performance.

a) What does ClientResources#ioThreadPoolSize actually represent? b) How many I/O threads (physical connections) Netty use in relation to ClientResources#ioThreadPoolSize property?

To a: The number in each transport-specific EventLoopGroup. Netty 4 has currently a limitation that requires a specific EventLoopGroup per channel type. So you cannot use an NIO EventLoopGroup with kqueue or epoll transport or vice versa. Netty 5 is going to address that shortcoming.

To b: Not sure I follow. A thread does not represent a connection. A connection gets a I/O thread assigned. Any higher number of connections than ioThreadPoolSize reuses threads. That is, if you have 4 threads and 4 connections, each connection uses exclusively a thread (there’s a configurable EventExecutorChooser but probably too detailed for now). If you open a 5th connection, then one of the 4 threads gets assigned to the 5th connection.

Probably also worth mentioning: Typically, you use a single mechanism to establish connections (nio, kqueue, epoll) so you should only see as many as ClientResources#ioThreadPoolSize I/O threads. Having nio and e.g. epoll active should not happen.

a) What computations is the documentation talking about? b) Is it somehow related to ClientResources#ioThreadPoolSize?

Computations are background tasks (cluster topology refresh, offloading of reactive pipeline signals, timers, …). That pool is configured though ClientResources#computationThreadPoolSize.

How is the lettuce’s shared connection related/bounded to Netty’s transport I/O thread?

That question is answered above.

Syncrhonous connections: If I set GenericObjectPoolConfig#setMaxTotal(int) to 20 and set ClientResources#ioThreadPoolSize (from nr. 3) to 5. a) Does it mean that if I try to obtain 6th connection from the pool and send a command using that connection (assuming that all 5 I/O threads from ClientResources are busy and waiting for response), that the command will be queued on the client side waiting for free I/O thread to process it? b) If YES the proper way to use pooling is to set maxTotal > ioThreadPoolSize?

Asyncrhonous connections: The very same questions like in nr. 5) but with using BoundedPoolConfig.builder().maxTotal(int).

There are no synchronous/asynchronous connections (we had this concept earlier in Lettuce 2 and 3, we removed it entirely in favor of a StatefulConnection exposing synchronous, asynchronous and reactive API facades).

The relation between connection count and how netty threads are associated with connections is explained above.

The AutoFlushCommands state cannot be set on pooled connections by the lettuce connection pooling.

a) So pooled connection is NOT dedicated? b) How should one use batch processing with pooled connections?

Probably we need to improve our documentation here. We had once the restriction that pooled connections are not allowed to change their state (database selection, flushing behavior). Looking at the code, this section is no longer valid and needs to be removed/reworked.

Let me know if this helps or whether there are things that need to be addressed.

0reactions
mp911decommented, Jul 1, 2020
Read more comments on GitHub >

github_iconTop Results From Across the Web

Beginner friendly documentation - Feature Requests - Home ...
I've mentioned it elsewhere, but the project has reached the point where the docs are primarily a reference manual rather than a user...
Read more >
We Should Care More About Higher Level Documentation - Joshua ...
Why we should all care more about higher-level documentation, a way to view documentation as a funnel, and an explanation of how things...
Read more >
How to Build the Best User Documentation (New Guide) | Blog
1. Gives them an easy reference guide. Great user documentation doesn't just have to be for customers. Your product support team can use...
Read more >
A Beginner's Guide to Using Developer Documentation Like a ...
Developer documentation is meant to describe every aspect of how developers should interface with a given software service or library. When we ...
Read more >
A beginner's guide to writing documentation - Write the Docs
It's really easy to have an idea in your head that sounds perfect, but the act of putting words to paper requires a...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found