目前有个场景: 比如 A 用户选中一条数据进入设计页面,然后在 A 用户保存之前其它用户都不能操作这条数据.有什么比较好的处理 方法吗?
1
th00000 2021-07-12 17:03:17 +08:00
打开 -> 加锁 => 保存 -> 释放锁
|
2
Spider1996 OP @th00000 这样如果用户不保存直接关闭浏览器的话 就死锁了吧... 我这业务时间不太确定 所以设置过期时间也不太行
|
3
IvanLi127 2021-07-12 17:25:19 +08:00
@Spider1996 自动保存 + 锁自动过期 呢
|
4
aitaii 2021-07-12 17:27:51 +08:00
谁先提交谁是 A 还是 指定 A 打开之后,其他人不能获取资源呢
|
5
xiaoming1992 2021-07-12 17:30:20 +08:00 via Android 1
心跳检测,不跳了就过期
|
6
aitaii 2021-07-12 17:30:40 +08:00
增加一个状态字段呢,打开页面更新时更新状态为使用中,其他人再获取时状态为使用中,提交校验状态不通过
|
7
Spider1996 OP @aitaii 有个用户打开后 其它人就不能再操作这条记录了
|
8
RRRSSS 2021-07-12 17:32:47 +08:00
Redis 分布式锁应该是最简单的
选中数据进入页面 -> lock 保存之后 -> unlock |
9
Spider1996 OP @aitaii 这样有点太简单了..要是用户打开页面 直接关闭了浏览器 那状态就一直为使用中 其它人都操作不了了
|
10
Spider1996 OP @RRRSSS Redisson 吗?
|
11
aitaii 2021-07-12 17:37:44 +08:00
@Spider1996 那看来得加个 daemon 了
|
12
SSang 2021-07-12 17:38:10 +08:00
锁要持有人去保活,做个过期时间就好了,比如 10s 过期,3s 保活一次
|
13
meshell 2021-07-12 17:40:22 +08:00
@Spider1996 如果用户直接关闭浏览器没有保存,关闭页面也有动作呀。就像上面说得也可以定时心跳。超过多少时间就释放呗 。
|
14
chenshun00 2021-07-12 18:18:34 +08:00
加个状态就可以了,定时心跳保活,不建议用 redis,多一个组件多一个麻烦,还用不到 redis,数据库本身就可以搞定了。这里的矛盾不在于并发有多大,粒度这么粗,数据库本身就搞定了。
|
15
RRRSSS 2021-07-12 18:24:02 +08:00
@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 就行了 |
16
Jooooooooo 2021-07-12 18:36:58 +08:00
页面的话简单, 每个人打开的页面都有版本, 后端每次更新版本都变. 写入的时候版本相等才能成功.
|
17
dynastysea 2021-07-12 18:50:30 +08:00
你这个需求太模糊了,至少要说清楚是单机还是多机,这两者的技术方案差的可太多了
|
18
loveyu 2021-07-12 19:12:54 +08:00
典型的后台编辑操作(如果不是请忽略后面的内容)
产品的需求一般是防止多人操作被覆盖(至于 A 保存之前不能操作,一般是指更新吧) 建议找产品改需求,不是不能实现,是没必要 |
19
akira 2021-07-12 22:00:32 +08:00
没有什么“好” 办法的,来去都是 加锁 保活 ,跑不掉的。
反而是 考虑下支持多人同时修改?这个才是现在的趋势呢 |
20
msg7086 2021-07-13 00:57:12 +08:00 via Android
还有一种做法就是允许其他人抢占锁。可以无脑参考一下 WordPress 之类软件的设计。
|
21
xx6412223 2021-07-13 13:47:44 +08:00
用乐观锁更合适吧
|
22
shellus 2021-07-14 11:41:59 +08:00
@chenshun00 最烦这些动不动就 redis 的。
|
23
leohuangsulei 2021-07-14 13:49:42 +08:00
@shellus 那不用 redis,用户直接关闭浏览器,这个数据,别人还要不要操作了?直接起定时任务改数据库中数据的状态吗?
|
24
leohuangsulei 2021-07-14 13:51:26 +08:00
@Spider1996 那就续期呗,js 定时发送请求,更新 redis 里面的过期时间
|
25
saulshao 2021-07-14 13:51:41 +08:00
你这个就是给这条记录定义一个状态,然后用户 A 一旦开始编辑操作,就把这个状态更新为编辑中。
直到用户 A 编辑完成(设一个显式的按钮)为止,其他人都只能看。没必要想那么复杂。 管它掉线之类的,一概不理。 |
26
liukanshan 2021-07-14 16:28:14 +08:00
没有必要用什么分布式锁吧 在数据库加一个版本号来实现乐观锁就可以了 你说的操作这条数据应该是指修改这条数据吧 读不用加锁
|
27
changwei 2021-07-14 23:28:08 +08:00
我也很好奇,google docs 两个人同时修改同一个 excel 文件的同一个单元格会怎么样呢,有没有人研究过他们的原理
|
28
shellus 2021-09-28 17:33:48 +08:00
```
# 进入编辑, 成功的话这条 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' ``` |
29
shellus 2021-09-28 17:34:43 +08:00
@leohuangsulei 不用 redis 一样可以实现超时啊。
|