Введение
Redis публикация и подписка (pub/sub) — это модель передачи сообщений: отправитель (pub) отправляет сообщения в канал (channel), а подписчик (sub) получает сообщения из канала (channel).
Redis в настоящее время поддерживает обычные подписки и подписки на шаблоны (шаблоны в стиле glob). Давайте воспользуемся обычной подпиской, чтобы понять принцип ее реализации.
Обычная подписка-публикация и принцип реализации подписки (pub/sub).
RedisСерверСловарь используется для хранения отношений подписки.。существоватьRedis-7.0.5Отражение в исходном коде:
(Источник: Redis-7.0.5: server.h --->struct redisServer )
Базовая реализация словаря используетРеализовано с использованием хеш-массива, ключом является имя канала, значением является связанный список (связанный список, состоящий из клиентов, подписавшихся на один и тот же канал), а элементы связанного списка представляют собой связанные клиентские объекты.
(Источник: Redis-7.0.5: server.h --->typedef struct client )
Используйте метод цепочки адресов для разрешения конфликтов хэшей(Сохраните все пары ключ-значение с конфликтующими хеш-адресами.связанный списоксередина)。
Чтобы подсчитать информацию о канале, на которую подписан клиент, структура client, которая инкапсулирует информацию о клиенте, также использует структуру данных словаря для избыточного сохранения всех названий каналов, на которые подписан клиент, в пространственно-временном режиме (поведение словаря выраженный как структура данных коллекции).
(Источник: Redis-7.0.5: server.h --->typedef struct client )
В качестве примера возьмем название канала Renzhikeji:
Функция обработки команды: subscribeCommand (файл pubsub.c)
(Источник: Redis-7.0.5: pubsub.c --> void subscribeCommand(client *c))
Команда подписки: ПОДПИСАТЬСЯ channel [channel ...],Поддерживает подписку на несколько каналов,В строке кода 27,Вызовите функцию pubsubSubscribeChannel для каждого канала в массиве каналов.,Сохраните отношения подписки на каналы в хэш-словаре.
Сначала добавьте пару ключ-значение: имя канала. -> null Сохраните его в хэш-словаре клиента pubsub_channels для поддержки команды, позволяющей легко получать информацию обо всех каналах, на которые подписан этот клиент (что соответствует строке кода 234).
Затем из хэш-словаря сервера В pubsub_channels запросите это значение ключа для связанного клиента, соответствующего текущему имени канала. список (соответствует строке кода 238), если не найден, создать Пустой связанный список,ВоляПара ключ-значение: название канала -> Пустой связанный список Сохраните его в хеш-словаре (соответствует строкам кода 239–242). Если вы нашли клиентсвязанный, соответствующий текущему названию канала с этим значением ключа список(Соответствующая строка кода244)Затем получите текущую пару ключ-значениеvalueценить。наконецДобавьте клиента, который в данный момент подписан на этот канал, в конец связанного списка.(Соответствующая строка кода246)。
Видно, что основным процессом подписки является операция поиска и добавления хеш-таблицы.
В качестве примера возьмем название канала Renzhikeji:
Функция обработки команд публикации сообщений: publicCommand (файл pubsub.c).
(Источник: Redis-7.0.5: pubsub.c --> void publishCommand(client *c) )
Сначала определите, запущен ли он в дозорном режиме. Если да, обработайте процесс обработки сообщения публикации в дозорном режиме.
Если это не дозорный режим, вызовите функцию
pubsubPublishMessageAndPropagateToCluster :
1、Из словаря структуры данных server.pubsub_channels (отношения подписки) найдите всех подписчиков этого канала и запишите сообщения, опубликованные этим каналом, в соответствующие кэши ответов всех соответствующих клиентов-подписчиков.。
Из словаря server.pubsub_channels, по названию каналадляkey,Найти пары ключ-значение dictEntry,если найден,Перейдите по связанному списку клиентов, соответствующему ключу,Воля Функция вызова опубликованного сообщенияaddReplyPubsubMessage Запись в кэш ответов клиента,и обновляет статистику памяти (и, конечно, перебирает словарь подписки на схему).
Примечание. Если кэш, соответствующий клиенту, превысит лимит, подписчик будет принудительно закрыт.
(Источник: Redis-7.0.5: networking.c )
2. Если сервер включает режим кластера (server.cluster_enabled), будет вызвана функция кластераPropagatePublish для управления отношениями подписки «главный-подчиненный» кластера.
Краткое описание того, как избежать ловушек