问题描述:
我们有一个传入消息队列(称为A),在经过一些预处理之后,这些消息将保存到DB。 预处理之后,将向交换机(称为B)产生新消息,该消息指示已完成预处理,并且可以继续进行另一个处理步骤。 我们有一台服务器已预订到B交换下的队列,并使用就绪消息。
我们不时要启动另一台服务器,并模拟从某个时间T(可能是2年或更久)开始接收就绪消息。 为此,我们需要以某种方式重放保存在数据库中的较旧消息,并在完成此操作后,应将新队列连接到B交换机并继续处理新消息。 这是卡夫卡支持的做法,但是在卡夫卡中存储多年的消息不是一个很好的方法。
我们想到的解决方案及其问题
解决方案: 我们想到的第一个解决方案是为新服务器创建一个新队列,生成从时间T开始从DB到该队列的所有消息,然后将该队列连接到交换机。
问题: 该解决方案的问题在于,在完成从DB的生产之后以及将队列连接到B交换机之前,我们可能会错过一些到达的消息。同样,如果从数据库重播的服务崩溃使事情变得复杂,我们应该保存一些状态,以指示我们现在在重播序列中的位置。
解决方案: 一个更强大的解决方案是为新服务器创建一个新的优先级队列,从时间T开始从优先级为1的数据库中产生所有消息,将该队列连接到交换机,然后再进行一次扫描以查找数据库中的新消息。并优先处理它们。
问题: 在此解决方案中,可能在某些极端情况下,我们多次生成同一条消息,并且顺序可能是错误的,但可能会没事。该解决方案的主要问题是,从数据库中生成数据非常快,但消耗却不是那么快,这意味着在服务器使用之前,新队列在很长一段时间内将非常大。此外,就像在以前的解决方案中一样,如果重放服务崩溃可能会导致问题,则新消息将取代旧消息,并且需要保存停止重放的状态。
解决方案: 另一个解决方案是立即重播所有消息,而不是立即重播所有消息,并且在服务器请求时分批处理,并且当没有其他重播内容时,请执行解决方案2的最后步骤(连接以再次交换并重新扫描数据库)。
问题: 该解决方案的问题是知道何时请求新批次,如果服务器崩溃,使用接收到的消息计数器可能会很棘手,我们需要将该数字保存在某些数据库中,这样会使事情变得复杂。等待空队列也很棘手,在考虑队列为空之前,我们应该等待多长时间没有消息?
解决方案: 另一种方法(完全不同)是,服务器将分批轮询就绪的数据库,而不是使用就绪的交换和队列。每个服务器将保存他消耗的最后一条消息,并从该点开始轮询另一批。
问题: 这种解决方案很简单,但是这种方法的缺点是消息准备到服务器轮询之间的延迟。
对大家的问题:
谢谢!