ar_mysql_flexmaster 0.0.6 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # ArMysqlFlexmaster
2
2
 
3
- TODO: Write a gem description
3
+ Mysql Flexmaster is an adapter for ActiveRecord that allows an application node to choose
4
+ among a list of potential masters at runtime. It trades some properties of a more traditional
5
+ HA solution (load balancing, middleware) for simplicity of operation.
4
6
 
5
7
  ## Installation
6
8
 
@@ -16,9 +18,85 @@ Or install it yourself as:
16
18
 
17
19
  $ gem install ar_mysql_flexmaster
18
20
 
19
- ## Usage
21
+ ## Configuration:
20
22
 
21
- TODO: Write usage instructions here
23
+ database.yml contains a list of hosts -- all of them potential masters, all of them potential replicas.
24
+ It should look like this:
25
+
26
+ ```
27
+ production:
28
+ adapter: mysql_flexmaster
29
+ username: flex
30
+ hosts: ["db01:3306", "db02:3306"]
31
+
32
+ production_slave:
33
+ adapter: mysql_flexmaster
34
+ username: flex
35
+ slave: true
36
+ hosts: ["db01:3306", "db02:3306"]
37
+ ```
38
+
39
+
40
+ ## How it works
41
+
42
+ ### Overview
43
+
44
+ The mysql "READ_ONLY" flag is used to indicate a current master amongst the cluster. Only one member
45
+ of the replication chain may be read-write at any given time. The application picks in run time, based
46
+ on the read_only flag, which host is correct.
47
+
48
+ ### boot time
49
+
50
+ Your activerecord application will pick a correct mysql host for the given configuration by probing hosts until
51
+ it finds the correct host.
52
+
53
+ For master configurations (slave: true is not specified):
54
+
55
+ The application will probe each host in turn, and find the mysql candidate among these nodes
56
+ that is read-write (SET GLOBAL READ_ONLY=0). If it finds more than one node where READ_ONLY == 0, it will
57
+ abort.
58
+
59
+ For slave configurations (slave: true specified):
60
+
61
+ The application will choose a replica at random from amongst those where READ_ONLY == 1.
62
+
63
+ ### run time
64
+
65
+ Before each transaction is begun on the master, the application checks the status of the READ_ONLY variable.
66
+ If READ_ONLY == 0, it will proceed with the transaction as normal. If READ_ONLY == 1, it will drop the current
67
+ connection and re-poll the cluster for the current master, sleeping up to a default of 5 seconds to wait for
68
+ the new master to be promoted. When it finds the new master, it will begin the transaction there.
69
+
70
+ ### promoting a new master
71
+
72
+ *The bin/master_cut script in this project will perform steps 3-5 for you.*
73
+
74
+ The process of promoting a new master to head the cluster should be as follows:
75
+
76
+ 1. identify a new candidate master
77
+ 1. ensure that all other replicas in the cluster are chained off the candidate master; you want the
78
+ chain to look like this:
79
+
80
+ ```
81
+ <existing master> -> <candidate master> -> <other replicas>
82
+ -> <other replicas>
83
+
84
+ ```
85
+
86
+ 1. set the old master to READ_ONLY = 1
87
+ 1. record the master-bin-log position of the candidate master (if you want to re-use the old master)
88
+ 1. set the new master to READ_ONLY = 0
89
+
90
+ The application will eventually shift slave traffic to another node in the cluster, if available, and
91
+ will drop their connection to the old master whenever a transaction is attempted, or after a certain
92
+ number of queries.
93
+
94
+
95
+ ### caveats, gotchas
96
+
97
+ - Any explicit ( BEGIN ... END ) transaction that are in-flight when the old master goes READ_ONLY
98
+ will crash. In theory there's a workaround for this problem, in pratice it's rather unwieldy due
99
+ to a lack of shared global variables in mysql.
22
100
 
23
101
  ## Contributing
24
102
 
@@ -12,7 +12,7 @@ Gem::Specification.new do |gem|
12
12
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
13
13
  gem.name = "ar_mysql_flexmaster"
14
14
  gem.require_paths = ["lib"]
15
- gem.version = "0.0.6"
15
+ gem.version = "0.0.8"
16
16
 
17
17
  gem.add_runtime_dependency("mysql2")
18
18
  gem.add_runtime_dependency("activerecord")
@@ -1,3 +1,4 @@
1
+ require 'active_record'
1
2
  require 'active_record/connection_adapters/mysql2_adapter'
2
3
  require 'timeout'
3
4
 
@@ -1,2 +1,3 @@
1
+ require 'active_record/connection_adapters/mysql_flexmaster_adapter'
1
2
  module ArMysqlFlexmaster
2
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ar_mysql_flexmaster
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.8
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-17 00:00:00.000000000 Z
12
+ date: 2013-02-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mysql2
@@ -137,7 +137,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
137
137
  version: '0'
138
138
  segments:
139
139
  - 0
140
- hash: -3392143039168594248
140
+ hash: 1068549902361046667
141
141
  required_rubygems_version: !ruby/object:Gem::Requirement
142
142
  none: false
143
143
  requirements:
@@ -146,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
146
  version: '0'
147
147
  segments:
148
148
  - 0
149
- hash: -3392143039168594248
149
+ hash: 1068549902361046667
150
150
  requirements: []
151
151
  rubyforge_project:
152
152
  rubygems_version: 1.8.24