如果以用户为单位上锁,你们会怎么实现这个功能?

2019-01-29 14:59:24 +08:00
 abcbuzhiming
有这么个场景。用户日程安排,要保证时间段设定的唯一性(时间段不能冲突),所以没法在数据库层面上用唯一约束解决问题。一定得想办法在应用层解决。但是同时,每个用户的日程彼此独立,所以不会发生冲突。因此,这个场景是 一个用户可能会和自己发生资源争抢(当压力比较大的时候,用户可能提交两个一样的时间段数据到数据库去),但是用户和用户之间不会发生资源争抢的问题。因此,如果单独在方法阶段加锁,对性能损失就很大——因为它对应的其实是用户争抢资源问题。而我希望的是,是针对用户本身进行加锁,也就是 A 用户如果已经提交了一次设定时间段的请求,在此次提交还没处理完前,因为种种原因 A 用户再次提交了请求,那么这个请求只能等待上一次请求处理完,才能进行处理。同时,其它用户的请求不受影响
5237 次点击
所在节点    Java
32 条回复
wccc
2019-01-29 15:16:37 +08:00
redisson 针对用户 时间 加锁 怎么样
没有分布式 那就 ConcurrentMap 存一个写锁
lhx2008
2019-01-29 15:17:09 +08:00
一般用数据库版本号 update set xxx, version=5 where vrrsion=4
或者用 redis 锁,用 setnx 和 del 的脚本
jimrok
2019-01-29 15:18:19 +08:00
Actor 模式下不用加锁,但我怕你去看 Akka 后,就逃掉了。
abcbuzhiming
2019-01-29 15:23:14 +08:00
@wccc 没有看懂你的方案,如何针对时间加锁呢?
@lhx2008 我这个问题里不光有 update,insert 也是大头,insert 时就不好用版本号解决了
@jimrok Actor 本质是用单线程消息队列躲开了锁的问题。我不太喜好这个方案
wccc
2019-01-29 15:30:02 +08:00
@abcbuzhiming #4 我有一个问题 时间段大小是固定的吗?
lihongjie0209
2019-01-29 15:34:01 +08:00
使用锁, 多个线程拿到锁再操作 >>>>> 临界区单线程操作

使用队列, 多线程写入队列作为生产者, 单线程操作数据库作为消费者 >>>>>>>> 临界区单线程操作






剩下的就是查 API 喽
TomVista
2019-01-29 15:41:33 +08:00
开始时间 结束时间

用户选择开始时间,传到服务器上,这之后,用户没有选对应结束时间之前,产生了其他日程时间,

如果新的日程包含第一个日程的开始时间,不允许用户操作.如果新的日程在第一个日程的开始时间之后,并且未接收到结束时间,提示用户去操作完第一个日程.

另外用数据库约束实现这个需求,本身极不明智.
abcbuzhiming
2019-01-29 16:04:24 +08:00
@wccc 当然不是固定的,固定的话就好解决多了
abcbuzhiming
2019-01-29 16:07:24 +08:00
@TomVista 额,你可能理解错了,开始时间和结束时间是在客户端选好后一起提交服务器的,服务器要判断用户选的时间段是否和已经有的日程发生冲突。另外,主要问题是需要考虑高负载下由于后端不能很快的响应客户端,造成客户端多次提交问题
你会用什么方式来约束呢?
wccc
2019-01-29 16:10:10 +08:00
@abcbuzhiming #8 我这个是针对用户级别加锁 让提需求的人去死.......
abcbuzhiming
2019-01-29 16:34:59 +08:00
@wccc 如何加锁,我感兴趣的是这个
timsims
2019-01-29 16:38:41 +08:00
我的理解是,LZ 意思是用户会在同时多次提交相同(或不同)的日程时间段,所以现在 LZ 要解决的是时间段冲突的问题?

那锁的粒度就是用户 id , 把所有日程提交的操作全都串行来处理可以吗?
TomVista
2019-01-29 16:52:15 +08:00
抱歉,想不出来,坐等答案,顺便找一个前端仔祭天
abcbuzhiming
2019-01-29 16:52:19 +08:00
@timsims 串行就是用队列,问题是不可能每个用户都给一个队列,明显是有浪费的。用队列就涉及到用几个的问题,我觉得挺烦这个,所以才想到针对用户 id 进行加锁的策略
wccc
2019-01-29 16:53:28 +08:00
redis 分布式锁 相关的框架 例如 Rlock
或者本地加锁 用一个 ConcurrentMap 存一下锁 ...
fashy
2019-01-29 16:54:43 +08:00
12306 行程冲突问题
pabupa
2019-01-29 17:30:59 +08:00
用户提交请求>查询数据库,验证是否冲突>根据验证结果,返回响应。
不就是这么个流程吗?我理解你的意思是如何避免用户重复请求,和锁没关系吧。
那:
让前段在没有相应之前禁用按钮;后台在查询数据库这一步做缓存。
是这么个道理吧……⊙﹏⊙
wccc
2019-01-29 17:33:17 +08:00
@pabupa #17 验证冲突的时候,需要加锁,
后端还是要做验证的 无论前端做不做验证
timsims
2019-01-29 17:34:50 +08:00
@abcbuzhiming 不用上队列,拿不到锁的操作可以等待,等待超时失败就让它失败咯,让用户重新提交就好

另外用队列的方案,怎么会想到每个用户给一个队列,所有用户公用一个队列也可以啊, 如果你有多队列的话,同一个用户都分配在相同的队列也能保证串行
zy445566
2019-01-29 17:36:59 +08:00
你这个没必要加锁,想办法搞用队列成顺序执行吧,如果是 nodejs 队列都能剩了,这样性能消耗会小很多

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/531596

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX