共用一个查询额度池时,优先顺序不该按团队先来后到,而该按“查询失败后能否靠重试自救”来分层:能靠缩小范围、换时间窗重试的探索性查询往后排,查的是唯一事实、失败就没有替代路径的核验查询往前排。这个分层的直接依据是额度耗尽后的损失不对称——前者损失的是等待时间,后者损失的是决策依据本身。下面按保留、改写、退出三种取舍展开,并说明各自成立的前提。
把每个团队的查询按目的分成两类:核验类用于确认一个已发生的事实(某条记录是否存在、某次变更是否生效、某个对象是否被正确纳入范围),失败后没有别的办法拿到答案;探索类用于试探规律(不同条件组合下结果如何变化、某个范围是否值得继续投入),失败后可以缩小范围再来一次。
核验类查询应当保留在优先队列前端。前提是它满足两个条件:一是结果直接影响下一步动作,二是没有等价的替代手段。假设某团队需要在发布前确认一批对象是否全部被正确识别,这类查询失败就意味着发布必须推迟,它的优先级应当高于任何“想看看趋势”的查询。
反过来,如果某个团队的核验查询其实可以通过其他已缓存的结果间接推断,它就不再属于不可替代,应当降级。判断标准很简单:把这条查询删掉,下一步动作是否还能照常进行。能,就降级;不能,才保留。
很多排队冲突的真正原因不是额度不够,而是查询颗粒度过粗。一个团队提交“全量对象在全部条件下的结果”,另一个团队只需要“其中一小批对象在单一条件下的结果”,两者被当成同等任务排队,前者会长时间占住额度。
可行的改写方向有三个:
改写的适用前提是:拆分后的结果仍然能拼回原来需要的结论。如果某个判断必须依赖全量数据同时返回,拆分反而会引入新的不确定性,这时应当保留原查询并把它归入核验类,而不是强行拆分。
一个假设的例子:两个团队共用额度,A 团队要确认三个对象是否被正确识别,B 团队想比较五种条件组合下的结果分布。若按提交顺序执行,B 的大查询可能先占满额度,A 的三个小核验被推迟。若把 B 的查询拆成五次单条件查询并排到 A 之后,A 的核验可以在很短时间内完成,B 的总等待时间可能略有增加,但它的探索性目的本身不要求即时性。这里的关键不是谁更重要,而是谁的失败可以靠重试自救。
当某个团队的查询长期属于核验类、且频率稳定可预期时,把它从共用队列中退出、单独安排额度,往往比反复争抢更省事。成立的边界是:该团队的查询量波动小,且它的失败代价确实高于其他团队。
但退出不是默认选项。如果该团队的查询量本身波动很大,单列额度会造成闲置与紧张交替出现,反而不如留在共用池里按优先级调度。另外,退出意味着其他团队要重新分配剩余额度,这一步需要同步确认,否则只是把冲突从队列内搬到了队列外。
排序规则改完之后,不要直接全量推行。先选一个短周期,记录两组数据:核验类查询从提交到拿到结果的时间,以及探索类查询因排队被推迟的次数。如果核验类时间明显缩短、探索类推迟次数在可接受范围内,说明分层方向成立;如果核验类没有改善,通常说明瓶颈不在排队顺序,而在单条查询本身的耗时或对象范围过大,这时应当回到改写查询粒度那一步,而不是继续调整优先级。
需要注意的是,核验类查询时间没有变化,也可能只是因为样本周期太短、恰好没有发生额度争抢,不能单凭一次对照就断定排序无效。至少覆盖一个完整的额度紧张周期,再决定是保留当前规则、继续改写查询,还是让某个团队退出共用队列。