Я думаю, что вы находитесь на правильном пути со вторым решением, однако производительность может быть выше, если вы будете хранить каждый добавленный_id как собственный ключ-значение вместо массива.
Логика довольно проста: каждый раз, когда вы получаете данные из очереди, ищите в своем кэше, есть ли запись для этого идентификатора сообщения. Если есть запись, не накапливайте эту информацию. В противном случае накапливайте ввод и сохраняйте ключ в кеше.
Как вы упомянули, у этого подхода есть проблемы с масштабируемостью, потому что кэш будет расти бесконечно. Чтобы обойти эту проблему, вы можете использовать кэш с функциями истечения срока действия и выселения. Самый простой способ сделать это - явно установить «expires at» каждого ключа, который вы пишете. Это поддерживается Mongo, Memcached и Redis.
Проблема в том, что даже если вы установите «expires at» в каждой точке, при достаточной нагрузке ваш кэш все равно будет нехватать памяти. Так что вам нужен запасной вариант - что-то делать, когда в кеше недостаточно памяти. Для этого вы можете использовать кеш с функцией «автоматического выселения», что означает, что он имеет алгоритм для удаления вещей, когда это необходимо.
Похоже, что Mongo не поддерживает ничего подобного (это база данных с функциями кэша, а не с правильным кэшем). Memcache использует алгоритм LRU (см. https://github.com/memcached/memcached/wiki/UserInternals#when-are-items-evicted). Redis имеет несколько алгоритмов, из которых вы можете выбрать (см. https://redis.io/topics/lru-cache).
Еще одна вещь, которую я хотел бы иметь в виду, это то, что выполнение всего этого процесса в распределенном или многопоточном приложении вводит условия гонки. Скажем, у вас есть 20 рабочих машин, которые по какой-то причине все получают одно и то же сообщение практически в одно и то же время. Каждый из них проверит кеш на предмет записи и ничего не найдет, поэтому ни один из них не помечен как дубликат.
Чтобы обойти эту проблему, вы можете использовать мьютексы / семафоры для нескольких потоков, работающих на одном компьютере (вертикальное масштабирование) или «распределенную блокировку», если у вас есть несколько машин полностью (горизонтальное масштабирование). См https://redis.io/topics/distlock
1020 * редактировать *
Я получил совет, что Монго может сделать авто-выселение с Capped Collections . Он поддерживает только выселение FIFO (сначала истекает самый старый срок действия данных), которое в любом случае может работать для ваших нужд.