Add ledger-tool dead-slots and improve purge a lot#13065
Add ledger-tool dead-slots and improve purge a lot#13065mergify[bot] merged 3 commits intosolana-labs:masterfrom
Conversation
|
example run result: |
| end_slot - start_slot, | ||
| no_compaction, | ||
| ); | ||
| for slots in &(start_slot..=end_slot).chunks(batch_size) { |
There was a problem hiding this comment.
Hmm, with dead_slot_iterator, we can do better by implementing ledger-tool purge --only-dead-slots? Or, too dangerous to add it at this moment? ;)
There was a problem hiding this comment.
Hmm, I think we should lean to the safer side. Still, the support incident's root cause is unclear. Purging only dead slots might not be enough...
There was a problem hiding this comment.
I think we should lean to the safer side. Still, the support incident's root cause is unclear. Purging only dead slots might not be enough...
On the other hand, I'm starting to suspect a validator can handle the repair_state which will contain around 2_200_000 worth of slots to repair (this is the number of slots since the incident up to the current slot).... So, maybe purging dead slots only might be the only viable way forward?
@carllin do you have rough estimate for the required ram? Also, maybe flushing repairs to disk isn't small work, right?
There was a problem hiding this comment.
Cool, solana-validator even can repair from snapshot-39258079-7o86jrh3NJNjYxx4pWcPa7fSwAZvX4HynXdhynZ98VF2.tar.zst, it seems atm.
So there is no problem.
We want to resume from around slot 41040067
There was a problem hiding this comment.
Hmm, with dead_slot_iterator, we can do better by implementing
ledger-tool purge --only-dead-slots?
I just added this in case for the backup plan: 61c38ac
| for slots in &(start_slot..=end_slot).chunks(batch_size) { | ||
| let slots = slots.collect::<Vec<_>>(); | ||
| assert!(!slots.is_empty()); | ||
|
|
||
| let start_slot = *slots.first().unwrap(); | ||
| let end_slot = *slots.last().unwrap(); |
There was a problem hiding this comment.
I think this batching logic should be too simple to introduce bugs.
There was a problem hiding this comment.
And this should be semantically equivalent repeatedly executing solana-ledger-tool purge ... {N1 N2, N2 N3, N3 N4}.
| ("purge", Some(arg_matches)) => { | ||
| let start_slot = value_t_or_exit!(arg_matches, "start_slot", Slot); | ||
| let end_slot = value_t!(arg_matches, "end_slot", Slot).ok(); | ||
| let no_compaction = arg_matches.is_present("no-compaction"); |
There was a problem hiding this comment.
"no-compaction" should be "no_compaction": https://github.com/solana-labs/solana/pull/11052/files#r509242376 #11052
Codecov Report
@@ Coverage Diff @@
## master #13065 +/- ##
=======================================
Coverage 82.1% 82.1%
=======================================
Files 366 366
Lines 86097 86105 +8
=======================================
+ Hits 70739 70748 +9
+ Misses 15358 15357 -1 |
|
|
||
| let end_slot = last_slot.unwrap(); | ||
| info!("Purging slots {} to {}", start_slot, end_slot); | ||
| blockstore.purge_slots(start_slot, end_slot, PurgeType::Exact); |
There was a problem hiding this comment.
this order was very broken, when the process is interrupted immediately after purge_slots and before purge_from_next_slots. It leaves super dangerous dangling references in meta....
| purge_from_blockstore(dead_slot, dead_slot); | ||
| } | ||
| } | ||
| blockstore.purge_from_next_slots(start_slot, end_slot); |
There was a problem hiding this comment.
this order was very broken, when the process is interrupted immediately after purge_slots and before purge_from_next_slots. It leaves super dangerous dangling references in meta....
There was a problem hiding this comment.
Well, when I was working around https://github.com/solana-labs/solana/pull/12350/files#diff-5e9f940ea065adfd3066ef0d8ef0cfb5029b5ba478d96fb484b36954e464505cR1609, I just skipped the fact check and corrected new code only.... and now that laziness bit me. ;)
|
|
||
| // Column family names | ||
| let meta_cf_descriptor = ColumnFamilyDescriptor::new(SlotMeta::NAME, get_cf_options()); | ||
| let meta_cf_descriptor = |
There was a problem hiding this comment.
heh, finally rustfmt aligns these nicely. ;)
| .long("batch-size") | ||
| .value_name("NUM") | ||
| .takes_value(true) | ||
| .default_value("1000") |
There was a problem hiding this comment.
well, I preferred more large values; but it seems that 10000 (45 slots/sec) worsens the throughput...
not much digging; I'll just settle down on 1000 (measured 50 slots/sec).
* Add ledger-tool dead-slots and improve purge a lot * Reduce batch size... * Add --dead-slots-only and fixed purge ordering (cherry picked from commit 0776fa0)
Problem
We need to support an incident where a validator must recover from very old slot (which are marked as dead because of corruption for unknown reason).
Summary of Changes
ledger-tool dead-slotswhich just prints the dead slots.ledger-tool purgeby batching. Previously, we tried to create infinitely-large (well, practically) rockdb's WriteBatch, resulting instd::bad_allocfrom libstd++ in librocksdb.ledger-tool purgeby really disabling auto and manual compaction (--no-compaction haven't working to begin with due to a bug....)...Combined with the changes, it's still slow but tolerable and finally we can purge any number of slots.
Note: This pr should be quickly backported way down to v1.3, so I tried to keep minimize diff and risk (of bugs).
Fixes #12907