Skip to content

Redisearch + Cluster seems unsupported #2365

Closed
@rpkak

Description

@rpkak

Version: 4.3.4

Platform: Python 3.10.6 on Archlinux with 5.19.5-arch1-1 kernel

Description:

Dockerfile
FROM redis/redis-stack-server:latest

RUN mkdir "/configs" \
        \
	&& echo "port 7000" >> "/configs/7000"  \
	&& echo "cluster-enabled yes" >> "/configs/7000"  \
	&& echo "cluster-config-file /configs/7000nodes.conf" >> "/configs/7000"  \
	&& echo "cluster-node-timeout 5000" >> "/configs/7000"  \
	&& echo "appendonly yes" >> "/configs/7000"  \
	&& echo "protected-mode no" >> "/configs/7000"  \
	\
	&& echo "port 7001" >> "/configs/7001"  \
	&& echo "cluster-enabled yes" >> "/configs/7001"  \
	&& echo "cluster-config-file /configs/7001nodes.conf" >> "/configs/7001"  \
	&& echo "cluster-node-timeout 5000" >> "/configs/7001"  \
	&& echo "appendonly yes" >> "/configs/7001"  \
	&& echo "protected-mode no" >> "/configs/7001"  \
	\
	&& echo "port 7002" >> "/configs/7002"  \
	&& echo "cluster-enabled yes" >> "/configs/7002"  \
	&& echo "cluster-config-file /configs/7002nodes.conf" >> "/configs/7002"  \
	&& echo "cluster-node-timeout 5000" >> "/configs/7002"  \
	&& echo "appendonly yes" >> "/configs/7002"  \
	&& echo "protected-mode no" >> "/configs/7002"  \
	\
	&& echo "port 7003" >> "/configs/7003"  \
	&& echo "cluster-enabled yes" >> "/configs/7003"  \
	&& echo "cluster-config-file /configs/7003nodes.conf" >> "/configs/7003"  \
	&& echo "cluster-node-timeout 5000" >> "/configs/7003"  \
	&& echo "appendonly yes" >> "/configs/7003"  \
	&& echo "protected-mode no" >> "/configs/7003"  \
	\
	&& echo "port 7004" >> "/configs/7004"  \
	&& echo "cluster-enabled yes" >> "/configs/7004"  \
	&& echo "cluster-config-file /configs/7004nodes.conf" >> "/configs/7004"  \
	&& echo "cluster-node-timeout 5000" >> "/configs/7004"  \
	&& echo "appendonly yes" >> "/configs/7004"  \
	&& echo "protected-mode no" >> "/configs/7004"  \
	\
	&& echo "port 7005" >> "/configs/7005"  \
	&& echo "cluster-enabled yes" >> "/configs/7005"  \
	&& echo "cluster-config-file /configs/7005nodes.conf" >> "/configs/7005"  \
	&& echo "cluster-node-timeout 5000" >> "/configs/7005"  \
	&& echo "appendonly yes" >> "/configs/7005"  \
	&& echo "protected-mode no" >> "/configs/7005"  \
	\
	&& echo "#!/usr/bin/env bash" >> "/entrypoint"  \
	&& echo "redis-server /configs/7000 --loadmodule /opt/redis-stack/lib/redisearch.so &" >> "/entrypoint"  \
	&& echo 'R7000=$!' >> "/entrypoint"  \
	&& echo "redis-server /configs/7001 --loadmodule /opt/redis-stack/lib/redisearch.so &" >> "/entrypoint"  \
	&& echo 'R7001=$!' >> "/entrypoint"  \
	&& echo "redis-server /configs/7002 --loadmodule /opt/redis-stack/lib/redisearch.so &" >> "/entrypoint"  \
	&& echo 'R7002=$!' >> "/entrypoint"  \
	&& echo "redis-server /configs/7003 --loadmodule /opt/redis-stack/lib/redisearch.so &" >> "/entrypoint"  \
	&& echo 'R7003=$!' >> "/entrypoint"  \
	&& echo "redis-server /configs/7004 --loadmodule /opt/redis-stack/lib/redisearch.so &" >> "/entrypoint"  \
	&& echo 'R7004=$!' >> "/entrypoint"  \
	&& echo "redis-server /configs/7005 --loadmodule /opt/redis-stack/lib/redisearch.so &" >> "/entrypoint"  \
	&& echo 'R7005=$!' >> "/entrypoint"  \
	&& echo "_term() {" >> "/entrypoint" \
	&& echo "  echo 'Stopping redisearch cluster'" >> "/entrypoint" \
	&& echo '  kill -TERM "$R7000"' >> "/entrypoint" \
	&& echo '  kill -TERM "$R7001"' >> "/entrypoint" \
	&& echo '  kill -TERM "$R7002"' >> "/entrypoint" \
	&& echo '  kill -TERM "$R7003"' >> "/entrypoint" \
	&& echo '  kill -TERM "$R7004"' >> "/entrypoint" \
	&& echo '  kill -TERM "$R7005"' >> "/entrypoint" \
	&& echo "}" >> "/entrypoint" \
	&& echo "sleep 1" >> "/entrypoint"  \
	&& echo "redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1 --cluster-yes" >> "/entrypoint"  \
	&& echo "trap '_term' TERM" >> "/entrypoint" \
	&& echo "trap '_term' INT" >> "/entrypoint" \
	&& echo "wait -n" >> "/entrypoint" \
	&& echo 'exit $?' >> "/entrypoint" \
	\
	&& chmod 755 "/entrypoint"

EXPOSE 7000
EXPOSE 7001
EXPOSE 7002
EXPOSE 7003
EXPOSE 7004
EXPOSE 7005

CMD [ "/entrypoint" ]

For the redis cluster I use a docker image build from the Dockerfile and start it with:

docker run -p 7000-7005:7000-7005 [imagename]

Setup:

from redis.cluster import RedisCluster, ClusterNode
from redis.commands.search.indexDefinition import IndexDefinition, IndexType
from redis.commands.search.field import TextField

r = RedisCluster(startup_nodes=[
    ClusterNode('localhost', '7000'),
    ClusterNode('localhost', '7001'),
    ClusterNode('localhost', '7002'),
    ClusterNode('localhost', '7003'),
    ClusterNode('localhost', '7004'),
    ClusterNode('localhost', '7005')
])

When I try to create a index the response is b'OK', but you can see that there was an error. Here my IPython logs:

In [2]: r.ft('foo').create_index([TextField('bar')])
MovedError
Traceback (most recent call last):
  File "path/venv/lib/python3.10/site-packages/redis/cluster.py", line 1074, in _execute_command
    response = redis_node.parse_response(connection, command, **kwargs)
  File "path/venv/lib/python3.10/site-packages/redis/client.py", line 1254, in parse_response
    response = connection.read_response()
  File "path/venv/lib/python3.10/site-packages/redis/connection.py", line 839, in read_response
    raise response
redis.exceptions.MovedError: 12182 127.0.0.1:7002
Out[2]: b'OK'

When I run r.ft('foo').create_index([TextField('bar')]) again I get:

...

ResponseError: Index already exists

So probably the first try worked as expected, but only prints an error.

By looking into the code I think that these two lines of RedisCluster._determine_nodes are causeing the issue because they always use the default node and not the node of slot of the index name:

redis-py/redis/cluster.py

Lines 836 to 837 in e6cd4fd

elif command in self.__class__.SEARCH_COMMANDS[0]:
return [self.nodes_manager.default_node]

When I removed these lines the error was gone, but I think the lines have to be there for a reason.

I while looking into the code I also saw, that Search.pipeline always (for clusters and single servers) returns a redis.commands.search.Pipeline object, which does not inharit ClusterPipeline.

Because of this r.ft('foo').pipeline() fails. Because Search.sugadd uses this function, r.ft('foo').sugadd('bar') fails as well.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions