Java 中多个项目同时执行,如何避免同时扫描到同一条数据 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Saurichthys
V2EX    Java

Java 中多个项目同时执行,如何避免同时扫描到同一条数据

  •  
  •   Saurichthys 2020-05-23 15:08:36 +08:00 5368 次点击
    这是一个创建于 2023 天前的主题,其中的信息可能已经有所发展或是发生改变。

    各位大佬,项目是这样子的 存在多个定时处理数据的项目,项目是一样的,只是端口不一样,实现效果是对相同的一个库的一张表进行查询与修改操作(每次都是取最新时间的十条数据),但是这样子好像数据又会冲突,如何避免这种情况

    30 条回复    2020-05-24 21:55:42 +08:00
    xuanbg
        1
    xuanbg  
       2020-05-23 15:35:50 +08:00
    分布式锁是唯一解决方案
    yc8332
        2
    yc8332  
       2020-05-23 15:40:39 +08:00
    搞个 redis 锁。或者把数据维护到 redis,只保留 10 条数据。。每次直接从 redis 取
    huhu3312
        3
    huhu3312  
       2020-05-23 15:42:11 +08:00
    这种跑一个定时任务不就好了
    Saurichthys
        4
    Saurichthys  
    OP
       2020-05-23 15:51:23 +08:00
    @huhu3312 一个定时任务效率太低了呀- -
    coder2019
        5
    coder2019  
       2020-05-23 17:14:46 +08:00
    @Saurichthys 感觉没啥意义,操作的是同个库同个表,修改数据会加锁,瓶颈在数据库上,跑多个定时任务有啥效率提升吗
    skypyb
        6
    skypyb  
       2020-05-23 17:30:21 +08:00
    。。。 就分布式锁就完事了呗
    jugelizi
        7
    jugelizi  
       2020-05-23 18:06:58 +08:00 via iPhone
    ...上消息队列吧
    yjxjn
        8
    yjxjn  
       2020-05-23 18:10:45 +08:00
    悲观锁?
    ak78
        9
    ak78  
       2020-05-23 18:12:29 +08:00
    1 、分布式锁(推荐) 2 、通过数据库乐观锁加上更新条件,条件不满足自然更新不到。3 、不同的机器粉笔通过相关表 id%取模来达到取到不同的数据(不推荐)
    huntcool001
        10
    huntcool001  
       2020-05-23 18:16:26 +08:00
    redisson 里有包装好的 redis 客户端

    或者用 xxl-job 一类的分布式框架, 有一台机子执行就行了
    fmumu
        11
    fmumu  
       2020-05-23 18:19:31 +08:00 via Android
    查询修改?乐观锁行吧
    xizismile
        12
    xizismile  
       2020-05-23 18:51:20 +08:00 via Android
    @huntcool001 +1,用 xxl-job
    luckyrayyy
        13
    luckyrayyy  
       2020-05-23 19:10:00 +08:00 via iPhone
    分布式锁,或者十个并发并不大,数据库加个 version 字段乐观锁
    luozic
        14
    luozic  
       2020-05-23 19:36:17 +08:00
    最简单的令牌桶,漏斗,麻烦点,消息队列。
    vchat
        15
    vchat  
       2020-05-23 19:49:20 +08:00
    可以这样, 多台机器 启动通过争抢的方式获取 leader 用来作为调度器 负责将来取数据库数据到缓存队列中,其他机器从缓存中获取数据处理更新数据表
    lyyhello
        16
    lyyhello  
       2020-05-23 22:00:57 +08:00
    xxl-job-gateway 投递-mq-应用系统消费(多几个消费端 多几个消费线程) 完美解决
    lyyhello
        17
    lyyhello  
       2020-05-23 22:01:24 +08:00
    xxl-job>gateway 投递>mq>应用系统消费(多几个消费端 多几个消费线程) 完美解决
    lyyhello
        18
    lyyhello  
       2020-05-23 22:09:52 +08:00
    方案二(垃圾方案 但是对你来说可能是改动最小的 主机名注册到一张表里面 server_config 配置处理序号 ),再从业务表里面挑出一个唯一字段 选取任务的时候进行 hash 然后取模 命中配置处理序号的,就有本台主机处理。 优点就是不加锁不用中间件 缺点就是主机挂了。有部分数据处理不到。只有等主机上线了。 有需要可以找我私聊。帮助大佬是我的美德
    aaahhh123
        19
    aaahhh123  
       2020-05-23 22:47:25 +08:00
    666
    fewok
        20
    fewok  
       2020-05-23 22:49:06 +08:00
    本质就是错的,为啥不一个定时任务扫出来,再发给其他机器协同处理呢??
    Saurichthys
        21
    Saurichthys  
    OP
       2020-05-23 23:04:11 +08:00
    @fewok 你好,一个任务扫出来,那就需要在创建一个项目来做这个事情了, 然后你原来项目的业务逻辑都要改了,之前是针对数据库,现在要针对这个任务转为接收数据执行业务逻辑。
    目前综合各位大佬的意见,我觉得分布式锁 Redis 的方案可能会比较好一点,任务启动,执行的数据 key 锁住 + expireTime,其他任务并发任务执行到这条数据 有 key 就跳过!!!
    syncnano
        22
    syncnano  
       2020-05-23 23:16:31 +08:00 via iPhone
    分布式锁太麻烦了吧,db 加一列 runhost,大家都同时去 update runhost is null 的,然后再去查询一下就拿到只属于自己的任务了
    wujieyuan
        23
    wujieyuan  
       2020-05-23 23:22:50 +08:00
    上面回答什么分布锁啊, 消息队列啊都太麻烦了, 其实有个非常简单的方法, 也无需修改代码,可以读指定路径下的文件, 如果有就执行,没有就不执行, 想让哪台机器执行任务就在那台机器上放上指定的文件,其他机器就不会执行啦, 日后不管怎么换服务器都不用修改代码
    fewok
        24
    fewok  
       2020-05-23 23:27:33 +08:00
    @Saurichthys 为啥要创建服务,所有服务的 ip 挨个发送下消息等结果,不就完事了。可以用中间件的话,直接扔 MQ 。。。
    micean
        25
    micean  
       2020-05-23 23:34:59 +08:00 via Android
    为什么要分布式锁啊……数据库开事务锁呗
    xyjincan
        26
    xyjincan  
       2020-05-23 23:37:13 +08:00 via Android
    把代码改改,写操作抽象出来,单独部署
    laball
        27
    laball  
       2020-05-24 00:08:06 +08:00
    这个设计方案感觉有问题啊,建议使用下次队列+多个消费者的模式,每次增加一条记录,即往 MQ 中放入一个任务,然后,让多个消费者去处理,这样,每条数据,都能处理到,描述中关于取最新时间的 10 条数据,逻辑上是存在问题的,因为有可能会出现有数据没有被取到的情况,这样就有些数据处理了,有些数据没有处理,存在不一致的情况;
    abcbuzhiming
        28
    abcbuzhiming  
       2020-05-24 14:43:23 +08:00
    @Saurichthys 你为什么觉得低?你的数据真多到了一个线程跑不够的地步?那你首先要考虑的是需要一个生产者模型来分配任务,为了保证任务不重复,你生产的时候是要加锁的,加锁后性能也就那样。你觉得你到了这一步了吗?
    lidlesseye11
        29
    lidlesseye11  
       2020-05-24 17:01:23 +08:00
    什么叫“每次都是取最新时间的十条数据”。。
    比如现在表里一共 20 条,A 取了 10 条最新的,这时候 B 进来是和 A 抢锁?还是取剩下的 10 条?还是等新的 10 条进来?
    Saurichthys
        30
    Saurichthys  
    OP
       2020-05-24 21:55:42 +08:00
    @lidlesseye11 是和 A 抢锁的呀, 都是处理最新的十条数据, 但是这十条可能 A 处理 也有 B 加载到需要处理呀,这不就很矛盾了吗
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     846 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 22:16 PVG 06:16 LAX 14:16 JFK 17:16
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86