Skip to content

Entry Log GC may get blocked when using entryLogPerLedgerEnabled option #2728

Description

@RaulGracia

BUG REPORT

Describe the bug

Summary: We use entryLogPerLedgerEnabled:"true" option in environments that have SSDs/NVMes to exploit drive parallelism and it provides significant improvements (as suggested in documentation). However, under high throughput workloads (1GBps, 6 Bookies, 3 replicas), our experiments showed us that there is a consistent problem with this option in which, at some point, makes the ledger volume to run out of storage space. Concretely, at some point one entry log file does not get rotated (i.e., flushRotatedLogs() method does not get invoked in EntryLogManagerForEntryLogPerLedger) while the system continues writing data and generating more entry log files. When this happens, and given that the removal of unnecessary (truncated) entry logs is sequential by entry log id, the GC Thread cannot continue progressing deleting entry logs. This eventually leads to the ledger volume to fill up. This problem was first detected on Bookkeeper 4.11.1 but we also reproduced it in Bookkeeper 4.14.0.

Next, we expose a more detailed explanation with real logs of the issue. Everything works well for some time (minutes or hours, depending on the load) until we detect some ledger activity like this:

(ENTRY LOG ID 1261)
λ grep "Created new entry log file\|Synced" bookkeeper-server-0.log | grep "1261"
2021-05-09 14:35:25,364 - INFO  - [pool-4-thread-1:EntryLoggerAllocator@181] - Created new entry log file /bk/ledgers/current/4ed.log for logId 1261.
2021-05-09 14:37:32,800 - INFO  - [SyncThread-14-1:EntryLogManagerForEntryLogPerLedger@693] - Synced entry logger 1261 to disk.

(ENTRY LOG ID 1262)
λ grep "Created new entry log file\|Synced" bookkeeper-server-0.log | grep "1262"
2021-05-09 14:35:26,152 - INFO  - [pool-4-thread-1:EntryLoggerAllocator@181] - Created new entry log file /bk/ledgers/current/4ee.log for logId 1262.

(ENTRY LOG ID 1263)
λ grep "Created new entry log file\|Synced" bookkeeper-server-0.log | grep "1263"
2021-05-09 14:35:26,419 - INFO  - [pool-4-thread-1:EntryLoggerAllocator@181] - Created new entry log file /bk/ledgers/current/4ef.log for logId 1263.
2021-05-09 14:36:33,031 - INFO  - [SyncThread-14-1:EntryLogManagerForEntryLogPerLedger@693] - Synced entry logger 1263 to disk.

So, as we can see, there is no Synced entry logger XXX for entry log id 1262, but the subsequent entry logs are rotated. The problem is that it seems that one entry log file not being "rotated" impacts GC for all the subsequent files. That is, if we look at the code that calculates the entryLogger.getLeastUnflushedLogId(), is as follows:

synchronized void flushRotatedEntryLog(Long entryLogId) {

synchronized void flushRotatedEntryLog(Long entryLogId) {                
    entryLogsStatusMap.replace(entryLogId, true);            
    while ((!entryLogsStatusMap.isEmpty()) &&(entryLogsStatusMap.get(entryLogsStatusMap.firstKey()))) {                
        long leastFlushedLogId = entryLogsStatusMap.firstKey();                
        entryLogsStatusMap.remove(leastFlushedLogId);                
        leastUnflushedLogId = leastFlushedLogId + 1;            
    }        
}

As you can see, flushRotatedEntryLog is only going to make progress assuming that each an every of the entry log files have been rotated. If just one of them is not rotated, then it stops updating leastUnflushedLogId, which makes the GC not deleting entry logs beyond that point:

For that entry log 1262, we see this message multiple times along the experiment:

2021-05-09 14:35:31,942 - DEBUG - [SyncThread-14-1:EntryLogManagerBase@129] - Flush and sync current entry logger 1262
...
2021-05-09 15:07:31,831 - DEBUG - [SyncThread-14-1:EntryLogManagerBase@129] - Flush and sync current entry logger 1262

Again, there is no sign of the message Synced entry logger XXXX to disk for that entry log file. This explains why the GC stopped, which makes sense given the current logic. But we don't know why the rotation of that entry log 1262 did not complete. Another question is whether GC for any subsequent entry log file should be stuck just because one of them is making slower progress in getting rotated.

Note that this problem only appears when entryLogPerLedgerEnabled:"true", so disabling that option solves the problem but at the cost of not being able to exploit the parallelism of SSDs/NVMe drives.

To Reproduce

Inducing a high load (+500MBps) on a Bookie with entryLogPerLedgerEnabled:"true", we normally get this error.

Expected behavior

A Bookie with entryLogPerLedgerEnabled:"true" should be able to continue garbage collecting entry log files even though one of the previous entry log files has not been yet rotated.

Screenshots
In this screenshot you can see the behavior related to this issue. As you can see, the Disk Usage of the ledger volume for few Bookies continues to grow until they get in read-only mode, whereas others are still handling properly GC activity:

image (3)

Additional context
n/a

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions