V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
lx91714
V2EX  ›  问与答

请教 V 友们一个技术上的问题,谢谢啦

  •  
  •   lx91714 · 2022-10-31 16:33:10 +08:00 · 644 次点击
    这是一个创建于 756 天前的主题,其中的信息可能已经有所发展或是发生改变。

    请教大佬们一个问题, 对于资源占用类的需求大家怎么设计的了,例如数据库存储了一批设备信息,每个设备只能被一个用户占用,用完释放了才能被继续占用。我目前的做法是,给设备表加了一个 status 状态字段,先获取一台空闲设备,然后去更新状态字段,更新成功则返回,更新失败就继续循环,原理就是利用数据库锁,但是实际使用中发现有些设备会释放失败,一直处于忙碌中,占用正常,没有出现重复占用情况,有什么改善方案吗

    Jooooooooo
        1
    Jooooooooo  
       2022-10-31 16:55:41 +08:00
    有个简单的办法是, 兜底释放, 占用时间是有上限的. 到了上限时间一定会被释放. (可以搞个定时任务扫到期的任务, 就算是某一次释放失败了下一次也能成功)

    但上面这个方法时效性不够, 而且某些场景下不适用

    时效性强一点可以考虑兜底去补偿. 方法也很多, 一种可行的是, 释放后, 直接发一个延迟检查的消息, 短暂时间后收到检查消息看看是不是真的释放了, 如果没有再释放一次, 并且再发这个检查消息, 比如重复发三次. 如此一来还会无法得到失败的场景就基本不存在了. (可以再结合上面第一种兜底到时间一定释放, 保证万无一失)

    这里面可再做改进的是, 可以当数据库更新失败后(无论是返回为 0 或者抛了异常), 可以原地直接重试释放, 然后再发检查消息

    这里面有个注意的点, 需要有个标记记录, 只能释放自己获得的资源, 否则会出现, A 释放了资源, B 获取了资源, A 获得延迟检查消息, 发现资源被占用, 把 B 占用的资源释放了. 可以多一个字段直接是一串随机数(uuid 就行), 延迟检查消息要带着这个 uuid 去释放, 对不上说明已经被其他人重新占用了, 不用再释放.
    lx91714
        2
    lx91714  
    OP
       2022-11-01 15:08:22 +08:00
    @Jooooooooo 感谢解答,让我有点头绪了,谢谢啦
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3162 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 13:47 · PVG 21:47 · LAX 05:47 · JFK 08:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.