helix-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "vlad.gm@gmail.com" <vlad...@gmail.com>
Subject Re: keeping the master node up during bootstrap
Date Fri, 04 Apr 2014 00:43:33 GMT
Hi Kanak,

I am using the SEMI_AUTO rebalancing mode. The code for setting up the
cluster is a bit of a handful, but I have copied it below (it is a command
line utility similar to helix_admin.sh).

My sequence of operations is as follows
setup_cluster
setup_model
setup_resource
add_node for all the nodes
add_nodes_to_resource (if there are no nodes, this calls rebalance,
otherwise it is an expansion, as can be seen in the corresponding function).

Regards,
Vlad

//// Some lines are missing, references to proprietary libraries and imports


/* Setup a Helix cluster for the KVStore */
public static void setupCluster() {
assert(cluster != null);
clusterSetup.addCluster(cluster, true);
}

/* Register the KVStore's state model for the KVStore cluster */
public static void setupStateModel() {
assert(cluster != null);
StateModelDefinition stateModel = KVHelixDefinitions.
defineStateModel();
clusterSetup.addStateModelDef(cluster,
KVHelixDefinitions.STATE_MODEL_NAME.stringify(),
stateModel);
}

/* Setup a new resource for a particular namespace */
private static void setupResource(int numPartitions) {
assert(cluster != null);
assert(resource != null);
assert(numPartitions > 0);

clusterSetup.addResourceToCluster(cluster,
resource,
numPartitions,
KVHelixDefinitions.STATE_MODEL_NAME.toString(),
RebalanceMode.SEMI_AUTO.toString());
}

/**
 *  Add a node to the cluster
 *  @param node the hostname of the new node
 *  @param sid  the ServerId of the new node
 *  */
private static void addNode(String node, String sid) {
assert(cluster != null);
assert(node != null);

clusterSetup.addInstanceToCluster(cluster,
KVHelixDefinitions.nodeToInstance(node));
clusterSetup.setConfig(ConfigScopeProperty.PARTICIPANT,
KVHelixDefinitions.clusterName()+','+
KVHelixDefinitions.nodeToInstance(node),
"ServerId="+sid);
}

/**
 * Replace a node with another in the cluster
 * @param nodes an array of node hostnames. We will be replacing
 * nodes[0] with nodes[1]
 */
private static void replaceNode(String[] nodes) {
assert(cluster != null);
assert(nodes != null);
assert(nodes.length >= 2);

admin.enableInstance(KVHelixDefinitions.clusterName(),
KVHelixDefinitions.nodeToInstance(nodes[0]), false);

clusterSetup.swapInstance(KVHelixDefinitions.clusterName(),
KVHelixDefinitions.nodeToInstance(nodes[0]),
KVHelixDefinitions.nodeToInstance(nodes[1]));
}

/**
 * Expand a resource over a few new nodes, moving as few
 * partitions as possible in order to rebalance the partitions
 * over the cluster.
 * @param nodes a list of new node hostnames
 */
private static void addNodesToResource(String[] nodes) {
assert(cluster != null);
assert(nodes != null);
assert(resource != null);

IdealState currentState = admin.getResourceIdealState(cluster, resource);

List<String> newNodes = new ArrayList<String>();
for (String node : nodes) {
admin.addInstanceTag(cluster,
KVHelixDefinitions.nodeToInstance(node),
resource);
newNodes.add(KVHelixDefinitions.nodeToInstance(node));
}

if (currentState.getRecord().getListFields().size() == 0) {
clusterSetup.rebalanceResource(cluster,
resource,
KVHelixDefinitions.NUM_REPLICAS);
} else {
clusterSetup.expandResource(cluster, resource);
}
}





On Thu, Apr 3, 2014 at 5:20 PM, Kanak Biscuitwala <kanak.b@hotmail.com>wrote:

> Hi Vlad,
>
> What rebalance mode are you using (FULL_AUTO, SEMI_AUTO, CUSTOMIZED, or
> USER_DEFINED)? Can you also paste the code you're using to set up your
> state model, if possible?
>
> Thanks,
> Kanak
>
> ________________________________
> > Date: Thu, 3 Apr 2014 16:57:59 -0700
> > Subject: keeping the master node up during bootstrap
> > From: vlad.gm@gmail.com
> > To: user@helix.apache.org
> >
> >
> > Dear all,
> >
> > I am trying to construct a state model with the following transition
> diagram:
> >
> > OFFLINE -> BOOTSTRAPPING <---> SLAVE <-----> MASTER
> > а а а а а<-----------------------------------
> >
> > That is, an offline mode can go into a bootstraping state, from the
> > bootstrap state it can go into a slave state,
> > from slave it can go from master, from master to slave and from slave
> > it can go offline.
> >
> > Assume that if I have a partition with two nodes pf1 and pf2 and a
> > partition partition_0 with the following ideal state:
> >
> > partition_0: pf2: MASTER pf1: SLAVE,
> >
> > and that currently pf1 is serving as a master. When pf2 boots, Helix
> > will issue, almost simultaneously, two commands:
> > for pf1: transition from MASTER to SLAVE
> > for pf2: transition from BOOTSTRAPPING to SLAVE
> >
> > My understanding is that this happens since Helix is trying to execute
> > as many commands in parallel and since the last state
> > has pf2 as master. However, the transition from BOOTSTRAPPING to SLAVE
> > for pf2 involves a long data copy step, so
> > I would like to keep pf1 as a master in the meanwhile. I tried
> > prioritizing the transition from BOOTSTRAPPING to SLAVE
> > over the transition from MASTER to SLAVE, however Helix still issues
> > them in parallel (as it should).
> >
> > I was wondering what my options would be in order to keep the master up
> > while the future master is bootstrapping. Could
> > a throttling in the number of transitions be enforced at partition
> > level? Could I somehow specify that a state with a slave
> > and a bootstrapping node is undesirable?
> >
> > As a note, I have also looked at the RSync-replicateed filesystem
> > example. The reason for not using the OfflineOnline or the
> > MasterSlave model in my application is that I would like the
> > bootstrapping node to receive updates from clients, i.e. be visible
> > during the bootstrap. For this reason, I am introducing the new
> > BOOTSTRAPPING phase in-between OFFLINE and SLAVE.
> >
> > Regards,
> > Vlad
> >
> >
> > PS: The state model definition is as follows:
> >
> > builder.addState(MASTER, 1); а а а а а а а а а а а а а а а а а
а а а а
> > а а а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а
> >
> > а а а а а а builder.addState(SLAVE, 2);а а а а а а а а а а а а
а а а а
> > а а а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а
> >
> > а а а а а а builder.addState(BOOTSTRAP, 3);а а а а а а а а а а а
а а а
> > а а а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а
> >
> > а а а а а а builder.addState(OFFLINE); а а а а а а а а а а а а
а а а а
> > а а а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а
> >
> > а а а а а а builder.addState(DROPPED); а а а а а а а а а а а а
а а а а
> > а а а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а
> >
> > а а а а а а // Set the initial state when the node startsа а а а а а
а
> > а а а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а
> >
> > а а а а а а builder.initialState(OFFLINE); а а а а а а а а а а а
а а а
> > а а а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а
> >
> > аа а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а
> >
> > а а а а а а // Add transitions between the states. а а а а а а а а
а а
> > а а а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а
> >
> > а а а а а а builder.addTransition(OFFLINE, BOOTSTRAP, 4);а а а а а а
а
> > а а а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а
> >
> > а а а а а а builder.addTransition(BOOTSTRAP, SLAVE, 5);а а а а а а а
а
> > а а а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а
> >
> > а а а а а а builder.addTransition(SLAVE, MASTER, 6); а а а а а а а
а а
> > а а а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а
> >
> > а а а а а а builder.addTransition(MASTER, SLAVE, 3); а а а а а а а
а а
> > а а а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а
> >
> > а а а а а а builder.addTransition(SLAVE, OFFLINE, 2);а а а а а а а
а а
> > а а а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а
> >
> > а а а а а а builder.addTransition(OFFLINE, DROPPED, 1);а а а а а а а
а
> > а а а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а
> >
> > аа а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а
> >
> > а а а а а а // set constraints on states.а а а а а а а а а а а
а а а а
> > а а а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а
> >
> > а а а а а а // static constraint а а а а а а а а а а а а а а
а а а а а
> > а а а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а
> >
> > а а а а а а builder.upperBound(MASTER, 1); а а а а а а а а а а а
а а а
> > а а а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а
> >
> > а а а а а а // dynamic constraint, R means it should be derived based
> > on the replication а а а а а а а а а а а а а а а а а а а а а
а а а а а
> > а а а а а а а а а а а а а а а а а а а
> >
> > а а а а а а // factor. а а а а а а а а а а а а а а а а а
а а а а а а а
> > а а а а а а а а а а а а а а а а а а а а а а а а а а а
а а а а а а а а а
> > а а а а а а а а а а а а а а а а а а
> >
> > а а а а а а builder.dynamicUpperBound(SLAVE, "R");а а а а а а а а
а а а
>

Mime
View raw message