V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Saurichthys
V2EX  ›  Java

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

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

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

    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 就跳过!!!
    gtexpanse
        22
    gtexpanse  
       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   ·   实用小工具   ·   2360 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 16:03 · PVG 00:03 · LAX 08:03 · JFK 11:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.