On Apr 30, 2009, at 6:52 PM, MARK CALLAGHAN wrote:
On Thu, Apr 30, 2009 at 6:35 PM, Clint Byrum <[email protected]> wrote:
On Apr 30, 2009, at 5:43 PM, MARK CALLAGHAN wrote:
Help me to understand what it is your proposing here..
* Connect to a server with a hint that you're readonly, and that
the last
change you made to the DB was at global transaction ID X
* Server informs you of its highest global transaction ID and you
decide
whether or not to stay connected?
This sounds like a job for a proxy. It would be *awesome* if this
were
always in the protocol, and the proxy would just improve things by
helping
to find an acceptable server w/o requiring the user to connect over
and
over.
Once that is working, adding additional constraints based on QoS and
server health should be easy.
I want a client to connect to a db server name, have all writes get
done on primary and have queries redirected to a slave when possible
where redirected queries are guaranteed to see any changes that client
committed on a primary.
I wrote my response to the proxying part below first, but then I re-
read this paragraph above, and recalled a problem I've had in the past.
"Have queries redirected to a slave when possible"
We had a system at (little, tiny) Adicio, much like, I'm sure, other
places have. The user's session gets marked as "dirty" when writes
happen. Basically for about 5 minutes after they change anything, they
are on the master. Then after 5 minutes, the slaves that are within 5
minutes are used.
The problem arises where the master gets *really* busy with writes,
and so the slaves get far, far, behind briefly. Our system has a
quorum that basically says "if less than half of the slaves are within
5 minutes, just send queries to them all." So in these instances,
users start seeing old data and getting confused until they change
things (at which point, they start seeing a lot of spinning
browsers). ;) We abandoned this mode of operation in favor of finding
instances where reads can always go to the slaves, or be pushed out to
memcached/memcachedb, and setting business expectations for realtime
to 'near-realtime'.
However I've heard of other systems that handle things differently.
When the slaves get too far behind, the reads *all* go to the master.
cowsay FAIL.
It strikes me that when one tries to be opportunistic about load
distribution, they might as well not do it. The time we really need
more capacity is when we're stressed. So it makes me think that a big
focus should be on making replication as fast and reliable as
possible. This, to me, means being able to break it up into smaller
pieces and not have it be single threaded or even single hosted
(slaves shard while master's don't.. crazy? well.. thats kind of what
memcached does).
I don't want the proxy to be a separate set of processes as I already
have enough of those to manage and failure of standalone proxy
processes would not be good for a highly available database service.
I think from a latency and complexity standpoint the server that you
sent the request to should get that result for you. If it works akin
to HTTP's 301/302, that might mean making a new connection or (better)
grabbing one out of a pool of connections.
This whole issue reminds me of mod_backhand. If you don't recall.. it
was (I say was because I don't think people use it anymore, but maybe
I'm wrong.. ;) a module for apache that would broadcast host stats and
then redirect, or proxy requests to other nodes based on those
stats.It was *really* effective at keeping resource utilization
distributed. This is where redirects would actually be handy, because
I know for us, mod_backhand failed us when we had too many individual
users accessing one resource, causing us to have to keep a lot of
proxy connections open on the mod_backhand machine itself. When we put
a load balancer in front of that, there was no more need for
mod_backhand.
Anyway, memcached rather than broadcast, wouldn't be a bad idea to
publish each slave's transaction ID.
I could totally see the replication slave process simply setting a
memcache item, something like 'transid_slave1', every time it commits
a transaction to that slave. The client libraries could then just keep
reasonably good track of that value and send queries directly without
the server protocol doing any more than giving back that transaction
id whenever it changes. This is where ranged key fetching would be
nice in memcached.. as you could just do something like memcachedb's
rget..
rget transid_ some_sane_endkey 0 0 100
Which would get up to 100 of them quickly and you could then pick the
best one. You could keep that list cached locally right up until your
thread changes its transactionid. Connections would still have to be
checked and discarded in case the information was inaccurate, or maybe
not, but either way, its basically just a hint as to which servers can
serve your request.
Maybe the master could manage all of this.. however.. I get a little
hesitant when we ask masters to keep track of slaves, knowing what a
mess server-id has been in the past. Seems much better to just let the
slaves keep track of themselves and make that information highly
available.
Still I see the point that if you let the users get away with ignoring
those hints, you're right back at "damnit use the slaves!". So, if all
of the logic above happens in a plugin in the master, the only thing
really required in the protocol is global transaction ID, and the
redirect response. However, I'm still troubled by "opportunistic load
distribution".. but .. my world is tiny, so maybe I just don't get
it. ;)
_______________________________________________
Mailing list: https://launchpad.net/~drizzle-discuss
Post to : [email protected]
Unsubscribe : https://launchpad.net/~drizzle-discuss
More help : https://help.launchpad.net/ListHelp