From 9618e63b5ff50613a23d3f0e628f0c2259dcea3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Wed, 5 Jul 2017 19:19:49 +0300 Subject: [PATCH] MXS-1310: Add deterministic conflict resolution The schemarouter can now resolve database mapping conflicts in a deterministic manner. This will fix the problem of central databases which are replicated shards being assigned in a non-deterministic manner. --- Documentation/Routers/SchemaRouter.md | 11 +++++++++++ server/modules/routing/schemarouter/schemarouter.c | 13 +++++++++++++ server/modules/routing/schemarouter/schemarouter.h | 7 ++++--- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/Documentation/Routers/SchemaRouter.md b/Documentation/Routers/SchemaRouter.md index d044b8ac6..0e3dc27c2 100644 --- a/Documentation/Routers/SchemaRouter.md +++ b/Documentation/Routers/SchemaRouter.md @@ -51,6 +51,17 @@ List of databases to ignore when checking for duplicate databases. Regular expression that is matched against database names when checking for duplicate databases. +### `preferred_server` + +The name of a server in MaxScale which will be used as the preferred server when +a database is found on more than one server. If a database exists on two +servers, of which neither is the server referred by this parameter, the server +that replies first will be assigned as the location of the database. + +This parameter allows deterministic conflict resolution when a sharded cluster +has a central database server and one or more sharded databases spread across +multiple servers which replicate from the central database server. + **Note:** As of version 2.1 of MaxScale, all of the router options can also be defined as parameters. The values defined in _router_options_ will have priority over the parameters. diff --git a/server/modules/routing/schemarouter/schemarouter.c b/server/modules/routing/schemarouter/schemarouter.c index 74972ed28..5c6a00de5 100644 --- a/server/modules/routing/schemarouter/schemarouter.c +++ b/server/modules/routing/schemarouter/schemarouter.c @@ -357,6 +357,17 @@ showdb_response_t parse_showdb_response(ROUTER_CLIENT_SES* rses, backend_ref_t* rses->rses_client_dcb->user, rses->rses_client_dcb->remote); } + else if (rses->router->preferred_server && + strcmp(target, rses->router->preferred_server->unique_name) == 0) + { + /** In conflict situations, use the preferred server */ + MXS_INFO("Forcing location of '%s' from '%s' to ''%s", + data, (char*)hashtable_fetch(rses->shardmap->hash, + data), target); + + hashtable_delete(rses->shardmap->hash, data); + hashtable_add(rses->shardmap->hash, data, target); + } } MXS_FREE(data); } @@ -651,6 +662,7 @@ MXS_MODULE* MXS_CREATE_MODULE() {"refresh_databases", MXS_MODULE_PARAM_BOOL, "true"}, {"refresh_interval", MXS_MODULE_PARAM_COUNT, DEFAULT_REFRESH_INTERVAL}, {"debug", MXS_MODULE_PARAM_BOOL, "false"}, + {"preferred_server", MXS_MODULE_PARAM_SERVER}, {MXS_END_MODULE_PARAMS} } }; @@ -719,6 +731,7 @@ static MXS_ROUTER* createInstance(SERVICE *service, char **options) router->schemarouter_config.max_sescmd_hist = config_get_integer(conf, "max_sescmd_history"); router->schemarouter_config.disable_sescmd_hist = config_get_bool(conf, "disable_sescmd_history"); router->schemarouter_config.debug = config_get_bool(conf, "debug"); + router->preferred_server = config_get_server(conf, "preferred_server"); if ((config_get_param(conf, "auth_all_servers")) == NULL) { diff --git a/server/modules/routing/schemarouter/schemarouter.h b/server/modules/routing/schemarouter/schemarouter.h index cb058b4f4..85acf5e87 100644 --- a/server/modules/routing/schemarouter/schemarouter.h +++ b/server/modules/routing/schemarouter/schemarouter.h @@ -365,14 +365,15 @@ typedef struct router_instance unsigned int bitvalue; /*< Required value of server->status */ ROUTER_STATS stats; /*< Statistics for this router */ struct router_instance* next; /*< Next router on the list */ - bool available_slaves; /*< The router has some slaves available */ + bool available_slaves; /*< The router has some slaves available */ HASHTABLE* ignored_dbs; /*< List of databases to ignore when the * database mapping finds multiple servers * with the same database */ - pcre2_code* ignore_regex; /*< Databases matching this regex will + pcre2_code* ignore_regex; /*< Databases matching this regex will * not cause the session to be terminated * if they are found on more than one server. */ - pcre2_match_data* ignore_match_data; + pcre2_match_data* ignore_match_data; + SERVER* preferred_server; /**< Server to prefer in conflict situations */ } ROUTER_INSTANCE;