@Override
  public void initialize(PartitionedRegionLoadModel model) {
    Member sourceMember = model.getMember(source);
    if (sourceMember == null) {
      throw new IllegalStateException(
          String.format(
              "Source member does not exist or is not a data store for the partitioned region %s: %s",
              model.getName(), source));
    }

    // Figure out how much load we are moving, based on the percentage.
    float sourceLoad = sourceMember.getTotalLoad();
    loadToMove = sourceLoad * percentage / 100;

    membershipChanged(model);
  }
Move buckets from one node to another, up to a certain percentage of the source node. Each call
to nextStep attempts to move a single bucket.

This uses a first fit decreasing strategy to choose which buckets to move. It sorts the buckets
by size, and then moves the largest bucket that is below the load we are trying to move.

An improvement would be find the bucket that can be moved with the least cost for the most load
change, but because the load probe currently use the same value for load and cost, there's no
need to complicate things now.
geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/rebalance/PercentageMoveDirector.java