From 2b5ec8f162342185123b26896630ed7e15bd8a9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Fri, 16 Dec 2016 19:33:05 +0200 Subject: [PATCH] Pick node with index of 0 as the Galera master When a Galera cluster loses a member, it will recalculate the wsrep_local_index values. As the index is zero-based, we can be certain that in a valid cluster there will always be a node with an index of 0. If the galeramon can't find a node with an index of 0, it means that either the cluster hasn't stabilized and there's a pending recalculation of the index or that there's no connectivity between MaxScale and the node with the index value 0. With this change and default settings, active-active MaxScale setups with Galera clusters should always choose the same node as the master. --- Documentation/Monitors/Galera-Monitor.md | 14 ++++++ .../MaxScale-2.1.0-Release-Notes.md | 9 ++++ server/modules/monitor/galeramon/galeramon.c | 46 ++++++++++++------- server/modules/monitor/galeramon/galeramon.h | 2 + 4 files changed, 55 insertions(+), 16 deletions(-) diff --git a/Documentation/Monitors/Galera-Monitor.md b/Documentation/Monitors/Galera-Monitor.md index d4d65488e..dbaa73873 100644 --- a/Documentation/Monitors/Galera-Monitor.md +++ b/Documentation/Monitors/Galera-Monitor.md @@ -62,6 +62,20 @@ Enable interaction with server priorities. This will allow the monitor to determ use_priority=true ``` +### `root_node_as_master` + +This option controls whether the write master Galera node requires a +_wsrep_local_index_ value of 0. This option is enabled by default and was +introduced in MaxScale 2.1.0. + +A Galera cluster will always have a node which has a _wsrep_local_index_ value +of 0. Based on this information, multiple MaxScale instances can always pick the +same node for writes. + +If the `root_node_as_master` option is disabled for galeramon, the node with the +lowest index will always be chosen as the master. If it is enabled, only the +node with a a _wsrep_local_index_ value of 0 can be chosed as the master. + ## Interaction with Server Priorities If the `use_priority` option is set and a server is configured with the diff --git a/Documentation/Release-Notes/MaxScale-2.1.0-Release-Notes.md b/Documentation/Release-Notes/MaxScale-2.1.0-Release-Notes.md index 8cfc18482..45ae45fdd 100644 --- a/Documentation/Release-Notes/MaxScale-2.1.0-Release-Notes.md +++ b/Documentation/Release-Notes/MaxScale-2.1.0-Release-Notes.md @@ -94,6 +94,15 @@ In 2.1.0, each listener has its own sub-directory in the service cache directory. The old caches in `/var/cache/maxscale` will need to be manually removed if they are no longer used by older versions of MaxScale. +### Galeramon Monitoring Algorithm + +The galeramon monitor will only choose nodes with a _wsrep_local_index_ +value of 0 as the master. This allows multiple MaxScales to always choose +the same node as the write master node for the cluster. The old behavior +can be taken into use by disabling the new `root_node_as_master` option. + +For more details, read the [Galeramon documentation](../Monitors/Galera-Monitor.md). + ## New Features ### Dynamic server configuration diff --git a/server/modules/monitor/galeramon/galeramon.c b/server/modules/monitor/galeramon/galeramon.c index c62c01c06..169161de1 100644 --- a/server/modules/monitor/galeramon/galeramon.c +++ b/server/modules/monitor/galeramon/galeramon.c @@ -145,6 +145,7 @@ startMonitor(MONITOR *mon, const CONFIG_PARAMETER *params) handle->disableMasterRoleSetting = 0; handle->master = NULL; handle->script = NULL; + handle->root_node_as_master = true; handle->use_priority = false; memset(handle->events, false, sizeof(handle->events)); spinlock_init(&handle->lock); @@ -165,6 +166,10 @@ startMonitor(MONITOR *mon, const CONFIG_PARAMETER *params) { handle->disableMasterRoleSetting = config_truth_value(params->value); } + else if (!strcmp(params->name, "root_node_as_master")) + { + handle->root_node_as_master = config_truth_value(params->value); + } else if (!strcmp(params->name, "use_priority")) { handle->use_priority = config_truth_value(params->value); @@ -548,29 +553,27 @@ monitorMain(void *arg) const int repl_bits = (SERVER_SLAVE | SERVER_MASTER | SERVER_MASTER_STICKINESS); if (SERVER_IS_JOINED(ptr->server)) { - if (handle->master) + if (ptr != handle->master) { - if (ptr != handle->master) + /* set the Slave role and clear master stickiness */ + server_clear_set_status(ptr->server, repl_bits, SERVER_SLAVE); + } + else + { + if (candidate_master && + handle->master->server->node_id != candidate_master->server->node_id) { - /* set the Slave role and clear master stickiness */ - server_clear_set_status(ptr->server, repl_bits, SERVER_SLAVE); + /* set master role and master stickiness */ + server_clear_set_status(ptr->server, repl_bits, + (SERVER_MASTER | SERVER_MASTER_STICKINESS)); } else { - if (candidate_master && - handle->master->server->node_id != candidate_master->server->node_id) - { - /* set master role and master stickiness */ - server_clear_set_status(ptr->server, repl_bits, - (SERVER_MASTER | SERVER_MASTER_STICKINESS)); - } - else - { - /* set master role and clear master stickiness */ - server_clear_set_status(ptr->server, repl_bits, SERVER_MASTER); - } + /* set master role and clear master stickiness */ + server_clear_set_status(ptr->server, repl_bits, SERVER_MASTER); } } + is_cluster++; } else @@ -674,6 +677,17 @@ static MONITOR_SERVERS *get_candidate_master(MONITOR* mon) moitor_servers = moitor_servers->next; } + if (!handle->use_priority && !handle->disableMasterFailback && + handle->root_node_as_master && min_id > 0) + { + /** The monitor couldn't find the node with wsrep_local_index of 0. + * This means that we can't connect to the root node of the cluster. + * + * If the node is down, the cluster would recalculate the index values + * and we would find it. In this case, we just can't connect to it. */ + candidate_master = NULL; + } + return candidate_master; } diff --git a/server/modules/monitor/galeramon/galeramon.h b/server/modules/monitor/galeramon/galeramon.h index 967a2e52c..768d7e216 100644 --- a/server/modules/monitor/galeramon/galeramon.h +++ b/server/modules/monitor/galeramon/galeramon.h @@ -58,6 +58,8 @@ typedef struct int disableMasterRoleSetting; /**< Monitor flag to disable setting master role */ MONITOR_SERVERS *master; /**< Master server for MySQL Master/Slave replication */ char* script; + bool root_node_as_master; /**< Whether we require that the Master should + * have a wsrep_local_index of 0 */ bool use_priority; /*< Use server priorities */ bool events[MAX_MONITOR_EVENT]; /*< enabled events */ } GALERA_MONITOR;