Thanks to visit codestin.com
Credit goes to github.com

Skip to content

redisCluster->rawCommand() didn't work correctly #1006

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
responder-tw opened this issue Nov 9, 2016 · 3 comments
Closed

redisCluster->rawCommand() didn't work correctly #1006

responder-tw opened this issue Nov 9, 2016 · 3 comments

Comments

@responder-tw
Copy link

Hi all,

My test environment
phpredis 2.2.8 + 5.4.45-0+deb7u5 on Debian 7 + redis 3.0.6 cluster.

I had tried to implement "ZADD NX" function by rawCommand(), but got an
"Unable to send command to the specified node" exception when work w/ redis cluster.

After some digging, I found it's caused by incorrect key slot.
The patch is as attached for your reference.
(sorry, I'm not familiar w/ the pull request workflow.)
Tested ok on my environment.

redisClusterRawCommandPatch.txt

@michael-grunder
Copy link
Member

Hey,

When using rawCommand with RedisCluster you pass the key or a host/port combination as the initial argument, which tells RedisCluster where to deliver the query:

Example:

$rc = new RedisCluster(NULL, ['127.0.0.1:7000']);

$ret = $rc->rawCommand('mykey', 'zadd', 'mykey', 'nx', 1, 'foo');
var_dump($ret);

So it uses the first argument above mykey to send (in my case) the query to port 7002.

127.0.0.1:7002> zrange mykey 0 -1 withscores
1) "foo"
2) "1"

I could be missing something though. πŸ˜ƒ

@responder-tw
Copy link
Author

Hi michael,

Thanks for the reply.
Passing key as the 1st argument indeed work. πŸ‘

I had tried to pass the cluster node info as 1st argument of rawCommand() on my previous test.
Ex.
$rc->rawCommand('127.0.0.1:700', 'zadd', 'mykey', 'nx', 1, 'foo');
$rc->rawCommand(array('127.0.0.1'. '7000'), 'zadd', 'mykey', 'nx', 1, 'foo');
Both failed w/ false or SIGSEG.

Just recheck the phpredis source and find out the port part must be passed as LONG to make it work.
NG : array('127.0.0.1', '7000')
OK : array('127.0.0.1', 7000)
I had been spoiled by php's loosing typing for awhile... Orz

One more thing to be noticed.
The host, port mapping must be correct to make rawCommand() work.
If I changed array('127.0.0.1', 7000) to array('127.0.0.1', 7001), I'll get a SIGSEG.

The following is the strace result for SIGSEG, it seemed the rawCommand implement didn't handle "MOVED" response nicely.
Maybe this topic should be renamed to "SIGSEG if passing wrong array(host, port) to redisCluser->rawCommand()" . XD

connect(4, {sa_family=AF_INET, sin_port=htons(7001), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
poll([{fd=4, events=POLLIN|POLLOUT|POLLERR|POLLHUP}], 1, 60000) = 1 ([{fd=4, revents=POLLOUT}])
getsockopt(4, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
fcntl(4, F_SETFL, O_RDWR) = 0
setsockopt(4, SOL_TCP, TCP_NODELAY, [1], 4) = 0
poll([{fd=4, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 0) = 0 (Timeout)
sendto(4, "*3\r\n$3\r\nSET\r\n$9\r\nRCTest:ZS\r\n$44\r"..., 79, MSG_DONTWAIT, NULL, 0) = 79
poll([{fd=4, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 0) = 0 (Timeout)
poll([{fd=4, events=POLLIN|POLLERR|POLLHUP}], 1, 60000) = 1 ([{fd=4, revents=POLLIN}])
recvfrom(4, "-MOVED 12795 127.0.0.1:7000\r"..., 8192, MSG_DONTWAIT, NULL, NULL) = 33
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++
Segmentation fault

@yatsukhnenko
Copy link
Member

Fixed SIGSEG, thanks @responder-tw

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants