-
Notifications
You must be signed in to change notification settings - Fork 421
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RATIS-1411. Alleviate slow follower issue #508
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -119,6 +119,17 @@ static SizeInBytes byteLimit(RaftProperties properties) { | |
static void setByteLimit(RaftProperties properties, SizeInBytes byteLimit) { | ||
setSizeInBytes(properties::set, BYTE_LIMIT_KEY, byteLimit, requireMin(1L)); | ||
} | ||
|
||
String FOLLOWER_MAX_GAP_RATIO_KEY = PREFIX + ".follower-max-gap-ratio"; | ||
float FOLLOWER_MAX_GAP_RATIO_DEFAULT = 1; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's use double instead of float. We should avoid using float, especially in 64-bit computers. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. Except for that double is more precise than float, any major drawbacks of using float? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Precision is the main reason. Also, double is the default in Java. For example, the code below does not compile.
Using float is easier to make mistakes unawarely. Unless space is an issue, we should just use double. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @szetszwo , thanks for the detail info. |
||
|
||
static float followerMaxGapRatio(RaftProperties properties) { | ||
return getFloat(properties::getFloat, FOLLOWER_MAX_GAP_RATIO_KEY, | ||
FOLLOWER_MAX_GAP_RATIO_DEFAULT, getDefaultLog(), requireMax(1f)); | ||
} | ||
static void setFollowerMaxGapRatio(RaftProperties properties, float ratio) { | ||
setFloat(properties::setFloat, FOLLOWER_MAX_GAP_RATIO_KEY, ratio, requireMax(1f)); | ||
} | ||
} | ||
|
||
interface Watch { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -79,6 +79,7 @@ | |
import java.util.stream.Stream; | ||
|
||
import static org.apache.ratis.server.RaftServer.Division.LOG; | ||
import static org.apache.ratis.server.RaftServerConfigKeys.Write.FOLLOWER_MAX_GAP_RATIO_KEY; | ||
|
||
/** | ||
* States for leader only. It contains three different types of processors: | ||
|
@@ -250,6 +251,8 @@ boolean removeAll(Collection<LogAppender> c) { | |
private final long placeHolderIndex; | ||
private final RaftServerMetricsImpl raftServerMetrics; | ||
private final LogAppenderMetrics logAppenderMetrics; | ||
private final long maxPendingRequests; | ||
private final long followerMaxGapThreshold; | ||
|
||
LeaderStateImpl(RaftServerImpl server) { | ||
this.name = server.getMemberId() + "-" + JavaUtils.getClassSimpleName(getClass()); | ||
|
@@ -269,6 +272,13 @@ boolean removeAll(Collection<LogAppender> c) { | |
this.pendingRequests = new PendingRequests(server.getMemberId(), properties, raftServerMetrics); | ||
this.watchRequests = new WatchRequests(server.getMemberId(), properties); | ||
this.messageStreamRequests = new MessageStreamRequests(server.getMemberId()); | ||
this.maxPendingRequests = RaftServerConfigKeys.Write.elementLimit(properties); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change maxPendingRequests to a local variable. |
||
float followerMaxGapRatio = RaftServerConfigKeys.Write.followerMaxGapRatio(properties); | ||
|
||
if (followerMaxGapRatio > 1f || followerMaxGapRatio <= 0f) { | ||
throw new IllegalArgumentException(FOLLOWER_MAX_GAP_RATIO_KEY + "s value must between [1, 0)"); | ||
} | ||
this.followerMaxGapThreshold = (long)(followerMaxGapRatio * maxPendingRequests); | ||
|
||
final RaftConfigurationImpl conf = state.getRaftConf(); | ||
Collection<RaftPeer> others = conf.getOtherPeers(server.getId()); | ||
|
@@ -700,6 +710,17 @@ static MinMajorityMax valueOf(long[] sorted) { | |
return new MinMajorityMax(sorted[0], getMajority(sorted), getMax(sorted)); | ||
} | ||
|
||
static MinMajorityMax valueOf(long[] sorted, long gapThreshold) { | ||
long majority = getMajority(sorted); | ||
long min = sorted[0]; | ||
if ((majority - min) > gapThreshold) { | ||
// The the gap between majority and min(the slow follower) is greater than gapThreshold, | ||
// set the majority to min, which will skip one round of lastCommittedIndex update in updateCommit(). | ||
majority = min; | ||
} | ||
return new MinMajorityMax(min, majority, getMax(sorted)); | ||
} | ||
|
||
static long getMajority(long[] sorted) { | ||
return sorted[(sorted.length - 1) / 2]; | ||
} | ||
|
@@ -725,7 +746,7 @@ private Optional<MinMajorityMax> getMajorityMin(ToLongFunction<FollowerInfo> fol | |
} | ||
|
||
final long[] indicesInNewConf = getSorted(followers, includeSelf, followerIndex, logIndex); | ||
final MinMajorityMax newConf = MinMajorityMax.valueOf(indicesInNewConf); | ||
final MinMajorityMax newConf = MinMajorityMax.valueOf(indicesInNewConf, followerMaxGapThreshold); | ||
|
||
if (!conf.isTransitional()) { | ||
return Optional.of(newConf); | ||
|
@@ -737,7 +758,7 @@ private Optional<MinMajorityMax> getMajorityMin(ToLongFunction<FollowerInfo> fol | |
} | ||
|
||
final long[] indicesInOldConf = getSorted(oldFollowers, includeSelfInOldConf, followerIndex, logIndex); | ||
final MinMajorityMax oldConf = MinMajorityMax.valueOf(indicesInOldConf); | ||
final MinMajorityMax oldConf = MinMajorityMax.valueOf(indicesInOldConf, followerMaxGapThreshold); | ||
return Optional.of(newConf.combine(oldConf)); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's rename it to ".follower.gap.ratio.max".