-
Notifications
You must be signed in to change notification settings - Fork 160
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
Change: remove AsyncSeek trait from snapshot #605
Conversation
b649785
to
1b1f046
Compare
1b1f046
to
a7a733a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The receiving end should not expect that snapshot segments will arrive in order. Thus seek
will be required.
I'm not sure I follow why. If that's the case then the receiving end might get a message with |
You are right the current implementation does not need AsyncSeek. In the future, several snapshot segments may be transmitted simultaneously and received in arbitrary orders to speed up snapshot transfer. Since it is a usual way for optimization thus, for now, it would be better not to assume segments are received in order. make sense? :D |
If the project's plan is to send chunks of the same snapshot in parallel then that makes sense. IMO that also seems like the kind of optimization that the user of the api should be making or let them be exposed to that option. Keeping AsyncSeek to me feels like it forces the underlying snapshot to be a single file or something that can fit in memory. Which severely limits what the users of the lib can do. |
Just my 2c: I'm also having my share of thoughts about the snapshot handling and I don't particularly like the stream-based API, and especially the AsyncSeek part :-). Our snapshot is a completely different beast and can't be easily pressed into a stream. What we'll use is probably some kind of out-of-band transport mechanism just sending a tiny information about the snapshot, which is then handled in an application-specific way. Speeding up the snapshot transfer in general makes sense - but then probably using a better protocol. But even a "regular" TCP/IP can already transfer >=4GB/s with a single stream (see for example https://doc.tm.uka.de/2019-LCN-100g-tuning-authors-copy.pdf for some pointers). There are also newer protocols better optimized for high-speed transfer, so I wouldn't force using a simple stream, seekable or not. |
@schreter I'm pretty sure I'm in the same boat as you (Rocksdb with large files). I was also looking at doing that approach or similar, but it alway seemed odd to have a massive timeout on sending the snapshot part (I'm still doing it anyways though). My original thought was to just let the user do whatever they want #600 but it sounds like that exposes to much of the raft logic to the user to worry about/implement. |
Looks like there are two options:
For option 1, either treat the snapshot as a sequence of bytes, as it does now, by making it seekable, or an application must define how snapshot data is organized, e.g., a list of rocksdb SSTable plus the level and key space of every SSTable. For option 2, the |
:D
IMHO, a trait such as read_snapshot_segment<SegmentId, Segment>(snapshot_id: SnapshotId, segment_id: SegmentId) -> Segment;
// Return true if all segments are received.
save_snapshot_segment<SegmentId, Segment>(snapshot_id: SnapshotId, segment_id: SegmentId, s: Segment) -> bool; For @schreter 's need, Finally, when |
Sorry I keep asking what feels like the same question, but for:
What is the downside to relying on this? Was it that the snapshot streaming would require too much raft state management? |
Is OK:)
Even without checking the Thus the safe way as it does now, is to let RaftCore check |
I finally see where my confusion and the disconnect on this is! I thought for Option 2 above, the downloading of the segments and building of the local (remote) snapshot would be done before the I like the idea of having exposing more API abstractions around the snapshot. Maybe something that would combine
The receiving side would implement the endpoint RPC's for the sender to send too. And would call the
|
Building a snapshot is simple. There won't be any change AFAIK. :) To send a snapshot, first, the Then let each On the receiving node, For every received segment, When all segments are transmitted, the sending node sends another The receiving node then calls The final step is I skipped some non-critical parts such as canceling a snapshot transmission. Any opinions? :) |
I think the above would solve most of issues I've run into!
I just want to make sure I understand the difference between this and what is currently being done. By following this pattern, |
I'd like an application just handle RPCs by simply forwarding them to
By my design, it should be called by You gave me a good point: whether a receiving snapshot process finishes can be returned by
Right, it's weird.
Yes, the application calls If I didn't explain something clearly, just let me know:) |
Got it. So |
One of the options is to provide two APIs: :S |
Thinking about it a bit more, |
I think we resolved this. |
Snapshots don't really need to be AsyncSeek. Simplifying the trait bounds for a snapshot.
Checklist
This change is