I really like the idea of having a "SUBSCRIBE" command that would allow a
client to subscribe to receive a
notification of either the next or all changes for a particular key. That
seems general enough and since a
common use case of Redis is as a holder of system state it makes sense that
system components (aka, clients)
shouldn't have to poll the server.
If this is acceptable to the developers, I'm more than willing to do the
work and provide a patch.
--
You received this message because you are listed in the owner
or CC fields of this issue, or because you starred this issue.
You may adjust your issue notification preferences at:
http://code.google.com/hosting/settings
Hello mrevelle,
I'm currently considering how to implement this. The feature can't be added
in 1.1 as
we already have too fresh meat and I really want 1.1 to be as stable as 1.0
was so
there is a lot to test already. But I could like to implement this feature
in a
cooperative and more general way. Something like this:
A client can issue the following command:
SLEEP foobar
(foobar does not have to be a key, can be any kind of string without spaces
and
newlines)
this client will block until some other client will issue the following:
AWAKE foobar
Multiple clients can sleep for the same token, and AWAKE will aware all the
clients in
a single operation. A client can sleep only for a single token.
This way the implementation will be much simpler, Redis will be faster, and
the user
will have full control, that is, sometimes it is needed to change the keys
without for
the "workers" to start processing items, because for instance there is a
script to
sanitize the DB running.
It seems like the best of all the worlds, please if you think my design is
flawed don't
esitate to prove me wrong.
Cheers,
Salvatore
Salvatore, you always come up with approaches i've never seen before. :)
Which is
good.
Obviously, there a race condition with multiple clients doing:
AWAKE foobar
RPOP list-key
What's your opinion on this?
I believe it looks like http://en.wikipedia.org/wiki/Thundering_herd_problem
Hello temotor,
yeah I was thinking about this issue when writing this proposal. Basically
in order to
be general this implementation is no longer atomic, *even* when a single
client
waits. This is the "flow of time" when implementing blocking LPOP using
SLEEP and
AWAKE.
t1) client 1 SLEEPs for foo_token
t2) client 2 PUSHes something in foo and AWAKE foo_token
t3) client 1 gets the +OK from the server
t4) client 1 LPOPs from foo
between t3 and t4 another client may PUSH something inside the foo list, so
there is
no guarantee that the latest item pushed by client 2 will be what client 1
will read, as
opposed to BLPOP (blocking lpop) that is able to guarantee this.
But the good news is that in most of the algorithms I can think of based on
blocking
by the consumer what really is important is to avoid polling. Once there is
something
new in the list this is going to be processed ASAP. Even if new stuff is in
the list as
far as the consumer is getting the top-most it should be ok.
But... unfortunately it's not this simple :)
Again, single client blocking, we'll try to generalize the idea later.
t1) client 1 SLEEPs for foo_token
t2) client 2 PUSHes something in foo and AWAKE foo_token
t3) client 1 gets the +OK from the server
t4) client 1 LPOPs from foo
t5) client 1 is still LPOPping, but client 3 PUSHes something into foo and
AWAKE
foo_token, that does not exist. No operation is permed by AWAKE.
t6) client 1 SLEEPs again for foo_token. Even if there are elements inside
the list it
will not get unblocked.
/\/\/\/\~~~~ NOT COOL ~~~~/\/\/\/\/ :)
How to fix this? Adding an internal counter, probably.
AWAKE increments a counter associated to the token
SLEEP waits if the counter is zero, otherwise decrements the counter and
returns.
With the new implementations of AWAKE and SLEEP now it's possible to mount a
blocking LPOP that actually is able to avoid deadlocks.
Still there is a problem even with just one client. What about the consumer
crashing
just after SLEEP returns with +OK but before the LPOP? There will be an
element
inside the list but no-one will LPOP it.
There are two fixes:
a) In some protocol it does not matter a lot, just it will get popped the
next time
something is pushed. After SLEEP the client may start with an LLEN to check
if there is
something new.
b) better: anyway a client before to SLEEP will start checking if the are
the conditions
to start working instead to wait. That is, perform an LLEN and if it's 0
start SLEEPing.
Multiple clients:
I think that when multiple clients are sleeping for the same key all should
be
awakened and the counter decremented of just one. This is almost never a
bad thing,
at max just one will get new data and all the rest will get a 'nil' in the
List example,
in basically they have a way to check if there is no data in all the
protocols.
After all the user is permitting N clients to sleep for the same key, she
should know
what she is doing.
On the other side SLEEP/AWAKE allow for a lot of new interesting protocols
to be
mounted, for instance you can have a randomized message passing data
structure,
that is a Redis Set with an SRANDPOP in the consumer side, or a centralized
way to
perform timing on background jobs in large structures with a lot of
background
processes, in order to make all this adaptive to the load, and so forth.
Cheers,
Salvatore
How about this?
SLEEP foo_key timeout
It returns +OK (meaning "you are awaken") or +TIMEOUT.
This is basically select(2) for single "key descriptor" :)
Yep temotor, a timeout may make systems based on SLEEP/AWAKE a lot more
robust. It
may be very similar to the final solution... at some point of the 1.x Redis
saga it may
get implemented, not sure when this will happen, if there are chances for
1.2 or 1.3
given the huge list in the TODO :)
Cheers,
Salvatore
Comment #18 on issue 65 by antirez: [Feature Request] Blocking LPOP
http://code.google.com/p/redis/issues/detail?id=65
this was implemented time ago, closing the issue...
thanks!