持久队列内存管理
当前的 3.x 代码在处理大量未确认消息的队列时可能会出现问题;由于从队列中的多个点进行消费、消费者不断进出、选择器仅匹配队列中的某些点等因素,导致代码非常复杂。
本页概述了设计方案。
目标区域
为每个消费者维护 TargetLists(已匹配一个或多个消费者选择器且将用于尝试将消息调度到消费者 DispatchArea 的消息)。当消息从队列到达时,TargetEntry 对象被添加到 TargetList 中。
TargetEntry 可以包含直接的消息引用或指向缓存中条目的 CacheReference。
提前加载
每个 TargetList 都具有一个水印,用于指示第一个作为 CacheReference 的 TargetEntry。其理念是在理想情况下,每个 TargetList 的水印等于高水印(即内存中存在足够的直接消息引用)。
因此,我们可以有一个后台线程将水印提高到理想级别 - 这意味着它从当前水印开始,直接加载对象;取消引用 CacheReference 并替换为直接引用。
挂起缓存
添加到 TargetList 中且高于高水印的 TargetEntry 对象会将其消息对象从直接引用中驱逐到 PendingCache 中。
Target 提前加载程序将在这些对象可用时将它们从该缓存移到 TargetList。如果它们不在 PendingCache 中,则从 QueueArea 加载它们。
队列区域
这表示实际的队列消息。还有一个匹配的 HeadQueueCache,它是一个简单的内存绑定队列。FIFO,因此较新的内容将从末尾驱逐。
返回
链接缓存
PendingCache 和 HeadQueueCache 与 TargetArea/DispatchArea 相互链接,以便所有缓存中使用的 RAM 数量固定。
随着 PendingCache 的增长,HeadQueueCache 会缩小。HeadQueueCache 仅用于新到达的消费者。启动时,它将保持一段时间,直到大量消息开始被传送到消费者,这时如果调度足够,它将缩小回零。
在负载很重的情况下,HeadQueueCache 将几乎为空,除非有新的消费者出现。