You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@hbase.apache.org by "chenglei (Jira)" <ji...@apache.org> on 2021/11/30 10:38:00 UTC

[jira] [Updated] (HBASE-26488) Memory leak when MemStore retry flushing

     [ https://issues.apache.org/jira/browse/HBASE-26488?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

chenglei updated HBASE-26488:
-----------------------------
    Summary: Memory leak when MemStore retry flushing  (was: Memory leak when MemStore retrying)

> Memory leak when MemStore retry flushing
> ----------------------------------------
>
>                 Key: HBASE-26488
>                 URL: https://issues.apache.org/jira/browse/HBASE-26488
>             Project: HBase
>          Issue Type: Bug
>    Affects Versions: 3.0.0-alpha-1, 2.4.8
>            Reporter: chenglei
>            Assignee: chenglei
>            Priority: Major
>              Labels: regionserver
>
> {{HStore.flushCache}} use following {{DefaultStoreFlusher.flushSnapshot}} to flush memStore and retry this method when this method throws exception,but increasing reference count of {{MemStoreLABImpl}}  which used by {{DefaultMemStore.snapshot}} in following line 55 and decreasing reference count of {{MemStoreLABImpl}}  in following line 82 is asymmetrical:
> {code:java}
> 47 public List<Path> flushSnapshot(MemStoreSnapshot snapshot, long cacheFlushId,
> 48      MonitoredTask status, ThroughputController throughputController,
> 49      FlushLifeCycleTracker tracker) throws IOException {
> 50    ArrayList<Path> result = new ArrayList<>();
> 51   int cellsCount = snapshot.getCellsCount();
> 52    if (cellsCount == 0) return result; // don't flush if there are no entries
> 53
> 54    // Use a store scanner to find which rows to flush.
> 55    InternalScanner scanner = createScanner(snapshot.getScanners(), tracker);
> 56    StoreFileWriter writer;
> 57    try {
> 58      // TODO:  We can fail in the below block before we complete adding this flush to
> 59      //        list of store files.  Add cleanup of anything put on filesystem if we fail.
> 60      synchronized (flushLock) {
> 61        status.setStatus("Flushing " + store + ": creating writer");
> 62       // Write the map out to the disk
> 63        writer = store.createWriterInTmp(cellsCount,
> 64            store.getColumnFamilyDescriptor().getCompressionType(), false, true,
> 65           snapshot.isTagsPresent(), false);
> 66        IOException e = null;
> 67        try {
> 68          performFlush(scanner, writer, throughputController);
> 69        } catch (IOException ioe) {
> 70          e = ioe;
> 71          // throw the exception out
> 72          throw ioe;
> 73        } finally {
> 74          if (e != null) {
> 75            writer.close();
> 76          } else {
> 77            finalizeWriter(writer, cacheFlushId, status);
> 78          }
> 79        }
> 80      }
> 81    } finally {
> 82      scanner.close();
> 83    }
> ......
> {code}
> The asymmetry because above line 55 {{snapshot.getScanners}} ,which is following {{MemStoreSnapshot.getScanners}}:
> {code:java}
>        public List<KeyValueScanner> getScanners() {
>                return scanners;
>        }
> {code}
> {{MemStoreSnapshot.getScanners}} does not create new {{SegmentScanner}}, and reuse the  {{SegmentScanner}} in following line 43 created in {{MemStoreSnapshot}} ctor:
> {code:java}
> 38 public MemStoreSnapshot(long id, ImmutableSegment snapshot) {
> 39    this.id = id;
> 40    this.cellsCount = snapshot.getCellsCount();
> 41    this.memStoreSize = snapshot.getMemStoreSize();
> 42    this.timeRangeTracker = snapshot.getTimeRangeTracker();
> 43    this.scanners = snapshot.getSnapshotScanners();
> 44    this.tagsPresent = snapshot.isTagsPresent();
> 45 }
> {code}
> So when flushing MemStore by {{DefaultStoreFlusher.flushSnapshot}} at first time, the reference count of {{MemStoreLABImpl}}  which used by {{DefaultMemStore.snapshot}} is 1, and if {{DefaultStoreFlusher.flushSnapshot}} throws exception, the {{SegmentScanner}} of {{DefaultMemStore.snapshot}}  is closed at
> the  end of {{DefaultStoreFlusher.flushSnapshot}} , and the the reference count of corresponding {{MemStoreLABImpl}} is decreased to 0.
> When retry flushing MemStore by {{DefaultStoreFlusher.flushSnapshot}} at first time



--
This message was sent by Atlassian Jira
(v8.20.1#820001)