скажи это прямо
RocketMQ извлекает уроки из Kafka в базовом хранилище, но у него также есть свой уникальный дизайн.Эта статья в основном посвящена базовой структуре файлового хранилища, которая сильно влияет на производительность RocketMQ, и немного Kafka будет вкраплен в середину для сравнения.
пример
Commit Log, набор файлов, каждый файл размером 1G.После заполнения хранилища сохраняется следующий.Для удобства обсуждения его можно рассматривать как файл, и все содержимое сообщения сохраняется в этот файл ; Очередь потребления: Тема может иметь несколько , каждый файл представляет собой логическую очередь, где хранится значение смещения сообщения в журнале фиксации, а также размер и атрибуты тега.
Для краткости приведу пример
Если в кластере есть брокер, количество очередей потребления, темой которых является binlog, равно 4, как показано на рисунке ниже, и 5 сообщений с разным содержимым отправляются последовательно.
Во-первых, кратко обратите внимание на Commit Log и Consume Queue.
Сообщения RMQ упорядочены как единое целое, поэтому содержимое этих пяти сообщений сохраняется в журнале фиксации по порядку. Очередь потребления используется для равномерного размещения сообщений в разных логических очередях.В кластерном режиме несколько потребителей могут параллельно потреблять сообщения очереди потребления.
Page Cache
Зная, где хранится каждый файл и какой контент хранится, мы формально обсудим, почему это решение для хранения повышает производительность.
Обычно файл читается и пишется относительно медленно.Если файл читается и пишется последовательно, скорость почти близка к случайному чтению и записи памяти.Почему так быстро?Причина в кэше страниц.
Давайте сначала интуитивно почувствуем: вся ОС имеет 3,7 ГБ физической памяти, после использования 2,7 ГБ должен остаться 1 ГБ свободной памяти, но ОС дает 175 МБ. Конечно, эту математическую задачу нельзя решить таким образом.
Когда ОС обнаружит, что в системе осталось много свободной физической памяти, для повышения производительности ввода-вывода она будет использовать избыточную память в качестве файлового кеша, который на рисунке обозначен баффом/кэшем. В смысле кэш страниц является подмножеством этих воспоминаний.
Когда ОС считывает диск, все содержимое текущей области будет считано в Кэш, так что Кэш может быть удален при следующем чтении обратно на диск.
Однако в системе много файлов, и даже избыточный кэш страниц является очень ценным ресурсом.Операционная система не может случайным образом назначить кэш страниц какому-либо файлу.Нижний уровень Linux предоставляет mmap для сопоставления файл, указанный программой, в виртуальную память (Virtual Memory). ), чтение и запись файла становятся чтением и записью памяти, что позволяет в полной мере использовать кэш страниц. Однако недостаточно использовать кэш страниц только для файлового ввода-вывода: если файл будет считываться и записываться случайным образом, это вызовет много прерываний по ошибке страницы (Page Fault) в виртуальной памяти.
Каждый процесс пользовательского пространства имеет свою собственную виртуальную память.Каждый процесс думает, что у него есть вся его физическая память, но виртуальная память — это только логическая память.Чтобы получить доступ к данным в памяти, их необходимо искать в блоке управления памятью (MMU).Таблицы страниц, которые отображают виртуальную память в физическую память. Если отображаемый файл очень большой, возникает ошибка страницы, когда программа обращается к виртуальной памяти, которая не может быть частично отображена в физическую память, и ОС необходимо прочитать и записать реальные данные дискового файла, а затем загрузить их в память. объем памяти. Поскольку наше приложение не кэширует определенный фрагмент данных, а напрямую обращается к базе данных для запроса данных, а затем записывает результат в кэш, этот процесс относительно медленный.
Однако во время последовательного ввода-вывода области чтения и записи являются горячими точками, которые были интеллектуально кэшированы ОС, и большое количество ошибок страниц не будет прервано.Файловый ввод-вывод почти равен вводу-выводу памяти, а производительность будет конечно улучшить.
Сказав так много о преимуществах кэша страниц, мы также должны упомянуть его недостатки.После того, как ядро выделит доступную память для кэша страниц, свободной памяти будет относительно меньше.Если у программы есть новые требования к выделению памяти или сбой страницы прерывания, бывает, что свободной памяти не хватает, и ядру тоже нужно потратить немного времени, чтобы высвободить память низкотемпературного кэша страниц, что вызовет глюки системы с очень требовательной производительностью.
По поводу mmap скажу еще кое-что, комплексное использование этой функции здесь не описывается, но следует помнить, что вызов mmap и передача fd файла выделяет непрерывный сегмент в адресном пространстве процесса (виртуальная память ).Адрес используется для сопоставления файла, ядро не выделяет реальную физическую память для загрузки файла в память. В конце концов, необходимо выделять память через прерывания сбоя страницы, но это, очевидно, повлияет на производительность, поэтому лучше всего вызвать madvise для передачи стратегии WILLNEED для предварительного нагрева кэша страниц, чтобы эта память не стала холодной и не замерзла. исправлено.
щетка
Чистка обычно делится на: синхронную чистку и асинхронную чистку.
синхронная щетка
После того, как сообщение действительно помещено на диск, оно возвращает успех Продюсеру.Пока диск не поврежден, сообщение не будет потеряно.
Обычно используемый только в финансовых сценариях, этот метод не рассматривается в этой статье, поскольку он не использует преимущества характеристик кэша страниц, RMQ использует метод GroupCommit для оптимизации синхронной очистки диска.
Асинхронная щетка
При чтении и записи файлов кэш страниц используется в полной мере, то есть запись в кэш страниц возвращает успех производителю.Есть два способа асинхронного обновления диска в RMQ, и общий принцип тот же.
Перепрошивка управляется программой и ОС
Сначала поговорим об ОС. Когда программа последовательно записывает файл, он сначала записывается в Кэш. Эта часть была изменена, но не сброшена на диск, что приводит к несоответствиям. Эти несогласованности в памяти называются грязными страницами. .
Если параметр грязной страницы слишком мал, количество флеш-дисков увеличится, а производительность снизится; если параметр грязной страницы слишком велик, производительность улучшится.
На приведенном выше рисунке показана конфигурация системы centos по умолчанию, dirty_ratio — это порог блокировки блокировки, а dirty_background_ratio — неблокировка блокировки. Для повышения производительности рекомендуется увеличить эти два значения, а затем протестировать производительность.
RMQ требует высокой производительности.При отправке сообщения сообщение должно быть записано в кэш страниц, а не напрямую на диск.При получении сообщения сообщение должно быть получено непосредственно из кеша страниц, а не считано с диска из-за к ошибкам страницы.
Что ж, после рассмотрения принципа мы можем увидеть ситуацию ввода-вывода Commit Log и Consume Queue после mmap в RMQ при отправке и получении сообщений.
Логика отправки RMQ
При отправке Производитель не имеет прямого отношения к Очереди на потребление. Как упоминалось выше, все сообщения RMQ будут храниться в журнале фиксации.Чтобы предотвратить хаотическое хранение сообщений, оно будет заблокировано перед записью в журнал фиксации.
После того, как сообщение будет постоянно заблокировано и сериализовано, журнал фиксации записывается последовательно, что часто называют операцией добавления. С Page Cache RMQ будет очень эффективным при написании журнала фиксации.
После сохранения журнала фиксации данные в нем будут отправлены в соответствующую очередь потребления.
Каждая Consume Queue представляет собой логическую очередь, которая добавляется службой ReputMessageService в один цикл потоков, очевидно, написанный последовательно.
Нижний слой логики потребления
При потреблении Consumer не работает напрямую с журналом фиксации, а извлекает данные из очереди потребления.
Порядок извлечения — от старого к новому.В файле каждая очередь потребления читается последовательно, полностью используя кэш страниц.
Простое извлечение Consume Queue не содержит данных, есть только одна ссылка на журнал фиксации, поэтому снова извлеките журнал фиксации.
Журнал фиксации будет выполнять случайное чтение
Однако весь RMQ имеет только один журнал фиксации.Хотя это случайное чтение, оно все же читается упорядоченным образом.Пока вся область все еще находится в области кэша страниц, кэш страниц все еще может быть полностью используется.
Глядя на сеть и диск на реальном MQ, даже если сторона сообщений продолжает читать сообщения от MQ, почти невозможно увидеть, что процесс извлекает данные с диска, а данные отправляются непосредственно из кэша страниц потребителю. через сокет.
Сравните Кафку
Как упоминалось в начале статьи, RMQ заимствует идеи Kafka, а также ломает дизайн Kafka в нижележащем хранилище.
В Kafka есть только один файл для хранения сообщений, называемый Partition (независимо от уточненных сегментов), который выполняет общие обязанности Commit Log и Consume Queue в RMQ, то есть он логически разделен и хранится для улучшения параллелизма потребления. также хранит реальное содержимое сообщения внутри.
Это выглядит идеально. Независимо от того, для производителя или для потребителя, один файл раздела является последовательным вводом-выводом в обычной логике отправки и потребления, в полной мере используя огромное улучшение производительности, обеспечиваемое кэшем страниц. , каждая тема разделена на разделы N. В настоящее время для ОС последовательное чтение и запись такого количества файлов становится случайным чтением и записью при одновременном выполнении.
В это время, не знаю почему, я вдруг вспомнил игру «Ударь крота». Для каждой лунки суслики, которых я ударил, всегда в порядке.Однако, если есть 10 000 лунок, и вы единственный, кто играет, бесчисленное количество сусликов будет входить и выходить из каждой лунки первыми.Это не случайный бой, ученики делают для этой сцены в их умах.
Конечно, студенты с хорошими идеями сразу обнаружили, что Consume Queue RMQ не похож на Kafka, когда очередей много.Хотя каждый файл — это последовательный ввод-вывод, в целом — случайный ввод-вывод. Не забывайте, что Consume Queue RMQ не хранит содержимое сообщения, а любое сообщение занимает 20 байт, поэтому файл можно контролировать очень маленьким, и большая часть доступа по-прежнему относится к кэшу страницы, а не к доступ к диску. При формальном развертывании журнал фиксации и очередь потребления также могут быть размещены на разных физических твердотельных накопителях, чтобы избежать конкуренции операций ввода-вывода между несколькими типами файлов.
сказать в спину
Для получения более замечательных статей, пожалуйста, обратите внимание на мой публичный аккаунт WeChat: технологии Эрика, реки и озера.