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

请教一个关于多人同时操作一条数据的问题

  •  
  •   Spider1996 · 145 天前 · 1841 次点击
    这是一个创建于 145 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前有个场景: 比如 A 用户选中一条数据进入设计页面,然后在 A 用户保存之前其它用户都不能操作这条数据.有什么比较好的处理 方法吗?

    29 条回复    2021-09-28 17:34:43 +08:00
    th00000
        1
    th00000  
       145 天前
    打开 -> 加锁 => 保存 -> 释放锁
    Spider1996
        2
    Spider1996  
    OP
       145 天前
    @th00000 这样如果用户不保存直接关闭浏览器的话 就死锁了吧... 我这业务时间不太确定 所以设置过期时间也不太行
    IvanLi127
        3
    IvanLi127  
       145 天前
    @Spider1996 自动保存 + 锁自动过期 呢
    aitaii
        4
    aitaii  
       145 天前
    谁先提交谁是 A 还是 指定 A 打开之后,其他人不能获取资源呢
    xiaoming1992
        5
    xiaoming1992  
       145 天前 via Android   ❤️ 1
    心跳检测,不跳了就过期
    aitaii
        6
    aitaii  
       145 天前
    增加一个状态字段呢,打开页面更新时更新状态为使用中,其他人再获取时状态为使用中,提交校验状态不通过
    Spider1996
        7
    Spider1996  
    OP
       145 天前
    @aitaii 有个用户打开后 其它人就不能再操作这条记录了
    RRRSSS
        8
    RRRSSS  
       145 天前
    Redis 分布式锁应该是最简单的

    选中数据进入页面 -> lock
    保存之后 -> unlock
    Spider1996
        9
    Spider1996  
    OP
       145 天前
    @aitaii 这样有点太简单了..要是用户打开页面 直接关闭了浏览器 那状态就一直为使用中 其它人都操作不了了
    Spider1996
        10
    Spider1996  
    OP
       145 天前
    @RRRSSS Redisson 吗?
    aitaii
        11
    aitaii  
       145 天前
    @Spider1996 那看来得加个 daemon 了
    SSang
        12
    SSang  
       145 天前
    锁要持有人去保活,做个过期时间就好了,比如 10s 过期,3s 保活一次
    meshell
        13
    meshell  
       145 天前
    @Spider1996 如果用户直接关闭浏览器没有保存,关闭页面也有动作呀。就像上面说得也可以定时心跳。超过多少时间就释放呗 。
    chenshun00
        14
    chenshun00  
       145 天前
    加个状态就可以了,定时心跳保活,不建议用 redis,多一个组件多一个麻烦,还用不到 redis,数据库本身就可以搞定了。这里的矛盾不在于并发有多大,粒度这么粗,数据库本身就搞定了。
    RRRSSS
        15
    RRRSSS  
       145 天前
    @Spider1996 就从你的描述来看,用 Redission,伪代码大概是这样:

    ```java
    // 进入页面 controller:

    RLock lock = redisson.getLock("anyLock");
    // 尝试加锁 最多等待 100s 上锁以后 10s 自动解锁
    boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);

    try {
    if (res) {
    // 获取到锁
    // 业务逻辑
    }
    } catch (Exception e) {
    throw e;
    } finally {
    // 最后一定要释放锁
    if (lock != null) {
    lock.unlock();
    }
    }

    ```

    如果只是 2B 业务,可能不用那么严谨,使用 Redission 直接用 redis 就行了
    Jooooooooo
        16
    Jooooooooo  
       145 天前
    页面的话简单, 每个人打开的页面都有版本, 后端每次更新版本都变. 写入的时候版本相等才能成功.
    dynastysea
        17
    dynastysea  
       145 天前
    你这个需求太模糊了,至少要说清楚是单机还是多机,这两者的技术方案差的可太多了
    loveyu
        18
    loveyu  
       145 天前
    典型的后台编辑操作(如果不是请忽略后面的内容)

    产品的需求一般是防止多人操作被覆盖(至于 A 保存之前不能操作,一般是指更新吧)

    建议找产品改需求,不是不能实现,是没必要
    akira
        19
    akira  
       145 天前
    没有什么“好” 办法的,来去都是 加锁 保活 ,跑不掉的。

    反而是 考虑下支持多人同时修改?这个才是现在的趋势呢
    msg7086
        20
    msg7086  
       145 天前 via Android
    还有一种做法就是允许其他人抢占锁。可以无脑参考一下 WordPress 之类软件的设计。
    xx6412223
        21
    xx6412223  
       144 天前
    用乐观锁更合适吧
    shellus
        22
    shellus  
       143 天前
    @chenshun00 最烦这些动不动就 redis 的。
    leohuangsulei
        23
    leohuangsulei  
       143 天前
    @shellus 那不用 redis,用户直接关闭浏览器,这个数据,别人还要不要操作了?直接起定时任务改数据库中数据的状态吗?
    leohuangsulei
        24
    leohuangsulei  
       143 天前
    @Spider1996 那就续期呗,js 定时发送请求,更新 redis 里面的过期时间
    saulshao
        25
    saulshao  
       143 天前
    你这个就是给这条记录定义一个状态,然后用户 A 一旦开始编辑操作,就把这个状态更新为编辑中。
    直到用户 A 编辑完成(设一个显式的按钮)为止,其他人都只能看。没必要想那么复杂。
    管它掉线之类的,一概不理。
    liukanshan
        26
    liukanshan  
       143 天前
    没有必要用什么分布式锁吧 在数据库加一个版本号来实现乐观锁就可以了 你说的操作这条数据应该是指修改这条数据吧 读不用加锁
    changwei
        27
    changwei  
       143 天前
    我也很好奇,google docs 两个人同时修改同一个 excel 文件的同一个单元格会怎么样呢,有没有人研究过他们的原理
    shellus
        28
    shellus  
       67 天前
    ```
    # 进入编辑, 成功的话这条 sql 更新记录数 1,如果被占用,就是更新记录数 0
    update posts set current_edit_uid='A', lock_time='当前时间戳' where id=123 and (current_edit_uid is null or lock_time<'当前时间-60 秒')
    # 编辑中续期,影响条数为 0 表示超时,已经被别人编辑了
    update posts set lock_time='当前时间戳' where id=123 and current_edit_uid='A'

    ```
    shellus
        29
    shellus  
       67 天前
    @leohuangsulei 不用 redis 一样可以实现超时啊。
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1248 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 115ms · UTC 00:03 · PVG 08:03 · LAX 16:03 · JFK 19:03
    ♥ Do have faith in what you're doing.