一个缓存实现平均分配队列的方案

时间:2022-11-15 11:15:28

场景:

在工单系统中,角色有处理员和报告人,一个工单创建后会被分配给多个待选处理员中的一个。

现要求平均的分配给这些处理员,使得每个处理员的工作量大体相当。

实现:

为了实现平均分配,首先想到的是随机数。

从数据库中获取到处理员组后,根据组的大小生成随机数作为下标,返回该下标对应的处理员即可。

实现简单,但如果一天的单数不多,那这一天每个处理员分到手头上的工单数就可能差别很大。

优化方案:

在缓存中维护一个处理员队列,再维护一个自增的下标值。

每次要分配处理员时,则从缓存中获取下标值,获取时返回的是自增后的,即++i。

当该下标值超过处理员队列的 size 时,则将该下标值置为 0,即返回队首的处理员。这种方式类似于负载均衡中的轮询法。

缓存通过 Redis 实现,自增下标值通过 INCR 命令实现,处理员队列通过 list 结构存储。

下标值也可以不用置 0,始终递增,而下标则为下标值对处理员队列 size 取余。

需求调整:

现处理员可以选择停止接单或开始接单。

那当处理员选择停止接单后缓存中的处理员队列就要将该处理员删掉,同样当处理员选择开始接单后要将处理员加到处理员队列的队尾。

这时,如果下标取得方式为取余,则会存在一种极端情况:

每次分配处理员时都有一个新的处理员被加到队列中,比如当前队列中为 A B C,下标值为 4,则分配给下标为 1 的 B 处理员,分配后处理员 D 开始接单,当前队列变为 A B C D,则下一次分配时,下标值为 5,那对 size = 4 取余,结果还是 1,那么还是会分给下标为 1 的 B 处理员。

这种情况下,下标置 0 的方式会更好。