{"id":7861,"date":"2018-05-03T12:56:46","date_gmt":"2018-05-03T10:56:46","guid":{"rendered":"http:\/\/code.openark.org\/blog\/?p=7861"},"modified":"2018-05-22T10:44:42","modified_gmt":"2018-05-22T08:44:42","slug":"mysql-master-discovery-methods-part-1-dns","status":"publish","type":"post","link":"https:\/\/code.openark.org\/blog\/mysql\/mysql-master-discovery-methods-part-1-dns","title":{"rendered":"MySQL master discovery methods, part 1: DNS"},"content":{"rendered":"<p>This is the first in a series of posts reviewing methods for MySQL master discovery: the means by which an application connects to the master of a replication tree. Moreover, the means by which, upon master failover, it identifies and connects to the newly promoted master.<\/p>\n<p>These posts are not concerned with the manner by which the replication failure detection and recovery take place. I will share <code>orchestrator<\/code> specific configuration\/advice, and point out where cross DC <code>orchestrator\/raft<\/code> setup plays part in discovery itself, but for the most part any recovery tool such as <code>MHA<\/code>, <code>replication-manager<\/code>, <code>severalnines<\/code> or other, is applicable.<\/p>\n<p>We discuss asynchronous (or semi-synchronous) replication, a classic single-master-multiple-replicas setup. A later post will briefly discuss synchronous replication (Galera\/XtraDB Cluster\/InnoDB Cluster).<\/p>\n<h3>Master discovery via DNS<\/h3>\n<p>In DNS master discovery applications connect to the master via a name that gets resolved to the master&#8217;s box. By way of example, apps would target the masters of different clusters by connecting to <code>cluster1-writer.example.net<\/code>, <code>cluster2-writer.example.net<\/code>, etc. It is up for the DNS to resolve those names to IPs.<\/p>\n<p><!--more--><\/p>\n<p>Issues for concern are:<\/p>\n<ul>\n<li>You will likely have multiple DNS servers. How many? In which data centers \/ availability zones?<\/li>\n<li>What is your method for distributing\/deploying a name change to all your DNS servers?<\/li>\n<li>DNS will indicate a <code>TTL<\/code> (Time To Live) such that clients can cache the IP associated with a name for a given number of seconds. What is that <code>TTL<\/code>?<\/li>\n<\/ul>\n<p>As long as things are stable and going well, discovery via DNS makes sense. Trouble begins when the master fails over. Assume <code>M<\/code> used to be the master, but got demoted. Assume <code>R<\/code> used to be a replica, that got promoted and is now effectively the master of the topology.<\/p>\n<p>Our failover solution has promoted <code>R<\/code>, and now needs to somehow apply the change, such that the apps connect to <code>R<\/code> instead of <code>M<\/code>. Some notes:<\/p>\n<ul>\n<li>The apps need not change configuration. They should still connect to <code>cluster1-writer.example.net<\/code>, <code>cluster2-writer.example.net<\/code>, etc.<\/li>\n<li>Our tool instructs DNS servers to make the change.<\/li>\n<li>Clients will still resolve to old IP based on <code>TTL<\/code>.<\/li>\n<\/ul>\n<h3>A non planned failover illustration #1<\/h3>\n<p>Master <code>M<\/code> dies. <code>R<\/code> gets promoted. Our tool instructs all DNS servers on all DCs to update the IP address.<\/p>\n<p>Say <code>TTL<\/code> is <code>60<\/code> seconds. Say update to all DNS servers takes <code>10<\/code> seconds. We will have between <code>10<\/code> and <code>70<\/code> seconds until all clients connect to the new master <code>R<\/code>.<\/p>\n<p>During that time they will continue to attempt connecting to <code>M<\/code>. Since <code>M<\/code> is dead, those attempts will fail (thankfully).<\/p>\n<h3>A non planned failover illustration #2<\/h3>\n<p>Master <code>M<\/code> gets network isolated for <code>30<\/code> seconds, during which time we failover. <code>R<\/code> gets promoted. Our tool instructs all DNS servers on all DCs to update the IP address.<\/p>\n<p>Again, assume <code>TTL<\/code> is <code>60<\/code> seconds. As before, it will take between <code>10<\/code> and <code>70<\/code> seconds for clients to learn of the new IP.<\/p>\n<p>Clients who will require between <code>40<\/code> and <code>70<\/code> seconds to learn of the new IP will, however, hit an unfortunate scenario: the old master <code>M<\/code> reappears on the grid. Those clients will successfully reconnect to <code>M<\/code> and issue writes, leading to data loss (writes to <code>M<\/code> no longer replicate anywhere).<\/p>\n<h3>Planned failover illustration<\/h3>\n<p>We wish to replace the master, for maintenance reasons. We successfully and gracefully promote <code>R<\/code>. We need to change DNS records. Since this is a planned failover, we set the old master to <code>read_only=1<\/code>, or even better, we network isolated it.<\/p>\n<p>And still our clients take <code>10<\/code> to <code>70<\/code> seconds to recognize the new master.<\/p>\n<h3>Discussion<\/h3>\n<p>The above numbers are just illustrative. Perhaps DNS deployment is quicker than <code>10<\/code> seconds. You should do your own math.<\/p>\n<p><code>TTL<\/code> is a compromise which you can tune. Setting lower <code>TTL<\/code> will mitigate the problem, but will cause more hits on the DNS servers.<\/p>\n<p>For planned takeover we can first deploy a change to the <code>TTL<\/code>, to, say, <code>2sec<\/code>, wait <code>60sec<\/code>, then deploy the IP change, then restore <code>TTL<\/code> to <code>60<\/code>.<\/p>\n<p>You may choose to restart apps upon DNS deployment. This emulates apps&#8217; awareness of the change.<\/p>\n<h3>Sample orchestrator configuration<\/h3>\n<p><code>orchestrator<\/code> configuration would look like this:<\/p>\n<pre><code class=\"json\">  \"ApplyMySQLPromotionAfterMasterFailover\": true,\n  \"PostMasterFailoverProcesses\": [\n    \"\/do\/what\/you\/gotta\/do to apply dns change for {failureClusterAlias}-writer.example.net to {successorHost}\"\n  ],  \n<\/code><\/pre>\n<p>In the above:<\/p>\n<ul>\n<li><code>ApplyMySQLPromotionAfterMasterFailover<\/code> instructs <code>orchestrator<\/code> to <code>set read_only=0; reset slave all<\/code> on promoted server.<\/li>\n<li><code>PostMasterFailoverProcesses<\/code> really depends on your setup. But <code>orchestrator<\/code> will supply with hints to your scripts: identity of cluster, identity of successor.<\/li>\n<\/ul>\n<p>See <a href=\"https:\/\/github.com\/github\/orchestrator\/blob\/master\/docs\/configuration.md\">orchestrator configuration<\/a> documentation.<\/p>\n<h3>All posts in this series<\/h3>\n<ul>\n<li><a href=\"http:\/\/code.openark.org\/blog\/mysql\/mysql-master-discovery-methods-part-1-dns\">MySQL master discovery methods, part 1: DNS<\/a><\/li>\n<li><a href=\"http:\/\/code.openark.org\/blog\/mysql\/mysql-master-discovery-methods-part-2-vip-dns\">MySQL master discovery methods, part 2: VIP &amp; DNS<\/a><\/li>\n<li><a href=\"http:\/\/code.openark.org\/blog\/mysql\/mysql-master-discovery-methods-part-3-app-service-discovery\">MySQL master discovery methods, part 3: app &amp; service discovery<\/a><\/li>\n<li><a href=\"http:\/\/code.openark.org\/blog\/mysql\/mysql-master-discovery-methods-part-4-proxy-heuristics\">MySQL master discovery methods, part 4: Proxy heuristics<\/a><\/li>\n<li><a href=\"http:\/\/code.openark.org\/blog\/mysql\/mysql-master-discovery-methods-part-5-service-discovery-proxy\">MySQL master discovery methods, part 5: Service discovery &amp; Proxy<\/a><\/li>\n<li><a href=\"http:\/\/code.openark.org\/blog\/mysql\/mysql-master-discovery-methods-part-6-other-methods\">MySQL master discovery methods, part 6: other methods<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>This is the first in a series of posts reviewing methods for MySQL master discovery: the means by which an application connects to the master of a replication tree. Moreover, the means by which, upon master failover, it identifies and connects to the newly promoted master. These posts are not concerned with the manner by [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"enabled":false},"version":2}},"categories":[5],"tags":[62,108,8],"class_list":["post-7861","post","type-post","status-publish","format-standard","hentry","category-mysql","tag-high-availability","tag-orchestrator","tag-replication"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2bZZp-22N","_links":{"self":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/7861","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/comments?post=7861"}],"version-history":[{"count":8,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/7861\/revisions"}],"predecessor-version":[{"id":7908,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/7861\/revisions\/7908"}],"wp:attachment":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/media?parent=7861"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/categories?post=7861"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/tags?post=7861"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}