我知道可以使用多个线程来使用SQS队列。我想保证每条消息都会消耗一次。我知道可以更改消息的可见性超时,例如,等于我的处理时间。如果我的进程花费的时间超过可见性超时(例如连接速度慢),则其他线程可以使用相同的消息。
保证邮件处理一次的最佳方法是什么?
答案 0 :(得分:23)
保证邮件处理一次的最佳方法是什么?
您要求保证 - 您赢得 。您可以将消息处理的可能性降低多次非常小,但您无法获得保证。
我将解释为什么以及减少重复的策略。
在大多数情况下,通过利用SQS message visibility timeout,从这些来源重复的可能性已经相当小 - 比如小百分之几。
如果处理副本确实不是那么糟糕(strive to make your message consumption idempotent!),我认为这还不错 - 减少重复的可能性更加复杂且可能更昂贵...
好的,这里我们沿着兔子洞走下去......在高层,您需要为您的消息分配唯一的ID,并在开始处理之前检查正在进行或已完成的ID的原子缓存:< / p>
答案 1 :(得分:1)
在收到消息时,将消息或对消息的引用存储在消息ID上具有唯一约束的数据库中。如果表中存在ID,您已经收到它,并且由于唯一约束,数据库将不允许您再次插入它。
答案 2 :(得分:1)
您可以对邮件和批处理使用setVisibilityTimeout(),以便延长可见时间,直到线程完成处理邮件。
这可以通过使用scheduledExecutorService来完成,并在初始可见时间的一半之后安排可运行事件。下面的代码片段在visibilityTime的每一半创建并执行VisibilityTimeExtender,其周期为可见时间的一半。 (时间应保证消息处理,使用visibilityTime / 2进行扩展)
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
ScheduledFuture<?> futureEvent = scheduler.scheduleAtFixedRate(new VisibilityTimeExtender(..), visibilityTime/2, visibilityTime/2, TimeUnit.SECONDS);
VisibilityTimeExtender必须实现Runnable,并且是您更新新可见性时间的地方。
当线程处理完消息后,您可以将其从队列中删除,并调用futureEvent.cancel(true)来停止预定的事件。
答案 3 :(得分:0)
AWS SQS API不会自动&#34;消费&#34;用API等读取时的消息。开发人员需要拨打电话来自行删除邮件。
SQS确实有一个功能调用&#34;重新启动策略&#34;作为“死信队列设置”的一部分&#34;。您只需将读取请求设置为1.如果使用过程崩溃,则后续读取同一消息会将消息放入死信队列。
SQS队列可见性超时最长可设置为12小时。除非您有特殊需要,否则您需要实现将消息处理程序存储在数据库中以允许其进行检查的过程。