[improve](env) Ensure next majority is met before drop an alive follower (#28101)
Here is an example: ``` mysql> ALTER SYSTEM DROP FOLLOWER "127.0.0.1:19017"; ERROR 1105 (HY000): errCode = 2, detailMessage = Unable to drop this alive follower, because the quorum requirements are not met after this command execution. Current num alive followers 2, num followers 3, majority after execution 2 ```
This commit is contained in:
@ -2768,6 +2768,10 @@ public class Env {
|
||||
throw new DdlException(role.toString() + " does not exist[" + NetUtils
|
||||
.getHostPortInAccessibleFormat(host, port) + "]");
|
||||
}
|
||||
if (role == FrontendNodeType.FOLLOWER && fe.isAlive()) {
|
||||
// Try drop an alive follower, check the quorum safety.
|
||||
ensureSafeToDropAliveFollower();
|
||||
}
|
||||
|
||||
int targetFollowerCount = getFollowerCount() - 1;
|
||||
if (fe.getRole() == FrontendNodeType.FOLLOWER || fe.getRole() == FrontendNodeType.REPLICA) {
|
||||
@ -2796,6 +2800,30 @@ public class Env {
|
||||
helperNodes.removeIf(node -> node.getHost().equals(host) && node.getPort() == port);
|
||||
}
|
||||
|
||||
private void ensureSafeToDropAliveFollower() throws DdlException {
|
||||
int numFollower = 0;
|
||||
int numAliveFollower = 0;
|
||||
for (Frontend fe : frontends.values()) {
|
||||
if (fe.getRole() == FrontendNodeType.FOLLOWER) {
|
||||
numFollower += 1;
|
||||
if (fe.isAlive()) {
|
||||
numAliveFollower += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int nextMajority = ((numFollower - 1) / 2) + 1;
|
||||
if (nextMajority + 1 <= numAliveFollower) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG.warn("Drop an alive follower is not safety. Current alive followers {}, followers {}, next majority: {}",
|
||||
numAliveFollower, numFollower, nextMajority);
|
||||
throw new DdlException("Unable to drop this alive follower, because the quorum requirements "
|
||||
+ "are not met after this command execution. Current num alive followers "
|
||||
+ numAliveFollower + ", num followers " + numFollower + ", majority after execution " + nextMajority);
|
||||
}
|
||||
|
||||
public Frontend checkFeExist(String host, int port) {
|
||||
for (Frontend fe : frontends.values()) {
|
||||
if (fe.getEditLogPort() != port) {
|
||||
|
||||
Reference in New Issue
Block a user