[Dbix-class] DBIx::Class::Storage::DBI::Replicated - read from
master
Bill Moseley
moseley at hank.org
Thu Jun 10 04:30:48 GMT 2010
Hi John,
On Wed, Jun 9, 2010 at 1:15 PM, John Napiorkowski <jjn1056 at yahoo.com> wrote:
>
> Interesting idea. The way DBIC Replication works is that by default when=
a
> slave falls too far behind it gets dropped from the pool until it catches
> up.
IIUC, Slony does have a way to report slave lag, but I discussed it briefly
with our DBA and for the existing (non-DBIC dbi-based) master/slave code it
was decided to just use a hard-coded per-user delay. A user writes to the
db and is pegged to master for some period of time. There's a separate
process that removes slaves if the lag gets too big.
I would be interested in trying to add lag support, though.
Since DBIx::Class::Storage::DBI::Pg doesn't have methods to report the lag,
I suppose I'd need to create a subclass. How do I
subclass DBIx::Class::Storage::DBI::Pg? Is there another way than using a
new dsn (e.g. dbi:PgReplicated) to tell DBIC which DBIC driver to use?
(Just to be clear -- the lag measurement is to determine if a slave should
be pulled out of the balancer pool, correct? My need to force all selects
to the master for some period of time after a write to the master is a
separate issue.)
I might want to investigate using other means to report the slave lag so
that not every process on every web server is querying this info directly
from each slave -- e.g. maintain a lag list in memcached.
We have also had some talk about using slave load when selecting a slave.
And another idea we kicked around was to list only one slave and use
Skype's pgbouncer for connection pooling and selection.
> Anything wrapped inside a transaction automatically does both reads and
> writes to the master. I didn't think about a strategy where after an ins=
ert
> access to slaves would be temporarily suspended. Seems a bit heavy handed
> to me, but I guess that could be grafted in.
>
In some cases it's possible that a (web) request may include multiple
transactions (via txn_do) followed by a select or two that needs the
updated data so I don't think we can expect the slaves to be synced that
fast. Yes, it's a bit heavy handed to force all selects to the master after
a write. Much of the app is accessed via and API so it's quite possible
that a read will happen right after a write and expect to fetch current
data. So, I'm not sure there's much option other than waiting until the
slave have synced.
I guess probably should figure out which queries can always go to the slaves
and which selects need to read from the master after any writes, but that
would be a bit of work for an existing app. So, it's easier to just force
all.
> >The existing (non-DBIC) application will set a flag in memcached when a
> write happens. This is keyed by user id. And each request memcached is
> checked to see if the current user needs to read from the master. I'm
> looking at a way to duplicate that behavior with ::Replicated.
> >
>
> Well, you can flip replication off on a per query basis:
>
> my $RS =3D $schema->resultset('Source')->search(undef,
> {force_pool=3D>'master'});
>
> I'd probably hack into my Catalyst model to add that bit to search
> resultset automatically.
>
By overriding (or "after resultset") in the ResultSet base class?
If I want to do that for an entire life of a request for every query is
there any reason why setting $storage->set_reliable_storage would not
accomplish the same thing? (Oh, you comment on that below..)
> Seems there's a bit more here than you need. Like I mentioned above you
> got that force_pool=3D>'master' thing. Honestly I'd probably start by ad=
ding
> that force_pool stuff to my controllers and make sure it works and then b=
ack
> it into the model. I'm not so excited by the "set_reliable_storage" and =
its
> counterpart since the way it flips state is a bit shaky in my mind.
Yes, that was one of my first questions when looking at the docs. There's
an example of cloning the schema and setting it. I was wondering why there
was a need to clone if I explicitly force it with set_reliable_storage or
set_balanced_storage.
> That was my first attempt at giving the user this kind of control and I
> left it in for backcompat. You should also take a look at the test for
> replication (in the t directory) and make heavy used of DBIC_TRACE=3D1 to=
see
> what is going on. I override this output so you can see what slaves (or =
the
> master) are picking up which bit.
>
Oh ya, I was concerned about that. I spent a bit if time checking the
behavior with DBIC_TRACE and I do see the intended behavior. My concern was
with a mix of transactions the code might be confused about what state it
was in (reliable or balanced). But, the behavior seems to work as expected
in my tests.
But, I could rewrite to check a flag added to the schema and add force_pool
=3D> 'master' to every resultset.
Thanks very much for the comments.
-- =
Bill Moseley
moseley at hank.org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.scsys.co.uk/pipermail/dbix-class/attachments/20100609/ce6=
6d4b8/attachment.htm
More information about the DBIx-Class
mailing list