Несколько мелочей о MQ (4) Как сделать так, чтобы сообщения не терялись

очередь сообщений

1.мк принцип

Нет дополнительных данных, не менее, больше нет, значит, что сообщения не могут быть неоднократно потребляются, что мы решили в предыдущем разделе; не менее не означает отсутствие потери данных. Если MQ передает очень основные сообщения и поддерживает основной бизнес, то данные не должны быть потеряны в этом сценарии.

2. Сценарии потери данных

Потеря данных обычно делится на два типа: первый заключается в том, что mq теряет сообщение, а другой заключается в том, что сообщение теряется при потреблении. Поговорим о сценарии потери данных у rabbitmq и kafka соответственно.
(1) кролик
A: Производитель потерял данныеКогда производитель отправляет данные в rabbitmq, данные могут быть потеряны из-за проблем с сетью в процессе передачи.
B: rabbitmq сам потерял данныеЕсли постоянство rabbitmq не включено, данные будут потеряны после перезапуска rabbitmq. Необходимо включить постоянство для сохранения сообщений на диск, чтобы даже в случае зависания rabbitmq ранее сохраненные данные автоматически читались после восстановления, а общие данные не терялись. За исключением крайне редких случаев, rabbitmq зависает до того, как успеет сохраниться, что может привести к некоторой потере данных.
C: потребитель потерял данныеОсновная причина в том, что когда потребитель потребляет, он только что потреблен и еще не обработан, в результате потребитель зависает, поэтому после перезапуска rabbitmq думает, что вы его потребили, а потом теряет данные.

rabbitmq数据丢失示意图.png
(2) кафка
A: Производитель потерял данныеПроизводители не устанавливают соответствующую стратегию, потеря данных при передаче.
B: кафка потеряла данныеБолее распространен сценарий, когда брокер в Kafka не работает, а затем переизбирается лидер раздела. Если ведомый не успел синхронизировать данные в это время, ведущий бросит трубку, и тогда ведущим становится ведомый, и он потеряет часть данных.
C: Потребители теряют данныеПотребитель потребляет данные, а затем автоматически отправляет смещение, чтобы сообщить kafka, что вы использовали сообщение.Когда вы готовы обработать сообщение, вы вешаете трубку, и сообщение теряется.

kafka丢失数据示意图.png

3. Как предотвратить потерю сообщений

(1) кролик
A: Производитель теряет сообщение
①: Вы можете использовать rabbitmq для обеспечения функции транзакции, то есть производитель открывает транзакцию перед отправкой данных, а затем отправляет сообщение.Если сообщение не будет успешно получено rabbitmq, производитель получит ненормальную ошибку, а потом транзакцию можно откатить.Потом попробовать отправить повторно,если сообщение получено,то вещь можно коммитить.

  channel.txSelect();//开启事物
  try{
      //发送消息
  }catch(Exection e){
      channel.txRollback();//回滚事物
      //重新提交
  }

недостаток:Транзакция rabbitmq была открыта, и она станет операцией синхронной блокировки. Производитель заблокирует и будет ждать успешной передачи. Слишком высокая производительность приведет к снижению пропускной способности.

②: можно включить режим подтверждения. После того, как производитель установил режим подтверждения для включения, каждому написанному сообщению будет присвоен уникальный идентификатор, а затем, как записать его в rabbitmq, rabbitmq отправит вам сообщение подтверждения, сообщая вам, что сообщение отправлено ОК; Если RabbitMQ не может обработать сообщение, он вызовет интерфейс nack, чтобы сообщить вам, что сообщение не удалось, и вы можете повторить попытку. И вы можете комбинировать этот механизм, чтобы знать, что вы сохраняете идентификатор каждого сообщения в памяти.Если обратный вызов сообщения не был получен через определенный период времени, вы можете отправить его повторно.

    //开启confirm
    channel.confirm();
    //发送成功回调
    public void ack(String messageId){
      
    }

    // 发送失败回调
    public void nack(String messageId){
        //重发该消息
    }

они разныеПосле синхронизации механизма транзакции вы подали забитые вещи в прямом эфире, но подтвердите механизм асинхронного и затем могут отправлять следующее сообщение после отправки сообщения, обратный вызов будет информировать успех Rabbitmq. Производители обычно избегают этой потери, используются подтверждают механизм.
B: rabbitmq сам потерял данныеУстановить сохранение сообщения на диск. Существует два шага для настройки постоянства:
① При создании очереди установите ее как постоянную, чтобы rabbitmq мог гарантировать, что метаданные очереди будут сохранены, но данные в очереди не будут сохранены.
②При отправке сообщения для параметра deliveryMode сообщения устанавливается значение 2, поэтому сообщение будет установлено в постоянный режим, а rabbitmq сохранит сообщение на диск. Оба должны быть включены одновременно.

Более того, персистентность может сочетаться с механизмом подтверждения производства: только после того, как сообщение будет сохранено на диске, производитель будет уведомлен о подтверждении, поэтому даже если rabbitmq зависнет до сохранения и данные будут потеряны, производитель не сможет получить подтверждение. обратный вызов. Сообщение будет отправлено повторно.
C: Потребители теряют данныеИспользуя механизм подтверждения, предоставляемый rabbitmq, сначала отключите автоматическое подтверждение RabbitMQ, а затем каждый раз вручную вызывайте подтверждение в коде, убедившись, что сообщение обработано. Таким образом, вы можете избежать подтверждения сообщения до его обработки.

(2) кафка
A: Потребитель потерял данныеОтключите автоматическую фиксацию смещений и вручную фиксируйте смещения после их самостоятельной обработки, чтобы данные не были потеряны.

B: кафка потеряла данныеКак правило, необходимо установить 4 параметра, чтобы гарантировать, что сообщение не будет потеряно:
① установить в темуreplication.factorПараметры: это значение должно быть больше 1, что указывает на то, что каждый раздел должен иметь не менее 2 копий.

②Установить на сервере kafkamin.isync.replicasПараметр: это значение должно быть больше 1, что означает, что лидер должен, по крайней мере, осознавать, что есть по крайней мере один ведомый, поддерживающий связь с самим собой для нормальной синхронизации данных, чтобы гарантировать, что после ведомого все еще есть ведомый. ведущий вешает трубку.

③Установить на стороне производителяacks=all: указывает, что каждый фрагмент данных должен быть записан во все реплики, прежде чем его можно будет считать успешным.

4 установка у производителяretries=MAX(Большая ценность, указывая на неограниченную попытку): сказал, что это то, что когда-то написано, есть неограниченное повторение

C: Производитель потерял данныеЕсли вы установите ack=all в соответствии с вышеизложенным, вы не потеряете данные.Требование состоит в том, чтобы ваш лидер получил сообщение, а все подписчики синхронизировались с сообщением, прежде чем вы посчитаете, что запись прошла успешно. Если это условие не выполняется, производитель будет автоматически и непрерывно повторять попытки бесконечное количество раз.

Предыдущий"Как убедиться, что сообщения не используются повторно
Следующий"Как обеспечить порядок выполнения сообщения