V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
keshao
V2EX  ›  程序员

任务队列的单用户串行设计

  •  
  •   keshao · 2021-12-01 10:33:30 +08:00 · 2041 次点击
    这是一个创建于 1117 天前的主题,其中的信息可能已经有所发展或是发生改变。
    各位同学,我有一个需求场景想请教下设计思路。我总感觉找不到太好的解决方案

    现在需要实现一个任务队列的需求,是一个导入任务的需求。

    因为文件很大并且数据要求幂等性,且还是用户自己上传的数据。所以需要针对单个用户串行化处理。还要要做分布式部署项目,所以 JDK 提供的 API 是无法做到的。所以最终的要求就是对用户串行,单个用户提交多个任务则排队串行运行。对系统来说就是多线程调度执行,最好还不要 CPU 进行空转。我能想到的就是空转( while )+单个用户 redis 锁去实现,想请教下各位有更好的方案么?
    12 条回复    2021-12-06 18:26:17 +08:00
    zhady009
        1
    zhady009  
       2021-12-01 11:26:18 +08:00
    用一个 BlockingQueue 的分布式实现 比如 Redisson 里的
    线程池用这个队列来创建
    BigBrother1024
        2
    BigBrother1024  
       2021-12-01 13:39:40 +08:00 via iPhone
    用 actor 模型
    Saxton
        3
    Saxton  
       2021-12-01 13:43:25 +08:00
    这不就是典型的队列吗
    keshao
        4
    keshao  
    OP
       2021-12-01 13:52:34 +08:00
    @Saxton 还不是典型的队列,我如果是 CPU 空转方案可能还需要为每个用户维护队列,不然无法保证单用户串行的
    teem
        5
    teem  
       2021-12-01 14:09:48 +08:00
    TDMQ
    Itoktsnhc
        6
    Itoktsnhc  
       2021-12-01 17:09:02 +08:00
    很像是 kafka 的一套东西
    多条队列(或者队列内分区)(q1,q2,q3)
    1. 消息在队列内的分布上需要考虑同一个 UserId 的消息有 FIFO 的顺序。(UserId Hash 保证落到同一个队列 /分区内)
    2. 每一个队列(分区)的接收者需要做绑定,用类似锁的机制处理 receive 的断链和补位 q1->r1
    siweipancc
        7
    siweipancc  
       2021-12-01 18:24:26 +08:00 via iPhone
    用户任务表与对应的独占队列. 先拿不存在执行时间点的锁(按顺序遍历立马返回),pop 任务,写执行时间点到任务表。任务完成做行移除。视业务重要程度需要一个守护线程做失败任务重新提交
    wqhui
        8
    wqhui  
       2021-12-01 19:22:01 +08:00
    @keshao 为什么要空转,redis 里面一个用户一个 list (里面放这个用户要执行的导入任务,比如文件名),当你一个线程要提交任务的时候,先去查一下 redis 有没这个 list ,把执行任务需要的参数加到这个 list 末尾,如果原本没有这个 list ,代表现在这个用户没有执行着的任务,启动一个工作线程去执行,工作线程完成当前任务后,检查下自己这个用户的 list 是不是空的,空的就删除这个 list 结束工作线程,不空就在这 list 取下一个任务执行。参考下 netty
    night98
        9
    night98  
       2021-12-01 20:42:03 +08:00
    rocketmq 顺序消息,用户 id 做 msg id ,完事,其他的就是楼上说的,手动实现单用户队列,创建线程处理
    Jooooooooo
        10
    Jooooooooo  
       2021-12-01 20:55:37 +08:00
    你了解下消息队列

    要处理的任务统一往队列发

    然后消费线程设置成 1, 就是一个消息一个消息串行消费了
    keshao
        11
    keshao  
    OP
       2021-12-06 18:25:28 +08:00
    @wqhui 这种方式确实解决了我的一些问题,当时的确是我没有绕过来,参照了你的部分思路。感谢~
    keshao
        12
    keshao  
    OP
       2021-12-06 18:26:17 +08:00
    @night98 这种方式我也参照了,感谢~
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2765 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 37ms · UTC 11:37 · PVG 19:37 · LAX 03:37 · JFK 06:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.