Встречается на 2% собеседований по Java

Как гарантировать, чтобы несколько консьюмеров не обрабатывали несколько событий от одной сущности одновременно

Используйте механизм блокировок или распределённые очереди с разделением по ключу. Например, в Kafka можно назначить партицию по ID сущности, гарантируя обработку событий одной сущности одним консьюмером:

java
// Kafka producer - отправка в партицию по ID сущности
producer.send(new ProducerRecord<>("topic", entityId, event));

// Kafka consumer - каждая партиция обрабатывается одним консьюмером
@KafkaListener(topicPartitions = @TopicPartition(topic = "topic"))
public void consume(ConsumerRecord<String, Event> record) {
    // Обработка
}

Альтернативно, можно использовать pessimistic locking в БД:

java
@Entity
public class Entity {
    @Version
    private Long version; // Оптимистичная блокировка
    
    @OneToMany(mappedBy = "entity")
    private List<Event> events;
}

// Или явная блокировка:
entityManager.find(Entity.class, id, LockModeType.PESSIMISTIC_WRITE);

Для распределённых систем подойдёт Redis с атомарными операциями:

java
// Попытка захватить блокировку
Boolean locked = redisTemplate.opsForValue().setIfAbsent("lock:"+entityId, "1", 10, TimeUnit.SECONDS);
if (locked) {
    try {
        // Обработка события
    } finally {
        redisTemplate.delete("lock:"+entityId);
    }
}
Sophi
Софи собрала все вопросы. Тренируйся и получай
офферы быстрее!
Попробовать бесплатноArrow

Следующий вопрос

Это единственный вопрос по вашему фильтру

как отвечать на вопрос
пример собеседования
фреймворки на собеседовании
типичные вопросы junior
интервью вопросы и ответы