предисловие
Моя предыдущая компания занималась кейтерингом, поэтому во время пиковых обедов в полдень и вечером параллелизм системы нельзя недооценивать. Чтобы быть в безопасности, компания предусматривает, что все отделы должны дежурить по очереди во время еды, чтобы предотвратить своевременное решение онлайн-проблем.
Я показал системной команде в задней части шеф-повара, который относится к нисходящему бизнесу заказов. После того, как пользователь закончит, система заказов пройдетkafka
Сообщение отправляется в нашу систему.После того, как система прочитает сообщение, она выполняет обработку бизнес-логики, сохраняет данные о заказе и блюде, а затем отображает их клиенту планирования овощей. Таким образом, шеф-повар знает, какие блюда должны быть приготовлены для какого заказа, и когда некоторые блюда будут готовы, их можно подать через систему. Система автоматически информирует официанта о подаче блюда, и если официант завершил подачу блюда и изменил статус подачи блюда, пользователь будет знать, какие блюда были поданы, а какие еще не поданы. Эта система может значительно повысить эффективность от кухни до пользователя.
Оказывается, ключом ко всему этому является промежуточное программное обеспечение сообщений:kafka
, если с ним возникнут проблемы, это напрямую повлияет на работу системы кухонного дисплея.
Недавно я случайно получил заметку о чистке, написанную крупным производителем BAT, которая открыла мне сразу вторую линейку Ren и Du, и я все больше чувствую, что алгоритм не так сложен, как я себе представлял.Заметки о чистке, написанные боссом BAT, позвольте мне мягко получить предложение
Далее я поговорю с вами об использованииkafka
Какие ямы два года вошли?
проблема последовательности
1. Почему гарантируется порядок сообщений?
В начале в нашей системе было очень мало мерчантов, чтобы быстро реализовать функцию, мы особо не задумывались. Поскольку это промежуточное программное обеспечение сообщенийkafka
Коммуникация, когда система заказов отправляет сообщение, детали заказа помещаются в тело сообщения, и нашей системе отображения кухни нужно только подписатьсяtopic
, вы можете получить соответствующие данные сообщения, а затем обработать свой собственный бизнес.
Однако в этом плане есть ключевой элемент:Чтобы гарантировать порядок сообщений.
Зачем?
Заказ имеет множество состояний, таких как: заказ, оплата, завершение, отмена и т.д., нельзя下单
Если сообщение не прочитано, оно будет прочитано первым支付
или撤销
Если это так, не будут ли данные запутанными?
Что ж, кажется, необходимо гарантировать порядок сообщений.
2. Как гарантировать порядок сообщений?
мы все знаемkafka
изtopic
является неупорядоченным, ноtopic
содержит несколькоpartition
, каждыйpartition
Интерьер в порядке.Таким образом, становится понятной идея: пока производитель пишет сообщение, он пишет одно и то же сообщение по определенным правилам.partition
, разные потребители читают по-разномуpartition
сообщения, порядок создания и потребления сообщений гарантируется.
Это то, что мы сделали в начале, то же самое商户编号
сообщения, написанные на тот жеpartition
,topic
создан в4
Кусокpartition
, а затем развернут4
потребительские узлы, которые составляют消费者组
,Одинpartition
Соответствует потребительскому узлу. Теоретически эта схема может гарантировать порядок сообщений.
Все вроде бы прошло «бесшовно», и мы вышли в онлайн «плавно».
3. Происходит авария
Эта функция была онлайн некоторое время, и поначалу она была относительно нормальной.
Однако хорошие времена длились недолго, и вскоре пошли жалобы от пользователей, мол, на клиенте планирования овощей не видно некоторых заказов и блюд, а также невозможно планировать блюда.
Я нашел причину: в то время сеть компании часто была нестабильной, бизнес-интерфейс время от времени отключался, а бизнес-запрос иногда не мог подключиться к базе данных.
Эта ситуация правильная顺序消息
удар, так сказать毁灭性
из.
Почему ты это сказал?
Предположим, система заказов отправляет три сообщения: «оформить заказ», «оплатить» и «завершить».Сообщение «заказ» не было обработано нашей системой по сетевым причинам, и данные следующих двух сообщений не могут быть сохранены в базе данных, поскольку только данные сообщения «заказ» являются полными данными, а другие типы сообщения только обновляют статус.
К тому же мы не делали失败重试机制
, что усугубляет проблему. Проблема заключается в следующем: если данные сообщения «заказ» не сохраняются в базе данных, пользователь никогда не увидит заказ и блюда.
Так как же решить эту насущную проблему?
4. Процесс разрешения
Наша первоначальная идея была такова: когда потребитель обрабатывает сообщение, если обработка не удалась, немедленно повторить попытку 3-5 раз. Но что, если некоторые запросы выполняются в 6-й раз? Невозможно повторять все время.Этот механизм синхронного повтора блокирует чтение сообщений о заказах других продавцов.
Очевидно, используя вышеуказанное同步重试机制
В нештатной ситуации это серьезно повлияет на скорость потребления сообщения потребителем и снизит его пропускную способность.
Таким образом, мы должны использовать异步重试机制
.
Если используется механизм асинхронных повторных попыток, ошибочное сообщение должно быть сохранено в重试表
вниз.
Но тут же появилась новая проблема:Как сохранить сообщение только с гарантией заказа?
Это правда, что сохранение сообщения не может гарантировать порядок.Если сообщение «заказ» не удается, нет времени на асинхронную повторную попытку. В этот момент сообщение «платеж» потребляется, и его нельзя использовать в обычном режиме.
В этот момент «платежное» сообщение должно ожидать, и время от времени следует оценивать, были ли потреблены сообщения перед ним?
Если вы это сделаете, возникнут две проблемы:
- Сообщению «Оплата» предшествует сообщение «Заказ», которое относительно простое. Но если перед сообщением определенного типа есть N видов сообщений, то сколько раз нужно судить?Это суждение слишком сопряжено с системой порядка, что равносильно переносу части логики их системы на нашу система.
- Влияют на скорость потребления потребителей
На этом этапе появляется более простое решение: когда потребители обрабатывают сообщения, они сначала определяют订单号
существует重试表
Есть ли данные, если есть, сохраните текущее сообщение напрямую重试表
. Если нет, выполните бизнес-обработку.Если возникает исключение, сохраните сообщение в重试表
.
Позже мы используемelastic-job
учредил失败重试机制
, если повторить7
Если это не удается после нескольких раз, статус сообщения помечается как失败
, чтобы уведомить разработчика по электронной почте.
Наконец-то из-за нестабильности сети была решена проблема, что пользователи не могли видеть некоторые заказы и блюда на клиенте Caicai. Теперь продавцы иногда максимум откладывают просмотр блюд, что намного лучше, чем не видеть блюда постоянно.
ожидание сообщения
Благодаря маркетинговому продвижению отдела продаж в нашей системе появляется все больше и больше продавцов. Далее следует, что количество сообщений становится все больше и больше, что приводит к тому, что потребители не могут их обработать, и часто возникает скопление сообщений. Воздействие на продавцов очень интуитивное, и просмотр заказов и блюд в клиенте Caicai может занять полчаса. Минуту-другую терплю, а полсообщения задерживается, терпеть не могу каких-то сварливых торговцев, поэтому сразу пожаловался. За это время к нам часто поступали жалобы от продавцов на задержку заказов и блюд.
Хотя, добавив服务器节点
может решить проблему, но согласно практике компании, чтобы сэкономить деньги, сначала необходимо выполнить оптимизацию системы, поэтому мы начали消息积压
Решение проблем.
1. Тело сообщения слишком большое
несмотря на то чтоkafka
Заявлено о поддержке百万级的TPS
, но отproducer
отправить сообщениеbroker
нужна сетьIO
,broker
Для записи данных на диск требуется диск один разIO
(операция записи),consumer
отbroker
Сначала получить сообщение через дискIO
(операция чтения), снова пройтись по сетиIO
.
Простое сообщение от производства до процесса потребления должно пройти через2次网络IO
и2次磁盘IO
. Если тело сообщения будет слишком большим, это неизбежно увеличит затраты времени на ввод-вывод, что повлияет на скорость производства и потребления Kafka. В результате того, что потребитель работает слишком медленно, будет отставание по сообщениям.
Помимо вышеперечисленных проблем,消息体过大
, это также приведет к пустой трате места на диске сервера.Если вы не будете осторожны, может не хватить места на диске.
На данный момент мы подошли к моменту, когда нам нужно оптимизировать проблему слишком большого тела сообщения.
Как его оптимизировать?
Мы реорганизовали бизнес, нет необходимости знать порядок中间状态
просто знаешь最终状态
Вот и все.
Так хорошо, мы можем спроектировать это так:
- Тело сообщения, отправляемое системой заказов, содержит только ключевую информацию, такую как идентификатор и статус.
- После того, как кухня отображает сообщение о потреблении системы, она вызывает интерфейс запроса сведений о заказе системы заказов через идентификатор для получения данных.
- Система отображения кухни оценивает, есть ли данные заказа в базе данных, если нет, то он будет помещен на склад, а если есть, то будет обновлен.
Конечно же, после этой корректировки проблема с бэклогом сообщений не появлялась снова в течение длительного времени.
2. Необоснованные правила маршрутизации
Не радуйтесь, как-то в полдень другой продавец пожаловался, что заказ и блюда задерживаются. Когда мы проверили тему Кафки, там снова было невыполненное сообщение.
Но на этот раз это немного странно, не всеpartition
На нем накопилась задолженность по сообщениям, но только одна.
Сначала я думал, что это потребляет, чтоpartition
Что не так с узлом сообщения. Но после проверки ничего аномального обнаружено не было.
Это странно, в чем проблема?
Позже я проверил журнал и базу данных, есть несколько порядков бизнеса, особенно большие, всего несколько предприятий, которые назначены для того жеpartition
, таким образомpartition
сообщений, чем другиеpartition
Намного больше.
Только потом мы поняли, что при отправке сообщения нажать商户编号
маршрутизацияpartition
Правила необоснованны и могут привести к некоторымpartition
Потребителям приходится обрабатывать слишком много сообщений, а некоторыеpartition
Однако, поскольку сообщений слишком мало, потребители простаивают.
Чтобы избежать этого неравномерного распределения, нам нужно настроить правила маршрутизации для отправки сообщений.
Мы подумали об этом, использование номера заказа для маршрутизации относительно более единообразно, и не будет ситуации, когда один заказ отправляет много сообщений. Разве что есть ситуация, когда кто-то продолжает добавлять еду, но добавление еды стоит денег, так что по факту сообщений по одному и тому же заказу не много.
После регулировки нажмите订单号
маршрут к другомуpartition
, сообщение с одним и тем же номером заказа каждый раз отправляется одному и тому жеpartition
.
После настройки проблема бэклога сообщений долго не появлялась. За это время количество наших торговцев росло очень быстро и становилось все более и более многочисленным.
3. Цепные реакции, вызванные пакетными операциями
Можно сказать, что в сценариях с высоким параллелизмом проблема невыполненных сообщений идет рука об руку, и на самом деле нет никакого способа ее кардинального решения. На первый взгляд, это было решено, но я не знаю, когда оно всплывет однажды, например, в этот раз:
Однажды днем товар пришел и сказал: несколько продавцов пожаловались, сказали, что посуда задерживается, и быстро проверяют причину.
На этот раз проблема оказалась несколько странной.
Почему ты это сказал?
Во-первых этот момент немного странный, обычно проблемный, разве это не все в полдень или ночью? Как этот вопрос появился днем?
Основанный на моем прошлом опыте, я напрямую смотрел наkafka
изtopic
, и, конечно же, выше накопилась задолженность по сообщениям, но на этот раз каждыйpartition
отставание十几万
сообщений не потребляются, а количество сообщений под давлением увеличилось за последнее время.几百倍
. Отставание новостей на этот раз крайне необычно.
Я быстро проверил сервисный мониторинг, чтобы увидеть, не повесил ли потребитель трубку, но, к счастью, этого не произошло. Снова проверил сервисный журнал и не нашел никаких исключений. В это время я был немного смущен, и я решился на удачу и спросил группу заказа, что случилось днем? Они сказали, что во второй половине дня была акция, и они выполнили задание по обновлению информации о заказах у некоторых продавцов партиями.
В это время я внезапно проснулся, как во сне, это была проблема, вызванная тем, что они посылали сообщения пачками в JOB. Почему нас не уведомили? Это так жалко.
Хотя я знаю причину проблемы, это отставание передо мной.十几万
Как следует обрабатывать сообщение?
В этот момент, если вы напрямую увеличитеpartition
Количество недостаточно, исторические сообщения были сохранены до 4 фиксированныхpartition
, на новый адрес будут отправляться только новые сообщения.partition
. Мы ориентируемся на существующий раздел.
Плюс прямой сервисный узел не работает, т.к.kafka
разрешить несколькоpartition
один из той же группыconsumer
потребления, но не позволяетpartition
сгруппированы по несколькимconsumer
Потребление может привести к пустой трате ресурсов.
Вроде только с многопоточностью.
Чтобы срочно решить проблему, я изменил использование пула потоков для обработки сообщений, а основные потоки и максимальное количество потоков настроены как50
.
После корректировки, конечно же, количество невыполненных сообщений продолжало уменьшаться.
Но в это время появилась более серьезная проблема: я получил тревожное письмо, и два узла системы заказов были отключены.
Вскоре ко мне подошли мои коллеги из группы заказов и сказали, что параллелизм нашей системы, вызывающей их интерфейс запросов заказов, резко увеличился, что в несколько раз больше, чем ожидалось, что привело к зависанию 2 сервисных узлов. Интегрировали функцию запроса в отдельный сервис, развернули 6 нод и повесили 2 ноды, если не обработают, остальные 4 ноды тоже зависнут. Службу заказов можно назвать основной службой компании, если она зависнет, компания много потеряет, а ситуация крайне актуальна.
Чтобы решить эту проблему, количество потоков можно только сначала уменьшить.
К счастью, количество потоков может быть переданоzookeeper
Динамически настроенный, я отрегулировал количество основных потоков до8
, количество основных потоков было изменено на10
Кусок.
Позже эксплуатация и техническое обслуживание перезапустили два узла, на которых обслуживание заказов было приостановлено, и нормализовали его, на всякий случай добавили еще два узла. Для того, чтобы не было проблем с обслуживанием заказов, поддерживается текущая скорость потребления, а отставание сообщений в системе отображения задней кухни возвращается к норме через 1 час.
Позже мы провели обзорную встречу и пришли к выводу:
- Пакетная операция системы заказов должна заранее уведомлять нижестоящую системную команду.
- Команда нижестоящей системы должна выполнять стресс-тестирование при вызове интерфейса запроса заказа в нескольких потоках.
- На этот раз тревога звонит на службу запроса заказа. Это основная служба компании, и она недостаточно хороша, чтобы ответить на высокую и легкую сцену, она должна быть оптимизирована.
- Следите за бэклогом сообщений
Кстати, для сценариев, требующих строгой гарантии порядка сообщений, пул потоков можно изменить на несколько очередей, каждая из которых обрабатывается одним потоком.
4. Таблица слишком большая
Чтобы предотвратить повторное возникновение проблемы задержки сообщений, потребители обрабатывают сообщения с помощью многопоточности.
Но однажды в полдень мы все же получили много тревожных писем, напоминающих о том, что в kafka есть отставание от тематических сообщений. Мы выясняем причину, а в это время подошел товар и сказал: Другой продавец пожаловался, что блюда задерживаются, поторопитесь и посмотрите. На этот раз она выглядела немного нетерпеливой и много раз оптимизировала его, но все равно возникала та же проблема.
С точки зрения непрофессионала:Почему ту же проблему нельзя решить?
На самом деле они не знают страданий техники.
На первый взгляд симптомы проблемы те же.Есть задержка блюд.Они знают,что это вызвано отставанием информации. Но они не знают глубинных причин.На самом деле причин задержки сообщений много. Это может быть распространенной проблемой при использовании ПО промежуточного слоя сообщений.
Я молчал и мог только стиснуть зубы и найти причину.
Позже я проверил журнал и обнаружил, что потребителям потребовалось много времени, чтобы обработать сообщение.2秒
. Ранее500毫秒
, теперь как это может стать2秒
Шерстяная ткань?
Странно, код потребителя не сильно доработан, почему так происходит?
Я проверил таблицу онлайн-меню, и объем данных одной таблицы прибыл.几千万
, то же самое верно и для других таблиц меню, и теперь в одной таблице сохраняется слишком много данных.
Наша группа разобралась с делами, по сути блюда только отображаются на стороне клиента.3天
возможно.
С этим легко справиться, наш сервер экономит多余的数据
, лишние данные в таблице лучше заархивировать. Таким образом, администратор баз данных помог нам архивировать данные и оставить только самые последние.7天
Данные.
После этой корректировки проблема отставания новостей была решена, а былое спокойствие восстановлено.
конфликт первичного ключа
Не слишком радуйтесь, есть и другие проблемы, такие как: электронное письмо с сигналом тревоги часто сообщает об исключениях базы данных: Duplicate entry '6' for key 'PRIMARY'
, скажем, конфликт первичного ключа.
Эта проблема обычно возникает из-за того, что имеется более двух SQL-запросов с одним и тем же первичным ключом и данные вставляются одновременно.После того как первая вставка будет успешной, вторая вставка сообщит о конфликте первичного ключа. Первичный ключ таблицы уникален и не допускает дублирования.
Я тщательно проверил код и обнаружил, что логика кода сначала запросит, существует ли заказ из таблицы в соответствии с первичным ключом, и обновит статус, если он существует, и вставит данные, если он не существует, без проблем.
Это суждение полезно, когда объем параллелизма невелик. Однако в сценарии с высокой степенью параллелизма два запроса обнаруживают, что порядок не существует в одно и то же время, один запрос вставляет данные первым, а другой запрос вставляет данные, возникает исключение конфликта первичного ключа.
Наиболее распространенным способом решения этой проблемы является:加锁
.
Я тоже так думал в начале, добавление пессимистической блокировки базы данных определенно неприемлемо, это слишком сильно повлияет на производительность. Добавление оптимистической блокировки базы данных на основе оценки номера версии обычно используется для операций обновления, и такие операции вставки в основном не используются.
Остальные могут использовать только распределенные блокировки.Наша система использует Redis, и мы можем добавить распределенные блокировки на основе Redis для блокировки номера заказа.
Но после того, как мы думаем об этом внимательно:
- Добавление распределенных блокировок также может повлиять на скорость обработки сообщений потребителями.
- Потребители полагаются на Redis.Если Redis имеет тайм-аут сети, наш сервис будет трагичным.
Так что я тоже не планирую использовать распределенные блокировки.
Вместо этого выберите использование mysqlINSERT INTO ...ON DUPLICATE KEY UPDATE
грамматика:
INSERT INTO table (column_list)
VALUES (value_list)
ON DUPLICATE KEY UPDATE
c1 = v1,
c2 = v2,
...;
Сначала он попытается вставить данные в таблицу и обновить поле, если первичный ключ конфликтует.
поставить предыдущийinsert
После трансформации заявления больше не было основных ключевых конфликтных вопросов.
Задержка master-slave базы данных
Вскоре после этого я получил жалобу от продавца, что после размещения заказа я мог видеть заказ в приложении Caicai, но блюда, которые я видел, были неполными, а иногда даже данные о заказе и блюде не были видны.
Эта проблема отличается от прошлой, в соответствии с прошлым опытом в первую очередьkafka
изtopic
В Китае отставания по новостям нет, но на этот раз отставания нет.
Я снова проверил журнал обслуживания и обнаружил, что некоторые данные, возвращаемые интерфейсом системы заказов, были пустыми, а некоторые возвращали только данные заказа, но не данные блюда.
Это очень странно, я пройду через коллег группы заказа. Они тщательно устраняют неполадки в службе, не обнаруживая проблем. В это время думаем что будет, не будет ли проблем с базой, иди найдиDBA
. В самом деле,DBA
Обнаружено, что основная база данных базы данных синхронизирует данные с подчиненной базой данных, и иногда возникают задержки из-за сетевых причин, а иногда задержки3秒
.
Если наш бизнес-процесс занимает менее3秒
, при вызове интерфейса запроса сведений о заказе данные могут быть не найдены или найденные данные могут быть не самыми последними.
Эта проблема очень серьезная и вызовет прямые ошибки в наших данных.
Для решения этой проблемы мы также добавили重试机制
. При вызове интерфейса для запроса данных, если возвращаемые данные пусты или возвращается только заказ без блюд, добавить重试表
.
После корректировки проблема с жалобой продавца была решена.
Повторное потребление
kafka
При использовании сообщений поддерживаются три режима:
- не более одного раза
Максимум один раз. Убедитесь, что каждое сообщение для каждого сообщения успешно до обработки потребления. Сообщения могут быть потеряны, но не дублированы.
- хотя бы один раз режим
Хотя бы один раз. Перед фиксацией убедитесь, что каждое сообщение успешно обработано. Сообщения не теряются, но могут дублироваться.
- режим ровно один раз
Прошел ровно один раз. Смещение используется как уникальный идентификатор для одновременной обработки сообщения, и гарантируется атомарность обработки. Сообщения обрабатываются только один раз, не теряются и не дублируются. Но это трудно сделать таким образом.
kafka
Режим по умолчаниюat least once
, но этот режим может вызвать проблемы с повторным потреблением, поэтому наша бизнес-логика должна быть разработана идемпотентной, иначе могут быть сгенерированы повторяющиеся данные.
И наш бизнес-сценарий сохраняет данные, используяINSERT INTO ...ON DUPLICATE KEY UPDATE
Синтаксис вставки, когда он не существует, и обновления, когда он существует, естественным образом поддерживает идемпотентность.
Проблемы потребления в нескольких средах
Наша онлайн-среда была разделена на:pre
(предрелизная среда) иprod
(производственная среда), две среды используют одну и ту же базу данных и один и тот же кластер kafka.
Следует отметить, что в конфигурацииkafka
изtopic
Если вы хотите добавить префикс, чтобы различать разные среды. Предварительная среда начинается с pre_, например: pre_order, а производственная среда начинается с prod_, например: prod_order, чтобы предотвратить объединение сообщений в разных средах.
Но как только эксплуатация и техническое обслуживаниеpre
Узел переключения среды, настройкаtopic
Когда совпадение было неправильным, оно было сопоставленоprod
изtopic
. Только в этот день у нас есть новая функция наpre
окружение. Результаты трагедии,prod
Некоторые сообщенияpre
относящийся к окружающей средеconsumer
потребляется, и из-за корректировки тела сообщения, в результате чегоpre
относящийся к окружающей средеconsumer
Обработка сообщения продолжает давать сбой.
В результате некоторые сообщения теряются в производственной среде. Но, к счастью, в итоге потребитель производственной среды сбрасывается наoffset
, повторное чтение этой части сообщения решают проблему без особых потерь.
постскриптум
В дополнение к вышеперечисленным проблемам я также столкнулся:
-
kafka
изconsumer
Использование механизма автоматического подтверждения, в результате чегоcpu使用率100%
. -
kafka
один из кластеровbroker
Узел зависает, и снова зависает после перезапуска.
Недавно я случайно получил заметку о чистке, написанную крупным производителем BAT, которая открыла мне сразу вторую линейку Ren и Du, и я все больше чувствую, что алгоритм не так сложен, как я себе представлял.Заметки о чистке, написанные боссом BAT, позвольте мне мягко получить предложение
Эти два вопроса немного сложны, поэтому я не буду перечислять их один за другим.Заинтересованные друзья могут подписаться на мой официальный аккаунт и добавить мой WeChat, чтобы найти меня для приватного чата.
Большое спасибо за использование промежуточного программного обеспечения сообщений в течение этих двух лет.kafka
Несмотря на то, что я столкнулся со многими проблемами, наступил на многие ямы и совершил много обходных путей, реальный опыт позволил мне накопить много ценного опыта и быстро расти.
фактическиkafka
Это очень хорошее промежуточное программное обеспечение для сообщений.Большинство проблем, с которыми я сталкивался, неkafka
Собственная проблема (за исключением того, что 100% загрузка процессора вызвана его ошибкой).
Последнее слово (пожалуйста, обратите внимание, не проституируйте меня по пустякам)
Если эта статья оказалась для вас полезной или поучительной, отсканируйте QR-код и обратите внимание, ваша поддержка — самая большая мотивация для меня продолжать писать.
Попросите в один клик три ссылки: лайк, вперед и смотреть.
Следите за официальной учетной записью: [Су Сан сказал о технологии], ответьте в официальной учетной записи: интервью, артефакт кода, руководство по разработке, управление временем имеют большие преимущества для фанатов, и ответьте: присоединяйтесь к группе, вы можете общаться и учиться со старшими многих производители БАТ.