1 package DBIx::Class::Storage::DBI::Replicated::Introduction;
5 DBIx::Class::Storage::DBI::Replicated::Introduction - Minimum Need to Know
9 This is an introductory document for L<DBIx::Class::Storage::Replication>.
11 This document is not an overview of what replication is or why you should be
12 using it. It is not a document explaing how to setup MySQL native replication
13 either. Copious external resources are avialable for both. This document
14 presumes you have the basics down.
18 L<DBIx::Class> supports a framework for using database replication. This system
19 is integrated completely, which means once it's setup you should be able to
20 automatically just start using a replication cluster without additional work or
21 changes to your code. Some caveats apply, primarily related to the proper use
22 of transactions (you are wrapping all your database modifying statements inside
23 a transaction, right ;) ) however in our experience properly written DBIC will
24 work transparently with Replicated storage.
26 Currently we have support for MySQL native replication, which is relatively
27 easy to install and configure. We also currently support single master to one
28 or more replicants (also called 'slaves' in some documentation). However the
29 framework is not specifically tied to the MySQL framework and supporting other
30 replication systems or topographies should be possible. Please bring your
31 patches and ideas to the #dbix-class IRC channel or the mailing list.
33 For an easy way to start playing with MySQL native replication, see:
36 If you are using this with a L<Catalyst> based appplication, you may also wish
37 to see more recent updates to L<Catalyst::Model::DBIC::Schema>, which has
38 support for replication configuration options as well.
40 =head1 REPLICATED STORAGE
42 By default, when you start L<DBIx::Class>, your Schema (L<DBIx::Class::Schema>)
43 is assigned a storage_type, which when fully connected will reflect your
44 underlying storage engine as defined by your choosen database driver. For
45 example, if you connect to a MySQL database, your storage_type will be
46 L<DBIx::Class::Storage::DBI::mysql> Your storage type class will contain
47 database specific code to help smooth over the differences between databases
48 and let L<DBIx::Class> do its thing.
50 If you want to use replication, you will override this setting so that the
51 replicated storage engine will 'wrap' your underlying storages and present to
52 the end programmer a unified interface. This wrapper storage class will
53 delegate method calls to either a master database or one or more replicated
54 databases based on if they are read only (by default sent to the replicants)
55 or write (reserved for the master). Additionally, the Replicated storage
56 will monitor the health of your replicants and automatically drop them should
57 one exceed configurable parameters. Later, it can automatically restore a
58 replicant when its health is restored.
60 This gives you a very robust system, since you can add or drop replicants
61 and DBIC will automatically adjust itself accordingly.
63 Additionally, if you need high data integrity, such as when you are executing
64 a transaction, replicated storage will automatically delegate all database
65 traffic to the master storage. There are several ways to enable this high
66 integrity mode, but wrapping your statements inside a transaction is the easy
69 =head1 PARTS OF REPLICATED STORAGE
71 A replicated storage contains several parts. First, there is the replicated
72 storage itself (L<DBIx::Class::Storage::DBI::Replicated>). A replicated storage
73 takes a pool of replicants (L<DBIx::Class::Storage::DBI::Replicated::Pool>)
74 and a software balancer (L<DBIx::Class::Storage::DBI::Replicated::Pool>). The
75 balancer does the job of splitting up all the read traffic amongst each
76 replicant in the Pool. Currently there are two types of balancers, a Random one
77 which chooses a Replicant in the Pool using a naive randomizer algorithm, and a
78 First replicant, which just uses the first one in the Pool (and obviously is
79 only of value when you have a single replicant).
81 =head1 REPLICATED STORAGE CONFIGURATION
83 All the parts of replication can be altered dynamically at runtime, which makes
84 it possibly to create a system that automatically scales under load by creating
85 more replicants as needed, perhaps using a cloud system such as Amazon EC2.
86 However, for common use you can setup your replicated storage to be enabled at
87 the time you connect the databases. The following is a breakdown of how you
88 may wish to do this. Again, if you are using L<Catalyst>, I strongly recommend
89 you use (or upgrade to) the latest L<Catalyst::Model::DBIC::Schema>, which makes
92 First, you need to connect your L<DBIx::Class::Schema>. Let's assume you have
93 such a schema called, "MyApp::Schema".
96 my $schema = MyApp::Schema->connect($dsn, $user, $pass);
98 Next, you need to set the storage_type.
100 $schema->storage_type(
101 ::DBI::Replicated' => {
102 balancer_type => '::Random',
104 auto_validate_every => 5,
105 master_read_weight => 1
113 Let's break down the settings. The method L<DBIx::Class::Schema/storage_type>
114 takes one mandatory parameter, a scalar value, and an option second value which
115 is a Hash Reference of configuration options for that storage. In this case,
116 we are setting the Replicated storage type using '::DBI::Replicated' as the
117 first value. You will only use a different value if you are subclassing the
118 replicated storage, so for now just copy that first parameter.
120 The second parameter contains a hash reference of stuff that gets passed to the
121 replicated storage. L<DBIx::Class::Storage::DBI::Replicated/balancer_type> is
122 the type of software load balancer you will use to split up traffic among all
123 your replicants. Right now we have two options, "::Random" and "::First". You
124 can review documentation for both at:
126 L<DBIx::Class::Storage::DBI::Replicated::Balancer::First>,
127 L<DBIx::Class::Storage::DBI::Replicated::Balancer::Random>.
129 In this case we will have three replicants, so the ::Random option is the only
130 one that makes sense.
132 'balancer_args' get passed to the balancer when it's instantiated. All
133 balancers have the 'auto_validate_every' option. This is the number of seconds
134 we allow to pass between validation checks on a load balanced replicant. So
135 the higher the number, the more possibility that your reads to the replicant
136 may be inconsistant with what's on the master. Setting this number too low
137 will result in increased database loads, so choose a number with care. Our
138 experience is that setting the number around 5 seconds results in a good
139 performance / integrity balance.
141 'master_read_weight' is an option associated with the ::Random balancer. It
142 allows you to let the master be read from. I usually leave this off (default
145 The 'pool_args' are configuration options associated with the replicant pool.
146 This object (L<DBIx::Class::Storage::DBI::Replicated::Pool>) manages all the
147 declared replicants. 'maximum_lag' is the number of seconds a replicant is
148 allowed to lag behind the master before being temporarily removed from the pool.
149 Keep in mind that the Balancer option 'auto_validate_every' determins how often
150 a replicant is tested against this condition, so the true possible lag can be
151 higher than the number you set. The default is zero.
153 No matter how low you set the maximum_lag or the auto_validate_every settings,
154 there is always the chance that your replicants will lag a bit behind the
155 master for the supported replication system built into MySQL. You can ensure
156 reliabily reads by using a transaction, which will force both read and write
157 activity to the master, however this will increase the load on your master
160 After you've configured the replicated storage, you need to add the connection
161 information for the replicants:
163 $schema->storage->connect_replicants(
164 [$dsn1, $user, $pass, \%opts],
165 [$dsn2, $user, $pass, \%opts],
166 [$dsn3, $user, $pass, \%opts],
169 These replicants should be configured as slaves to the master using the
170 instructions for MySQL native replication, or if you are just learning, you
171 will find L<MySQL::Sandbox> an easy way to set up a replication cluster.
173 And now your $schema object is properly configured! Enjoy!
177 John Napiorkowski <jjnapiork@cpan.org>
181 You may distribute this code under the same terms as Perl itself.