Классы python-redis
Redis
и ConnectionPool
наследуются от threading.local
, и это производит "магические" эффекты, которые вы видите.
Сводка : клиенты self._redis_sub
вашего основного потока и рабочих потоков заканчивают тем, что использовали два разных соединения с сервером, но только соединение основного потока вызвало команду SUBSCRIBE.
Подробности : Поскольку основной поток создает self._redis_sub
, этот клиент в конечном итоге помещается в локальное хранилище потока. Далее я предполагаю, что основной поток выполняет client.subscribe(channel)
вызов. Теперь клиент основного потока подписан на соединение 1. Затем вы запускаете рабочий поток self._sub_thread
, который в конечном итоге имеет свой собственный атрибут self._redis_sub, установленный на новый экземпляр redis.Client, который создает новый пул соединений и устанавливает новое соединение. на сервер Redis.
Это новое соединение еще не подписано на ваш канал, поэтому listen()
немедленно возвращается. Таким образом, с python-redis
вы не можете передавать установленное соединение с выдающимися подписками (или любыми другими командами с отслеживанием состояния) между потоками.
В зависимости от того, как вы планируете реализовать свое приложение, вам может потребоваться переключиться на использование другого клиента или придумать какой-то другой способ сообщить состояние подписки рабочим потокам, например, отправлять команды подписки через очередь.
Еще одна проблема заключается в том, что python-redis
использует блокирующие сокеты, которые не позволяют вашему прослушивающему потоку выполнять другую работу во время ожидания сообщений, и он не может сигнализировать о своем желании отписаться, если это не происходит сразу после получения сообщения.