122 Commits

Author SHA1 Message Date
michael-grunder 2451c75ed8 WATCH command
Implemented the WATCH command for RedisCluster.  This command can
take any number of keys, so phpredis splits the request across the
cluster in the best way it can.

For every key in a multiple key command, Redis Cluster requires
that they all hash to the same SLOT, else it will return a
CROSSLOT error and fail.

For WATCH in RedisCluster, a few things to note:

* The command will fail if phpredis is out of sync with the keyspace.
  This is because we'll need to know where to deliver each command,
  or can't possibly deliver them correctlhy.

* The command will fail if any command delivery failures occur on any
  node.  This is the case either for a normal communication error or
  if RedisCluster returns to us MOVED/ASK redirection.
2015-05-05 15:00:51 -07:00
michael-grunder 95ecefcec6 Transaction support
This is the initial commit supporting transactions in RedisCluster
via MULTI..EXEC.  Given that the data can be distributed across
many nodes, we accomplish transactions as follows.

1.  When entering MULTI mode, the cluster context state is changed
    to MULTI
2.  When we send a command to a node, we check that node's RedisSock
    state, and if it's still ATOMIC, deliver the MULTI command,
    updating the node's state to MULTI.
3.  When reading replies, we check if the RedisSock* is in a MULTI
    state, which means we need to issue the EXEC command.  We do
    this and then flip the state back to ATOMIC.
4.  On completion, everything is reverted to ATOMIC state and our
    reply callbacks are freed and set to NULL.

For transactions, we enforce writes such that they MUST be able to
be processed by the node in question (e.g. they can't work during
a reshard, because there is no way to know what has failed, etc).

This is the same as RedisCluster which will also cancel transactions
in the case where a request was made for data that is somewhere else.
2015-05-05 14:59:29 -07:00
michael-grunder 4a88dd9d89 Moved our typedef below all defines 2015-05-05 14:55:48 -07:00
michael-grunder cd87c04a21 Created cluster specific option handling
Added distribution option to RedisCluster in preperation for
implementation of commands which can be distributed by the client.

The two distribution modes will be:

* DIST_OOE   : Maintain order of execution
* DIST_SPEED : Most efficient delivery

Either way, the RedisCluster object will need to return values that
were gathered in the same way they were sent in, but might execute
them in a different order if the option is set to DIST_SPEED.
2015-05-05 14:55:48 -07:00
michael-grunder d5cd5d081f Added context, HMGET/HMSET
Added context void pointer that we pass around, which is
(thus far) really just for hmget (as we need to keep the
keys around to bind them with the returned values).

This requires every command construction routine and each
response callback be passed this void pointer, which is always
NULL except for HMGET

Added HMGET and HMSET commands
2015-05-05 14:37:23 -07:00
michael-grunder 1b591b8fc9 HGETALL/INCR/INCRBY/DECR/DECRBY
Added zipstr handler for k,v,k2,kv to k=>v,k2=>v2 as well as
implemented int based incr and decr commands.
2015-05-05 14:32:55 -07:00
michael-grunder d6916a43e0 Added zipped with strings multi bulk response handler 2015-05-05 14:32:55 -07:00
michael-grunder 9b2db3d3b8 Use long long for reply length/count storage
We can't use size_t here because Redis might return to us a negative
value (e.g. -1 for a bulk or multi bulk length part).
2015-05-05 14:32:55 -07:00
michael-grunder 39796aa095 DUMP command, raw bulk handler
Added support for the DUMP command and created a Cluster based
RAW bulk handler.  Thinking we should do like MULTI BULK and
create a generic handler, with various callbacks for encoding
2015-05-05 14:32:06 -07:00
michael-grunder 69096d4d37 ZCARD/ZSCORE as well as double response handler for cluster 2015-05-05 14:31:42 -07:00
michael-grunder 6f2a309b7e Added PERSIST and SMEMBERS command, also spaces > tabs :) 2015-05-05 14:31:17 -07:00
michael-grunder 3cdc11d90b LPUSHX/RPUSHX
Implemented LPUSHX and RPUSHX in our new generic way for both
Redis and RedisCluster classes.
2015-05-05 14:18:38 -07:00
michael-grunder 1c1a7de1b4 Disable KEYS command, and add TYPE
We need to figure out how the KEYS command should work in the
context of cluster.  We could either send it to all nodes, or
send it to just one slot.

Added TYPE command and cluster response processor
2015-05-05 14:17:50 -07:00
michael-grunder 18f84efb93 Switched macro ordering and added mbulk processing for cluster 2015-05-05 14:17:49 -07:00
michael-grunder b84366c906 Added integer response handler for cluster 2015-05-05 14:17:27 -07:00
michael-grunder b6b5f09c16 Process and keep the first line in any response.
Added a mechanism to our RedisCluster context structure to retain
the last reply_type, single line reply, and/or integer response
which could either be the length of a BULK/MULTIBULK payload, or
an actual integer.

This makes command processing functions simpler, as we just have
to check that the reply type is correct, and for single line/int
responses, the values themselves.
2015-05-05 14:16:59 -07:00
michael-grunder f08370173e Several updates and fixes to the cluster library.
Updated node parsing to understand that clusters can serve
1-N sequential slots, rather than just one contiguous series.

Updated how we detected masters by using that column in CLUSTER NODES
rather than counting them, as a master can be set up that serves no
slots (e.g. newly added or data was migrated away from it).
2015-05-05 14:11:42 -07:00
michael-grunder 8e12374b44 Initial commit of request/redirect/request logic
This is the initial draft of the logic we'll use in phpredis to
direct requests at a cluster, and then upon getting a moved or
ask response, try at the node delivered.
2015-05-05 14:11:15 -07:00
michael-grunder b1d0ffedb3 Integrated command loop processing to send command to our
Redis Cluster instance, as well as formalized a generic
macro we will use for any return type.

Further work to be done creating the response parsing generics
and then later in combining them with standard phpredis response
parsing.
2015-05-05 13:37:18 -07:00
michael-grunder a8dbe68a21 Initial commit of RedisCluster send/receive loop for commands.
Every time we communicate with the cluster we have to determine
which slot to try, and then if we get a MOVED or ASK redirection,
retry at the new slot.

In the case of MOVED, we'll update the node mapping we cache locally.
For ASK, we'll leave it unchanged but try at the slot where directed
2015-05-05 13:37:18 -07:00
michael-grunder 7ac9279231 Add a method to easily hash a ZVAL 2015-05-05 13:37:18 -07:00
michael-grunder 2f69b07ee4 Initial commit of RedisCluster class and library
This is an initial commmit which adds a RedisCluster class as well
as the framework around which we'll be building proper cluster
support.

The first commit just contains the code to set up and use our new
RedisCluster class as well as parsing logic to handline CLUSTER NODES
such that we can map the keyspace.

Next up, command processing and then pipelining in a sane way.
2015-05-05 13:37:18 -07:00