-
Notifications
You must be signed in to change notification settings - Fork 59
feat: restrict the replication factor while creating app #963
Conversation
Thanks for your pull request for adding replica count check while creating table~
I have a different option with your third rule, I think system should not restrict its table max replica count for scalability. Besides, I think it's unnecessary to make |
src/meta/server_state.cpp
Outdated
std::string hint_message; | ||
|
||
zauto_read_lock l(_lock); | ||
|
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.
{
zauto_read_lock l(_lock);
auto alive_node_count = get_alive_node_count_unlocked();
}
src/meta/server_state.cpp
Outdated
return is_valid; | ||
} | ||
|
||
int32_t server_state::get_alive_node_count_unlocked() |
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.
uint32_t server_state::get_alive_node_count_unlocked() const
Yeah, I agree that we should provide scalability and flexibility for the system. The purpose of introducing Introducing
Considering this example, I think we can set the minimum replication factor as 3 for a cluster that has 3 or more replica servers. |
Okay, your comment persuades me~ |
A good idea ! How about set |
In most our scenarios, replica_count is 3. As our discussion above, |
Ok, how about setting |
I think it's okay to set |
} | ||
|
||
FLAGS_min_allowed_replica_count = 1; |
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.
FLAGS_min_allowed_replica_count = reserved_min_allowed_replica_count;
LGTM |
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.
LGTM~ By the way, I suggest using 'feat' rather than 'fix' to describe this pull request, because this pull request actually provides feature~
Sure, I'll change the type |
FLAGS_min_allowed_replica_count); | ||
return false; | ||
} | ||
|
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.
you may don't need to split two if
to log the hit_message
, consider the following whether more simple:
if (max_replica_count > max_allowed_replica_count || max_replica_count < FLAGS_min_allowed_replica_count) {
hint_message = fmt::format("requested replica count({}) must be range within [min={} max={}] ",
max_replica_count,
FLAGS_min_allowed_replica_count
max_allowed_replica_count);
return false;
}
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.
Ok, I'll merge the both conditions. A range seems more specific.
src/meta/server_state.cpp
Outdated
@@ -56,6 +56,17 @@ using namespace dsn; | |||
namespace dsn { | |||
namespace replication { | |||
|
|||
const int32_t max_allowed_replica_count = 15; |
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.
Why the max
is not set dynamic variable
like min
?
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.
Initially the max_allowed_replica_count
was set configurable. Then as discussed with @hycdong above, max_allowed_replica_count
has been changed as a const value, not a configurable one, since in normal cases it will not be updated.
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.
By the way, the const int should be named like k...
refer to google code style
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.
Agreed. I'd considered following google code style such as the camel-case naming of constant which begins with 'k'. On the other hand, however I'd found many constants are named in upper or lower snake case before I turned to follow the existing custom. I think we should gradually unify the naming style.
@hycdong @empiredan I do consider a const and unoptional value of 15 is too large, any new user could create a table with 15 replicas at most without any limitation, it's harmful for the system. If most cases are 3 replicas, why not make it optional, in the rare case if any body want to create a table with some larger replication factor, they can set a larger RF and reboot the metaserver. |
As I mentioned before, I think |
@hycdong @acelyc111 Or, can we turn to refer to the implementation of the system that has the similar problem with us ? In apache/kudu@b39491d, Todd has explained why kudu uses Therefore, should we make And also, RF is restricted by As for the related code, please see the following quotes: DEFINE_int32(max_num_replicas, 7,
"Maximum number of replicas that may be specified for a table.");
// Tag as unsafe since we have done very limited testing of higher than 5 replicas.
TAG_FLAG(max_num_replicas, unsafe);
TAG_FLAG(max_num_replicas, runtime);
DEFINE_int32(min_num_replicas, 1,
"Minimum number of replicas that may be specified when creating "
"a table: this is to enforce the minimum replication factor for "
"tables created in a Kudu cluster. For example, setting this flag "
"to 3 enforces every new table to have at least 3 replicas for "
"each of its tablets, so there cannot be a data loss when a "
"single tablet server fails irrecoverably.");
TAG_FLAG(min_num_replicas, advanced);
TAG_FLAG(min_num_replicas, runtime);
...
template<typename RespClass>
Status CatalogManager::ValidateNumberReplicas(const std::string& normalized_table_name,
RespClass* resp, ValidateType type,
const boost::optional<int>& partitions_count,
int num_replicas) {
if (num_replicas > FLAGS_max_num_replicas) {
return SetupError(Status::InvalidArgument(
Substitute("illegal replication factor $0: maximum allowed replication "
"factor is $1 (controlled by --max_num_replicas)",
num_replicas, FLAGS_max_num_replicas)),
resp, MasterErrorPB::REPLICATION_FACTOR_TOO_HIGH);
}
if (num_replicas < FLAGS_min_num_replicas) {
return SetupError(Status::InvalidArgument(
Substitute("illegal replication factor $0: minimum allowed replication "
"factor is $1 (controlled by --min_num_replicas)",
num_replicas, FLAGS_min_num_replicas)),
resp, MasterErrorPB::ILLEGAL_REPLICATION_FACTOR);
}
// Reject create/alter table with even replication factors, unless master flag
// allow_unsafe_replication_factor is on.
if (num_replicas % 2 == 0 && !FLAGS_allow_unsafe_replication_factor) {
return SetupError(Status::InvalidArgument(
Substitute("illegal replication factor $0: replication factor must be odd",
num_replicas)),
resp, MasterErrorPB::EVEN_REPLICATION_FACTOR);
}
...
} |
Okay, I think if we set max_num_replica as 5, we should add an option for it, user can update it through config. In this case, it is the unreasonable replica count, it restirct the max replica count through a cluster-level configuration. If user would like to create table with higher replica_count, it should update config. |
+1 |
Ok, I'll make |
As has been mentioned by @hycdong , it's difficult to guarantee that |
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.
LGTM
feat: restrict the replication factor while creating app (XiaoMi#963) feat(manual_compaction): meta server support querying compaction status (XiaoMi#987) manual test
While creating app on the side of the meta server, currently the replication factor(i.e. replica count) is simply checked to just keep it positive. However, this is not enough since a wrong replication factor will result in later failures.
For example, as we've supported single-replica in #932, creating an app with 3 replicas by shell in a cluster that just includes a single node will be blocked for long since there're not enough nodes for the extra replicas.
Another example will be creating an app with a single replica in a cluster that includes 3 nodes. Later then we decide to upgrade this cluster by HA(i.e. high-availability, upgraded without stopping service of the cluster) to a higher version. The upgrade process will be blocked in the phase of moving the only replica of that app out to another node, since the node that deployed the only replica is stopped.
Also, If there are 2 alive replica servers (with 1 dead), creating an app with 3 replicas will end up with failure. Creating an app in a 3-node cluster with 5 replicas is nonsense. An excessive replication factor is unreasonable for a storage system, too.
Based on the problems illustrated above, I think the replica factor should be restricted further by the following rules.
Replication factor should not exceed the number of alive replica servers
It's obvious that there should be enough replica servers to put the replicas. Once there're extra replicas that cannot be placed anywhere, creating app will fail.
Replication factor has a minimum
Actually creating an app with a single replica in a 3-node cluster is eccentric. Therefore, A minimum value should be set for the replication factor. For example, the minimum for a 3-node cluster can be set to 3. This minimum replication factor will be a configuration for the cluster which is named as
min_allowed_replica_count
.Replication factor has a maximum
Similarly, an excessive replication factor is invalid for a cluster. It'll be restricted by another configuration, named
max_allowed_replica_count
. Any attempt that sets an app with a replication factor exceedingmax_allowed_replica_count
will be rejected. Typically, this value is set to 3, since 4 or more replicas are unusual.