ioredis icon indicating copy to clipboard operation
ioredis copied to clipboard

CLIENT ID and blocking XREAD in cluster

Open NeoPhi opened this issue 4 years ago • 2 comments

I didn't see anything in the API that would help us with our situation and wanted to make sure I wasn't missing something. We have a Redis cluster where we want to issue a XREAD BLOCK 0 command. At some later point we will want to issue a CLIENT UNBLOCK to break the infinite block. The Redis documentation suggests running CLIENT ID before the blocking XREAD will allow you to know what ID to pass to CLIENT UNBLOCK. However it seems ioredis is using the stream key passed to XREAD to determine a slot and node in the cluster it should connect to. If the CLIENT ID happens on execute on a different node than the XREAD we have no way of knowing the correct CLIENT ID to issue the CLIENT UNBLOCK on.

Below is some sample DEBUG output showing the node hopping (for testing purposes I'm not blocking):

  ioredis:redis write command[172.22.0.4:7000]: 0 -> client([ 'id' ]) +2ms
  ioredis:redis status[172.22.0.4:7002]: wait -> connecting +6ms
  ioredis:redis queue command[172.22.0.4:7002]: 0 -> xread([ 'STREAMS', 'a', '$' ]) +1ms
  ioredis:redis status[172.22.0.4:7002]: connecting -> connect +1ms
  ioredis:redis write command[172.22.0.4:7002]: 0 -> info([]) +0ms
  ioredis:redis status[172.22.0.4:7002]: connect -> ready +1ms
  ioredis:connection send 1 commands in offline queue +11ms
  ioredis:redis write command[172.22.0.4:7002]: 0 -> xread([ 'STREAMS', 'a', '$' ]) +0ms
  ioredis:redis write command[172.22.0.4:7002]: 0 -> client([ 'id' ]) +1ms
  ioredis:redis status[172.22.0.4:7001]: wait -> connecting +2ms
  ioredis:redis queue command[172.22.0.4:7001]: 0 -> xread([ 'STREAMS', 'c', '$' ]) +0ms
  ioredis:redis status[172.22.0.4:7001]: connecting -> connect +1ms
  ioredis:redis write command[172.22.0.4:7001]: 0 -> info([]) +0ms
  ioredis:redis status[172.22.0.4:7001]: connect -> ready +1ms
  ioredis:connection send 1 commands in offline queue +5ms
  ioredis:redis write command[172.22.0.4:7001]: 0 -> xread([ 'STREAMS', 'c', '$' ]) +0ms

You can see the first client id takes place on 7000 while the xread takes place on 7002.

Are there any facilities to know which node a command will be run on so that we can capture the correct client id and also issue the client unblock to the correct node?

NeoPhi avatar Jan 06 '21 22:01 NeoPhi

I added Redis Stream Classes. Maybe they help you

https://github.com/luin/ioredis/pull/1376

Uzlopak avatar Jul 01 '21 05:07 Uzlopak

I added Redis Stream Classes. Maybe they help you

That's not relevant at all

Regarding the issue. There's a slot table: https://github.com/luin/ioredis/blob/88b8a3125cd039afdac928c529a1b9958009979c/test/functional/cluster/transaction.ts#L9-L12 https://github.com/luin/ioredis/blob/88b8a3125cd039afdac928c529a1b9958009979c/lib/cluster/index.ts#L850

And some way to calculate it for a key: https://github.com/luin/ioredis/blob/88b8a3125cd039afdac928c529a1b9958009979c/test/functional/cluster/transaction.ts#L1

marcbachmann avatar Jan 27 '22 18:01 marcbachmann