Repository navigation
fetch data from leader - #770
JacksonYao287 wants to merge 1 commit into
Conversation
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #770 +/- ##
===========================================
+ Coverage 56.51% 66.72% +10.20%
===========================================
Files 108 110 +2
Lines 10300 13056 +2756
Branches 1402 1895 +493
===========================================
+ Hits 5821 8711 +2890
+ Misses 3894 3347 -547
- Partials 585 998 +413 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
xiaoxichen
left a comment
There was a problem hiding this comment.
LGTM
It will be interesting if we allow to fetch from non-leader which will offload the IO pressure of fetch_data on leader. cc @Besroy
But that can be done in other track.
| RD_REL_ASSERT(false, "Error in reading data"); | ||
|
|
||
| // if read data failed, we should ignore the rpc_data and let the follower retry the fetch | ||
| RD_LOGT(NO_TRACE_ID, |
| return; | ||
|
|
||
| // TODO: Find a way to return error to the Listener | ||
| // TODO: actually will never arrive here as iomgr will assert |
There was a problem hiding this comment.
Remove the TODO and put the non-io-error cases into the L1305
| group_msg_service() | ||
| ->data_service_request_bidirectional( | ||
| originator, FETCH_DATA, | ||
| leader_server_id, FETCH_DATA, |
There was a problem hiding this comment.
remove the comment in L1207
| rreq->remote_blkid().server_id /* blkid_originator */, | ||
| leader_server_id, | ||
| builder->CreateVector(rreq->remote_blkid().blkid.serialize().cbytes(), | ||
| rreq->remote_blkid().blkid.serialized_size()))); |
There was a problem hiding this comment.
If the originator != leader, will the remote_blkid change (due to garbage and vchunk->pchunk mapping)?
There was a problem hiding this comment.
HO will read from the given remote blkid and verify data, if failed, it will try to read from index.
This fallback allow us send fetch data to anyone.
There was a problem hiding this comment.
Thank you for your explanation. I'm not sure if we need to add some logic in HO to handle scenarios like chunk reclamation or disk bad here. Nevertheless, it looks good to me.
There was a problem hiding this comment.
chunk reclaim is fine as validate_blob will fail. Bad drive (or degrade mode) is a concern..... lets create an issue and wait zhiteng's POC on single-disk-mode....
| COUNTER_INCREMENT(m_metrics, fetch_total_blk_size, total_size); | ||
| if (!raw_data || total_size == 0) { | ||
| RD_LOGW(NO_TRACE_ID, "Data Channel: FetchData returned empty payload, ignoring"); | ||
| return; |
There was a problem hiding this comment.
JFYI: If a fetch is called during the end_of_append_batch and the leader returns empty data, the follower currently does not retry. After expiration, it will trigger the assertion at notify_after_data_written:HS_REL_ASSERT(false, "Data fetch timeout, should not happen");. However, this seems to be an existing issue; perhaps we could add a TODO for a retry mechanism.
af5351b to
1e91a4e
Compare
|
I have changed the policy of fetching data to fetch data from a random peer. as a result , it need the host to be capable of parsing user_header and get the correct blob. However, In the current raft_repl_dev UT, it use the default implementation of fetch_data, which will directly fetch data by blk_id and not do any user_header parsing, so this will lead to some data verification error. to support this case, I also add a choice to also support the case of only fetching data from originator. |
xiaoxichen
left a comment
There was a problem hiding this comment.
lgtm aside from a nit
| // clear reqs that has allocated blks on the given chunk. | ||
| void clear_chunk_req(chunk_num_t chunk_id); | ||
|
|
||
| static void enable_fetch_data_only_from_originator(bool enable) { m_fetch_data_only_from_originator = enable; } |
There was a problem hiding this comment.
suggest add virtual bool ReplDevListener::support_fetch_from_non_leader() {return false}
It will be cleaner.
In HO we overwrite this member function to return true.
| std::vector< int32_t > peer_ids; | ||
| for (const auto& srv_config : srv_configs) { | ||
| auto peer_id = srv_config->get_id(); | ||
| if (peer_id != m_raft_server_id) peer_ids.emplace_back(peer_id); |
There was a problem hiding this comment.
fetch data might fail and then generate some garbage here if the selected peer doesn't have data in the following case, but anyway, raft will retry:
T1: leader push blob=100 to F1 and F2
T2: F1 and F2 cannot alloc blk because the related shard not committed
T3: F1 append log, fetch data from F2
T4: F2 append log, fetch data from F1
then F1 and F2 will failed to get data, waiting raft retry and select the leader
There was a problem hiding this comment.
Thanks this is a good point.
Maybe we should only fetch data when we are in resync mode ? in that case (only consider 3 copies) leader and another follower both committed.
Lets track this and verify in SH testing, and decide based on metrics,
- how much improvement we see in fetch latency ?
- how many more garbages this approach create vs previous?
|
I find a read verification issue in storage hammer testing. I need to confirm whether it is caused by recent PRs. so I will hold off on merging the PR until I figure out what happens. cc @Besroy @xiaoxichen |
1e91a4e to
81eb2ed
Compare
81eb2ed to
3a6a385
Compare
86e32e2 to
5218d1c
Compare
1 fetch data from leader , not leader, to avoid the case that originator is the out_member when replace member happens
2 if error happens when handling fetch_data request, return empty mesage and let follower retry. don`t crash