public class ThrottlingSession extends AbstractSession
Cassandra session that limits the number of statements that are executed
concurrently. This class wraps a regular Session
forwarding most of
the methods directly to the backing session. Methods that start the execution
of statements, however, are wrapped with a logic that limits the number of
statements that are executed in parallel. When the limit is reached, the
execution of further statements is paused until statements started earlier
have completed. This happens transparently to the calling code: When using
one of the asynchronous methods of this class, the calling code will still
receive a ResultSetFuture
immediately, even when the execution has
not started yet.
The limit for the number of read statements and write statements that can run in parallel is configured separately. Usually, read statements put more load on the database cluster than write statements because executing them typically involves scanning through several SSTables while write statements only require a sequential append to the commit-log. This means that usually, one will set a higher limit for write than for read statements. However, when using write statements that are batched statements or even conditional statements (also known as light-weight transactions), these statements involve a significant overhead. A logged batch requires a considerable amount of coordination and a light-weight transaction (LWT) implies read operations that are needed to check whether the specified condition is met and also need significant coordination across the replicas. For these reasons, when using such statements one will typically set a lower limit for write statements than for read statements.
Limitations
Unfortunately, there is no good way to easily tell whether an
INSERT
, UPDATE
, or DELETE
is a
conditional statement. Finding this out would involve a significant effort
for parsing the statement, leading to a huge overhead for each execution. For
this reason, this class treats conditional and unconditional writes the same
way, even though LWTs cause much more load on the database cluster. For the
same reason, batched statements are simply treated as one simple write
statement, even though such a batch might actually contain many statements.
Another limitation of this class is that will consider a statement to have
completed execution when the future returned by the backing session's
executeAsync
method has completed. However, the
ResultSet
returned by the future might actually trigger additional
database operations when the number of rows is large and paging is enabled.
In this case, the statement will not contribute towards the count of running
read statements, even though it ist still causing load on the database
cluster.
Finally, this session does not implement the AbstractSession.checkNotInEventLoop()
method. In order to do so, it would need to call the corresponding method of
the backing session, which it cannot due to access restrictions (the method
is protected
).
ThrottlingCassandraProvider
Session.State
Constructor and Description |
---|
ThrottlingSession(int maxConcurrentReadStatements,
int maxConcurrentWriteStatements,
Session session)
Creates a throttling session that is backed by the specified session.
|
Modifier and Type | Method and Description |
---|---|
CloseFuture |
closeAsync() |
ResultSetFuture |
executeAsync(Statement statement) |
Cluster |
getCluster() |
String |
getLoggedKeyspace() |
int |
getPendingReadStatementsCount()
Returns the current number of read statements that are waiting for
execution.
|
int |
getPendingWriteStatementsCount()
Returns the current number of write statements that are waiting for
execution.
|
Session |
getRawSession()
Returns the session that backs this session.
|
int |
getRunningReadStatementsCount()
Returns the current number of read statements that are running.
|
int |
getRunningWriteStatementsCount()
Returns the current number of write statements that are running.
|
Session.State |
getState() |
Session |
init() |
ListenableFuture<Session> |
initAsync() |
boolean |
isClosed() |
ListenableFuture<PreparedStatement> |
prepareAsync(RegularStatement statement) |
ListenableFuture<PreparedStatement> |
prepareAsync(String query) |
protected ListenableFuture<PreparedStatement> |
prepareAsync(String query,
Map<String,ByteBuffer> customPayload) |
checkNotInEventLoop, close, execute, execute, execute, execute, executeAsync, executeAsync, executeAsync, prepare, prepare
public ThrottlingSession(int maxConcurrentReadStatements, int maxConcurrentWriteStatements, Session session)
maxConcurrentReadStatements
- maximum number of read statements that may run concurrently.
Must be greater than zero.maxConcurrentWriteStatements
- maximum number of write statements that may run concurrently.
Must be greater than zero.session
- session that is used for actually executing the statements.
That session is also used directly when other methods, that do
not involve the execution of statements, are called.IllegalArgumentException
- if maxConcurrentReadStatements
or
maxConcurrentWriteStatements
is less than one.public CloseFuture closeAsync()
public ResultSetFuture executeAsync(Statement statement)
public Cluster getCluster()
public String getLoggedKeyspace()
public int getPendingReadStatementsCount()
public int getPendingWriteStatementsCount()
public Session getRawSession()
public int getRunningReadStatementsCount()
executeAsync
method has been called but the future returned by that method has not
completed yet.public int getRunningWriteStatementsCount()
executeAsync
method has been called but the future returned by that method has not
completed yet.public Session.State getState()
public Session init()
public ListenableFuture<Session> initAsync()
public boolean isClosed()
public ListenableFuture<PreparedStatement> prepareAsync(String query)
prepareAsync
in interface Session
prepareAsync
in class AbstractSession
public ListenableFuture<PreparedStatement> prepareAsync(RegularStatement statement)
prepareAsync
in interface Session
prepareAsync
in class AbstractSession
protected ListenableFuture<PreparedStatement> prepareAsync(String query, Map<String,ByteBuffer> customPayload)
prepareAsync
in class AbstractSession
Copyright © 2011–2017 aquenos GmbH. All rights reserved.