Skip to content

Conversation

@zuston
Copy link
Member

@zuston zuston commented Dec 2, 2022

What changes were proposed in this pull request?

  1. Avoid partial events being pushed into pending queue when using MultipleStorageManager
  2. Introduce the cleanupCallback of ShuffleDataFlushEvent to scope all cleanup operation with event lifecycle.
  3. Make the concrete under storage bound to data-flush event to avoid duplicate invoking selectStorage method after writing.
  4. Refactor the whole flush process to a while loop, more simple and clear.
  5. Add the metric of total_failed_written_event_num

Why are the changes needed?

To fix the fallback invalid when data-flush event enters into pending queue

Does this PR introduce any user-facing change?

No

How was this patch tested?

  1. Simple UTs
  2. Integration tests

@zuston zuston requested review from jerqi and xianjingfeng December 2, 2022 03:25
private final ShuffleBuffer shuffleBuffer;
private final AtomicInteger retryTimes = new AtomicInteger();
private boolean isPended = false;
private StorageManager underStorageManager;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we avoid using storageManager in a ShuffleDataFlushEvent? It's a little weird.

Copy link
Member Author

@zuston zuston Dec 2, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I also want to avoid this, but if we don't, we have to maintain this relation mapping in multipleStorageManager. However we couldn't remove this structure when event's lifecycle finished, because we don't have similar interface in storage manager

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we only have Storage field. Could we use Storage to find its StorageManager?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently it can't. But this solution sounds great. We could extend the interface of storage

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently it can't. But this solution sounds great. We could extend the interface of storage

I think we need add a interface for StorageManager#isBelongto(Storage storage). Storage is in the module storage. StorageManager is in the module server. Storage shouldn't depend on StorageManager.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Emmm…. I still think cache is not suitable. Because it holds the reference of events and will cause memory leak. We should implicitly remove this event reference when event is flushed.

It's not acceptable for me to put StorageManager into ShuffleDataFlushEvent. I would rather give up this strategy.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know. I don’t insist on keeping this into event. I just explain the cache is also unreasonable.

And this is also a potential bug due to memory leak.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add a callback for ShuffleFlushEvent. In the callback, it will remove the data. When we call the cleanupFlushEventData(event) method. We call event.clearCallback();

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds great!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The relation will help event find the concrete under-storage-manager selected by method of selectStorage when invoked by write method. Right? @xianjingfeng

Yes, if we remove pending queue, we don't need maintain this relation.

@jerqi
Copy link
Contributor

jerqi commented Dec 2, 2022

We should refactor the ShuffleFlushEvent. We need a method getShuffleWriteHandler(ShuffleFlushEvent). So we can remove Storage.getCreateWriterHandlerRequest().

@jerqi
Copy link
Contributor

jerqi commented Dec 2, 2022

To implement what you want
We just modify here

  private StorageManager selectStorageManager(ShuffleDataFlushEvent event) {
    StorageManager storageManager = storageManagerCache.getIfPresent(event);
    if (storageManager != null) {
      // modify here if storageManager is not canWrite we fallback.
      return storageManager;
    }
    if (event.getSize() > flushColdStorageThresholdSize) {
      storageManager = coldStorageManager;
    } else {
      storageManager = warmStorageManager;
    }

    if (!storageManager.canWrite(event)) {
      storageManager = storageManagerFallbackStrategy.tryFallback(
          storageManager, event, warmStorageManager, coldStorageManager);
    }
    storageManagerCache.put(event, storageManager);
    return storageManager;
  }

@codecov-commenter
Copy link

codecov-commenter commented Dec 2, 2022

Codecov Report

Merging #383 (48082a4) into master (897613b) will increase coverage by 0.18%.
The diff coverage is 64.89%.

@@             Coverage Diff              @@
##             master     #383      +/-   ##
============================================
+ Coverage     58.59%   58.78%   +0.18%     
- Complexity     1589     1602      +13     
============================================
  Files           193      193              
  Lines         10910    10938      +28     
  Branches        957      955       -2     
============================================
+ Hits           6393     6430      +37     
+ Misses         4139     4131       -8     
+ Partials        378      377       -1     
Impacted Files Coverage Δ
...rg/apache/uniffle/storage/common/LocalStorage.java 43.22% <0.00%> (-0.57%) ⬇️
...orage/handler/impl/LocalFileClientReadHandler.java 61.29% <ø> (+1.91%) ⬆️
...org/apache/uniffle/server/ShuffleFlushManager.java 78.01% <61.11%> (-1.14%) ⬇️
...g/apache/uniffle/server/ShuffleDataFlushEvent.java 83.33% <66.66%> (-16.67%) ⬇️
...he/uniffle/server/storage/MultiStorageManager.java 64.15% <66.66%> (+16.38%) ⬆️
...rg/apache/uniffle/server/ShuffleServerMetrics.java 97.19% <100.00%> (+0.96%) ⬆️
...rg/apache/uniffle/server/buffer/ShuffleBuffer.java 93.38% <100.00%> (+0.05%) ⬆️
...he/uniffle/server/buffer/ShuffleBufferManager.java 82.74% <100.00%> (+0.06%) ⬆️
...che/uniffle/server/storage/HdfsStorageManager.java 95.23% <100.00%> (+0.15%) ⬆️
...he/uniffle/server/storage/LocalStorageManager.java 91.24% <100.00%> (+0.06%) ⬆️
... and 10 more

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@zuston
Copy link
Member Author

zuston commented Dec 2, 2022

To implement what you want We just modify here

  private StorageManager selectStorageManager(ShuffleDataFlushEvent event) {
    StorageManager storageManager = storageManagerCache.getIfPresent(event);
    if (storageManager != null) {
      // modify here if storageManager is not canWrite we fallback.
      return storageManager;
    }
    if (event.getSize() > flushColdStorageThresholdSize) {
      storageManager = coldStorageManager;
    } else {
      storageManager = warmStorageManager;
    }

    if (!storageManager.canWrite(event)) {
      storageManager = storageManagerFallbackStrategy.tryFallback(
          storageManager, event, warmStorageManager, coldStorageManager);
    }
    storageManagerCache.put(event, storageManager);
    return storageManager;
  }

Make sense.

@zuston
Copy link
Member Author

zuston commented Dec 2, 2022

We should refactor the ShuffleFlushEvent. We need a method getShuffleWriteHandler(ShuffleFlushEvent). So we can remove Storage.getCreateWriterHandlerRequest().

For what?

@jerqi
Copy link
Contributor

jerqi commented Dec 2, 2022

We should refactor the ShuffleFlushEvent. We need a method getShuffleWriteHandler(ShuffleFlushEvent). So we can remove Storage.getCreateWriterHandlerRequest().

For what?

I think Storage.getOrCreateWriterHandlerRequest isn't reasonable.

@zuston
Copy link
Member Author

zuston commented Dec 2, 2022

I think Storage.getOrCreateWriterHandlerRequest isn't reasonable.

This is not related with this PR. Let's focus on this.

@zuston zuston changed the title [WIP][BUG] Overlook fallback when data-flush event enters into pending queue [BUG] Overlook fallback when data-flush event enters into pending queue Dec 2, 2022
ShuffleServerMetrics.incStorageRetryCounter(storage.getStorageHost());
continue;
} else {
if (event.isPended()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need isPended?

} else if (!event.isValid()) {
// avoid printing error log

while (true) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do need while(true)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If not, how to handle?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while (retryTimes < maxRetry)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me, it is the same with this PR’s current implementation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, the exit condition in while will be more clear.

I will correct it

@jerqi
Copy link
Contributor

jerqi commented Dec 2, 2022

We should refactor the ShuffleFlushEvent. We need a method getShuffleWriteHandler(ShuffleFlushEvent). So we can remove Storage.getCreateWriterHandlerRequest().

For what?

I think Storage.getOrCreateWriterHandlerRequest isn't reasonable.

My mistake. It's necessary.

long start = System.currentTimeMillis();
List<ShufflePartitionedBlock> blocks = event.getShuffleBlocks();
boolean writeSuccess = false;
try {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to modify the flush process?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this logic need to be refactored.

ShuffleServerMetrics.gaugeEventQueueSize.set(flushQueue.size());
ShuffleServerMetrics.gaugeWriteHandler.inc();
flushToFile(event);
flushToFileImpl(event);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we rename to flushToFIleImpl?
Usually we use Impl method , because we have already had a interface method.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I’ll correct it

@jerqi
Copy link
Contributor

jerqi commented Dec 2, 2022

If we can't make the process clear, I would better to remove pending queue. There are too many bugs caused by pending queue.

@zuston
Copy link
Member Author

zuston commented Dec 2, 2022

If we can't make the process clear, I would better to remove pending queue. There are too many bugs caused by pending queue.

Removing is OK for me.

@jerqi
Copy link
Contributor

jerqi commented Dec 2, 2022

If we can't make the process clear, I would better to remove pending queue. There are too many bugs caused by pending queue.

Removing is OK for me.

Let's remove it. It's more simple.

}

if (!storage.canWrite()) {
if (storageManager instanceof MultiStorageManager) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we avoid judging the MultiStorageManager?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we want to remove pending queue, this is unnecessary.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add an interface supportPending for storageManager?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Emm... It's weird, let me think again.

Copy link
Member Author

@zuston zuston Dec 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let us leave a todo comment for later optimization, and make current PR small.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any process about this optimization?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After supporting multiple disk selection #435 , I think we could remove this pending queue.

@zuston zuston changed the title [BUG] Overlook fallback when data-flush event enters into pending queue [ISSUE-380] Refactor the flush process to fix fallback fail Dec 3, 2022
@zuston zuston requested a review from jerqi December 6, 2022 05:50

if (event.getRetryTimes() > retryMax) {
LOG.error("Failed to write data for {} in {} times, shuffle data will be lost", event, retryMax);
ShuffleServerMetrics.incStorageFailedCounter(event.getUnderStorage().getStorageHost());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getUnderStorage may be null.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch. Fixed.

Copy link
Contributor

@jerqi jerqi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Except for MultiStorageManager, LGTM.

@jerqi jerqi merged commit c09cbd1 into apache:master Dec 6, 2022
@jerqi
Copy link
Contributor

jerqi commented Dec 6, 2022

Merge. thanks @zuston

zuston pushed a commit that referenced this pull request Apr 10, 2024
…rs cache (#1627)

### What changes were proposed in this pull request?

Remove the meaningless eventOfUnderStorageManagers.

### Why are the changes needed?

Fix #1626 & #1620.
It's also a follow-up PR for #383.

This cache only makes sense when the event retries after a failure. However, after the event fails, it is not appropriate to continue taking the original storageManager from the cache(because events usually fail due to high IO pressure or disk damage or disk full). In this case, the cache seems to be meaningless, so there is a contradiction here, we should remove it.

### Does this PR introduce _any_ user-facing change?

No.

### How was this patch tested?

Tested in our env
jerqi pushed a commit that referenced this pull request Apr 30, 2024
…rs cache (#1627)

### What changes were proposed in this pull request?

Remove the meaningless eventOfUnderStorageManagers.

### Why are the changes needed?

Fix #1626 & #1620.
It's also a follow-up PR for #383.

This cache only makes sense when the event retries after a failure. However, after the event fails, it is not appropriate to continue taking the original storageManager from the cache(because events usually fail due to high IO pressure or disk damage or disk full). In this case, the cache seems to be meaningless, so there is a contradiction here, we should remove it.

### Does this PR introduce _any_ user-facing change?

No.

### How was this patch tested?

Tested in our env
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants