@Override
  public void preGetOp(ObserverContext<? extends RegionCoprocessorEnvironment> c, Get get,
    List<Cell> result) throws IOException {
    Scan scan =
      new Scan().withStartRow(get.getRow()).withStopRow(get.getRow(), true).readAllVersions();
    NavigableMap<byte[], NavigableMap<byte[], MutableLong>> sums =
      new TreeMap<>(Bytes.BYTES_COMPARATOR);
    get.getFamilyMap().forEach((cf, cqs) -> {
      NavigableMap<byte[], MutableLong> ss = new TreeMap<>(Bytes.BYTES_COMPARATOR);
      sums.put(cf, ss);
      cqs.forEach(cq -> {
        ss.put(cq, new MutableLong(0));
        scan.addColumn(cf, cq);
      });
    });
    List<Cell> cells = new ArrayList<>();
    try (RegionScanner scanner = c.getEnvironment().getRegion().getScanner(scan)) {
      boolean moreRows;
      do {
        moreRows = scanner.next(cells);
        for (Cell cell : cells) {
          byte[] family = CellUtil.cloneFamily(cell);
          byte[] qualifier = CellUtil.cloneQualifier(cell);
          long value = Bytes.toLong(cell.getValueArray(), cell.getValueOffset());
          sums.get(family).get(qualifier).add(value);
        }
        cells.clear();
      } while (moreRows);
    }
    sums.forEach((cf, m) -> m.forEach((cq, s) -> result
      .add(createCell(get.getRow(), cf, cq, HConstants.LATEST_TIMESTAMP, s.longValue()))));
    c.bypass();
  }
An example for implementing a counter that reads is much less than writes, i.e, write heavy.
<p>
We will convert increment to put, and do aggregating when get. And of course the return value of
increment is useless then.
<p>
Notice that this is only an example so we do not handle most corner cases, for example, you must
provide a qualifier when doing a get.
hbase-examples/src/main/java/org/apache/hadoop/hbase/coprocessor/example/WriteHeavyIncrementObserver.java