New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal for async out-of-band callback support #157
Comments
Looks like a good idea, particularly for GET from slow disks or cloud storage backends. It can avoid the FIFO head of line blocking. Checkpoints do not block operations in Garnet so that's not a reason for us. We don't yet have BRPOP, but it will help when we do. I prefer the RESP3 version. Making a second connection per connection is prohibitively inefficient for most scenarios I've seen that might use this. Is there no way to reuse the same connection in RESP2? If not then Garnet could offer the RESP3 semantics just for this. |
Piping up to say, this would solve some issues my team is having as well. When embedding Garnet it is desirable to conditionally go async, rather than always either blocking or forcing operations onto the threadpool. Today we just block, since most operations complete synchronously and the extra trip through the threadpool is murder on performance.
RESP3 introduces the Push type, the equivalent under RESP2 is to use a separate connection. This inefficiency in RESP2 is why the Push type was added 😊. |
Technically (and I'll explain why I don't advocate this) we could break specification and issue a RESP3 push response out-of-band on the single connection in RESP2; a suitably educated client would know to expect and handle However: here's the thing - implementing RESP3 doesn't need to be hard! You do not necessarily need to change every available response to issue RESP3 counterparts; RESP3-aware clients need to handle both RESP2 and RESP3 (because they still want to talk to RESP2 servers), so: even if the only thing you did was implement the Note that if SE.Redis is in RESP3 mode, it will want to use regular pub/sub on the RESP3 connection, so: any other pub/sub support would need to work on RESP3. |
I have one suggestion for the Example API:
|
Makes sense, but I would suggest "ASYNC BARRIER" - keeping everything as
subcommands minimizes the top-level command explosion.
…On Fri, 29 Mar 2024, 23:00 Badrish Chandramouli, ***@***.***> wrote:
I have one suggestion for the async API proposed above. It should have
the notion of a *barrier*, that will *complete* (or *await*) all the
earlier-issued asynchronous operations. This is useful for clients to
maintain session consistency. For example, they may do a series of reads
followed by a write, but might want the pending reads to complete first
before issuing the write on that session. This is already available, called
CompletePending(...) in FASTER and Tsavorite (Garnet's fork of FASTER).
Example API:
C: GET foo1
S: -ASYNC 3434534
C: GET foo2
S: "asldkfslkfdgh"
C: GET foo3
S: -ASYNC 3434535
C: BARRIER
S: ["async" "3434535" "askdjhasdkjsah_foo3"]
S: ["async" "3434534" "askdjhasdkjsah_foo1"]
S: OK # when we get this OK response to BARRIER, we know all async ops are over
—
Reply to this email directly, view it on GitHub
<#157 (comment)>
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAEHMGFFDHSCNMTTBT67ATY2XW75BFKMF2HI4TJMJ2XIZLTSSBKK5TBNR2WLJDUOJ2WLJDOMFWWLO3UNBZGKYLEL5YGC4TUNFRWS4DBNZ2F6YLDORUXM2LUPGBKK5TBNR2WLJDUOJ2WLJDOMFWWLLTXMF2GG2C7MFRXI2LWNF2HTAVFOZQWY5LFUVUXG43VMWSG4YLNMWVXI2DSMVQWIX3UPFYGLAVFOZQWY5LFVI2TQNZQG43TQNZUGGSG4YLNMWUWQYLTL5WGCYTFNSWHG5LCNJSWG5C7OR4XAZNMJFZXG5LFINXW23LFNZ2KM5DPOBUWG44TQKSHI6LQMWVHEZLQN5ZWS5DPOJ42K5TBNR2WLKJWHAYTGNZSHA3TDAVEOR4XAZNFNFZXG5LFUV3GC3DVMWVDEMRRGA2TINJVGQ4IFJDUPFYGLJLMMFRGK3FFOZQWY5LFVI2TQNZQG43TQNZUGGTXI4TJM5TWK4VGMNZGKYLUMU>
.
You are receiving this email because you authored the thread.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>
.
|
This is beyond features that Redis offers; I have discussed similar with Redis, but it hasn't gone anywhere; maybe Garnet can trailblaze here?
The FIFO nature of Redis request/response means that two scenarios cause severe head-of-line blocking problems:
BRPOP
etc)Wouldn't it be nice if async completion was possible, WITHIN the existing RESP protocol?
Proposal:
Add a feature that is consistent with the pattern used by the client side caching Redis feature, composed of four parts:
ASYNC {ON|OFF} [REDIRECT conn] [OPTIN]
- enables the async feature on a connection, optionally specifying a redirect pub/sub connection (required on RESP2, disallowed on RESP3), and the optionalOPTIN
that indicates whether this is on/off by default on a command-by-command basis; response:+OK
ASYNC {YES|NO}
- (requiresASYNC ON
first) optional; explicitly enable/disable async for the next operation (typically used asASYNC YES
to turn async on for an individual call, whenOPTIN
is enabled) - response:+OK
-ASYNC token
new error response from the server when a specific operation has gone out-of-band, wheretoken
is the correlation identifier to match this result when available (only used whenASYNC ON
is in operation, and the command is electing to use async)"async"
, the correlation identifier, and the RESP fragment that is the response for that message; this includes all possible RESP responses including errors, etcWhen is a command eligible for async?
ASYNC ON
must have been issued, and no subsequentASYNC OFF
OPTIN
was specified, there must be anASYNC YES
immediately† before the messageASYNC NO
immediately† before the message†=allowing for stacking with other "applies to the next command" commands, for example
CLIENT CACHING
Notes:
-ASYNC token
-MOVED
for cluster-ERR
fromASYNC
commands on servers that do not implement it; the next command will simply return synchronously which is exactly what we expect - no change to sync pathASYNC
is inherently also saying "I'm ok with this going out of FIFO"MULTI
(responses will-QUEUED
, including forASYNC
messages) or forWATCH
/DISCARD
(response will always be synchronous); the server may (but is not required to) allow async completion forEXEC
Lua
(responses will be synchronous)brpop
etc) would be expected to work as such, though-ERR too many async operations
ASYNC
command will never itself give a-ASYNC
responseASKING
,READONLY
,READWRITE
,SELECT
are always synchronous-ASYNC 123
and-ASYNC 456
may receive async responses in the order456
then123
Typical usage:
On RESP3 the
REDIRECT 12344
would be omitted, and the server would respond (at some point) via "push" on the same connection.Alternatively:
I am happy to offer the time to get such an idea working with SE.Redis
The text was updated successfully, but these errors were encountered: