Какова хорошая стратегия горизонтального масштабирования для считывателя потока изменений MongoDB?
Я думаю о реализации считывателя потока изменений MongoDB, и я хочу убедиться, что я делаю это правильно. Существует множество простых примеров того, как реализовать реальный код читателя, включая официальную документацию, и я не слишком обеспокоен этим аспектом.
Однако меня немного беспокоит, что читатель отстает от потока изменений и не может наверстать упущенное, и я хочу убедиться, что читатель сможет справиться с этим потоком.
Сервер Монго является кластером и позволяет предположить, что он довольно занят в любое время суток. API потока изменений, похоже, совместим только с одним экземпляром, выполняющим работу, учитывая, как он должен повторять результаты потока, а не работать с ним как с очередью. Поэтому я обеспокоен тем, что вполне возможно, что один экземпляр, повторяющий результаты, может занять больше времени для выполнения своей работы, чем новые элементы помещаются в поток.
Мой инстинкт заключается в том, чтобы на самом деле читатель просто читал поток, пакетировал изменения и затем помещал его в очередь, где другие работники могли бы затем горизонтально масштабировать для выполнения работы. Однако у меня все еще есть один экземпляр в качестве читателя, и теоретически возможно, что он отстанет от потока, даже выполняя лишь минимальную работу по переносу изменений в очередь.
Итак, мои вопросы: насколько реально это беспокоиться и есть ли способ создать читателя таким образом, чтобы он мог масштабироваться по горизонтали, даже если он только передает изменения в рабочую очередь? Какие еще соображения я должен принять во внимание?
1 ответ
Скорее всего, одного читателя может быть достаточно, просто делегировав всю работу в горизонтально масштабированную очередь.
Если окажется, что этого недостаточно, и вашему читателю все еще нужно масштабировать по горизонтали, вы можете достичь этого, используя фильтр соответствия таким образом, чтобы это позволило нескольким читателям разделить работу.
Например, если у вас есть идентификатор с шестнадцатеричными символами, вы можете разделить работу на два сервера, используя оператор сопоставления на каждом сервере, где каждый сервер сопоставляет половину символов в полном диапазоне:
// Change Stream Reader 1
const params = [
{ $match: { _id: /^[0-7]/ } }
];
const collection = db.collection('inventory');
const changeStream = collection.watch(params);
На второй машине:
// Change Stream Reader 2
const params = [
{ $match: { _id: /^[8-9a-f]/ } }
];
const collection = db.collection('inventory');
const changeStream = collection.watch(params);
Если вам нужно иметь более 16 серверов, вы можете сделать диапазон еще более конкретным:
// Server 0 matches on /^0[0-7]/
// Server 1 matches on /^1/
// ...
// Server 15 matches on /^f/
// Server 16 matches on /^0[8-9a-f]/
Это позволит каждой машине просматривать подмножество сообщений и обрабатывать их, в то время как другие машины обрабатывают другие сообщения без дублирования.
Координация того, какой сервер следит за тем, какой диапазон надежным способом становится несколько сложной, поскольку вам необходимо обеспечить возобновление работы разбитой или зависшей машины и, если вам необходимо динамическое масштабирование по горизонтали, вам необходимо иметь возможность доставлять новые диапазоны на серверы и изменять их размеры., Это решение также приведет к тому, что сообщения будут обрабатываться не по порядку, поэтому, если порядок важен, вам нужно будет найти решение для переупорядочения сообщений или решения проблем, не связанных с последовательностью.
Но это все разные темы из этого вопроса, поэтому я пока опущу детали.