Это может быть сделано на товарном ПК (и может масштабироваться до сервера без изменений кода).
Замки не являются проблемой. С одним автором и несколькими потребителями, которые занимаются трудоемкими задачами на больших данных, у вас будет редкая блокировка и практически полное нарушение блокировки, поэтому это не проблема.
Все, что угодно от простой спин-блокировки (если вы действительно отчаянно нуждаетесь в малой задержке), или, желательно, pthread_mutex
(который в любом случае возвращается к тому, чтобы быть спин-блокировкой). Ничего особенного.
Обратите внимание: не получить блокировку, получить мегабайт данных из сокета, записать его на диск, а затем отпустить блокировку. Это не так, как это работает.
Вы получаете мегабайт данных и записываете их в регион , который у вас есть исключительно, затем приобретите замок, измените указатель (и, таким образом, передайте право собственности) и отпустите замок. Блокировка защищает метаданные, а не каждый байт в буфере гигабайтного размера. Длительные задачи, короткие времена блокировки, утверждение = ноль.
Что касается фактических данных, то выписать 15MiB/s абсолютно не сложно, обычный жесткий диск будет делать в 5-6 раз больше, а SSD будет легко делать в 10-20 раз. Это также не то, что вам даже нужно делать самому. Это то, что вы можете оставить в операционной системе для управления.
Я хотел бы создать 54.1GB файл на диске и памяти карты, (если это система 64-разрядная, разумное предположение, когда речь идет о многогигабайтных-RAM-серверов, это не проблема). Операционная система заботится обо всем остальном. Вы просто записываете свои данные в отображаемую область, которую вы используете как круговой буфер .
То, что было написано в последнее время, будет более или менее гарантировано быть резидентом в ОЗУ, чтобы потребители могли получить к нему доступ без сбоев. Более старые данные могут быть или не быть в ОЗУ, в зависимости от наличия у вашего сервера достаточного количества физической памяти.
Данные, которые старше, по-прежнему могут быть доступны, но, вероятно, на немного более медленной скорости (если нет достаточной физической памяти, чтобы сохранить весь резидентный набор). Это, однако, не повлияет на производителя или потребителей, читающих недавно записанные данные (если только машина не настолько ужасна, что она не может даже удерживать 2-3 блока 1MiB в ОЗУ, но тогда у вас есть другая проблема!).
Вы не очень конкретны в отношении того, как вы собираетесь обрабатывать данные, кроме 5 потребителей, поэтому я не буду углубляться в эту часть. Возможно, вам придется внедрить систему планирования заданий, или вы можете просто разделить каждый входящий блок на 5 небольших кусков или что угодно - в зависимости от того, что именно вы хотите сделать.
В любом случае вам необходимо указать область (либо как указатель, либо лучше как смещение в сопоставление) данных в вашем отображаемом буфере обмена, который является «действительным», а регион, который «не используется».
Производитель является владельцем сопоставления, и он «позволяет» потребителям получать доступ к данным в пределах, указанных в метаданных (пара начала/конца смещений). Только этот производитель может изменить эти метаданные. Любой пользователь (включая производителя), получающий доступ к этим метаданным, должен получить блокировку.
Возможно, это возможно даже с атомными операциями, но, видя, как вы редко блокируете, я даже не буду беспокоиться. Это бесполезно, используя замок, и нет никаких тонких ошибок, которые вы можете сделать.
Поскольку производитель знает, что потребители будут рассматривать данные только в пределах четко определенных границ, он может писать в области за пределами границ (область, известная как «emtpy») без блокировки. Это необходимо только для фиксации, чтобы впоследствии изменить границы.
Как 54.1Gib> 54Gib, у вас есть сто запасных блоков 1MiB в сопоставлении, на которое вы можете писать. Это, вероятно, намного больше, чем нужно (2 или 3 следует делать), но не больно иметь несколько дополнительных. Когда вы пишете новый блок (и увеличиваете допустимый диапазон на 1), также настраивайте другой конец «допустимого диапазона».Таким образом, потокам больше не будет разрешен доступ к старому блоку, но поток, все еще работающий в этом блоке, может завершить свою работу (данные все еще существуют).
Если вы строго придерживаетесь правильности, это может создать условие гонки, если обработка блока занимает очень много времени (более 1 1/2 минуты в этом случае). Если вы хотите быть абсолютно уверены, вам понадобится еще один замок, который может в худшем случае блокировать производителя. Это то, чего вы абсолютно не хотели, но блокирование продюсера в худшем случае - единственное, что на 100% правильное в каждом случае, если гипотетический компьютер не имеет неограниченной памяти.
Учитывая сложившуюся ситуацию, я думаю, что эта теоретическая гонка является «допустимой». Если обработка одного блока на самом деле занимает так много времени, так как количество данных постоянно поступает, у вас гораздо более серьезная проблема, поэтому практически, это не проблема.
Если ваш босс решает, в какой-то момент в будущем, что вы должны сохранить более 1 часа отставания, вы можете увеличить файл и переназначить, а когда «пустая» область будет следующей в конце старой размера буфера, просто расширьте «известный» размер файла и настройте значение max_size в производителе. Потребительские потоки даже не нужно знать. Разумеется, вы могли бы создать другой файл, скопировать данные, обменять и заблокировать потребителей в среднем, но я считаю, что это плохое решение. Вероятно, нет необходимости в том, чтобы увеличение размера было сразу видно, но, с другой стороны, очень желательно, чтобы это был «невидимый» процесс.
Если вы поместили больше ОЗУ в компьютер, ваша программа будет «волшебным образом» использовать его, без необходимости ничего менять. Операционная система будет просто хранить больше страниц в ОЗУ. Если вы добавите еще нескольких потребителей, они все равно будут работать одинаково.
Преднамеренно больше, чем то, что вам нужно, пусть будет несколько «лишних» блоков 1MiB.
Предпочтительно связываться, вы можете madvise
операционную систему (если вы используете систему, которая имеет разрушительную DONT_NEED подсказку, например, Linux), что вы больше не заинтересованы в содержании перед перезаписью области. Но если вы этого не сделаете, это будет работать в любом случае, только немного менее эффективно, потому что ОС, возможно, выполнит операцию чтения-изменения-записи, где операции записи было бы достаточно.
Существует, конечно, никогда не действительно гарантию, но это то, что будет иметь место в любом случае.
Если верхний предел действительно 50 гб, я уверен, что вы можете получить машину, которая справляется с этим с легкостью. 128gb довольно стандартный для тяжелых рабочих станций. – stijn
Если ваша память будет ограничена, просто сохраните последние несколько секунд в ОЗУ и сфотографируйте другую на диск, используя [файлы с отображением памяти] (http://en.wikipedia.org/wiki/Memory-mapped_file). –
@JoachimPileborg, сохраняющий всего несколько секунд в ОЗУ, не помогает. Поскольку потоки чтения могут требовать данные из любого временного интервала, а не только из последних. – user2955554