1
wccc 2019-01-29 15:16:37 +08:00
redisson 针对用户 时间 加锁 怎么样
没有分布式 那就 ConcurrentMap 存一个写锁 |
2
lhx2008 2019-01-29 15:17:09 +08:00 via Android
一般用数据库版本号 update set xxx, version=5 where vrrsion=4
或者用 redis 锁,用 setnx 和 del 的脚本 |
3
jimrok 2019-01-29 15:18:19 +08:00
Actor 模式下不用加锁,但我怕你去看 Akka 后,就逃掉了。
|
4
abcbuzhiming OP |
5
wccc 2019-01-29 15:30:02 +08:00
@abcbuzhiming #4 我有一个问题 时间段大小是固定的吗?
|
6
lihongjie0209 2019-01-29 15:34:01 +08:00
使用锁, 多个线程拿到锁再操作 >>>>> 临界区单线程操作
使用队列, 多线程写入队列作为生产者, 单线程操作数据库作为消费者 >>>>>>>> 临界区单线程操作 剩下的就是查 API 喽 |
7
TomVista 2019-01-29 15:41:33 +08:00
开始时间 结束时间
用户选择开始时间,传到服务器上,这之后,用户没有选对应结束时间之前,产生了其他日程时间, 如果新的日程包含第一个日程的开始时间,不允许用户操作.如果新的日程在第一个日程的开始时间之后,并且未接收到结束时间,提示用户去操作完第一个日程. 另外用数据库约束实现这个需求,本身极不明智. |
8
abcbuzhiming OP @wccc 当然不是固定的,固定的话就好解决多了
|
9
abcbuzhiming OP @TomVista 额,你可能理解错了,开始时间和结束时间是在客户端选好后一起提交服务器的,服务器要判断用户选的时间段是否和已经有的日程发生冲突。另外,主要问题是需要考虑高负载下由于后端不能很快的响应客户端,造成客户端多次提交问题
你会用什么方式来约束呢? |
10
wccc 2019-01-29 16:10:10 +08:00
@abcbuzhiming #8 我这个是针对用户级别加锁 让提需求的人去死.......
|
11
abcbuzhiming OP @wccc 如何加锁,我感兴趣的是这个
|
12
timsims 2019-01-29 16:38:41 +08:00
我的理解是,LZ 意思是用户会在同时多次提交相同(或不同)的日程时间段,所以现在 LZ 要解决的是时间段冲突的问题?
那锁的粒度就是用户 id , 把所有日程提交的操作全都串行来处理可以吗? |
13
TomVista 2019-01-29 16:52:15 +08:00
抱歉,想不出来,坐等答案,顺便找一个前端仔祭天
|
14
abcbuzhiming OP @timsims 串行就是用队列,问题是不可能每个用户都给一个队列,明显是有浪费的。用队列就涉及到用几个的问题,我觉得挺烦这个,所以才想到针对用户 id 进行加锁的策略
|
15
wccc 2019-01-29 16:53:28 +08:00
redis 分布式锁 相关的框架 例如 Rlock
或者本地加锁 用一个 ConcurrentMap 存一下锁 ... |
16
fashy 2019-01-29 16:54:43 +08:00
12306 行程冲突问题
|
17
pabupa 2019-01-29 17:30:59 +08:00 via Android
用户提交请求>查询数据库,验证是否冲突>根据验证结果,返回响应。
不就是这么个流程吗?我理解你的意思是如何避免用户重复请求,和锁没关系吧。 那: 让前段在没有相应之前禁用按钮;后台在查询数据库这一步做缓存。 是这么个道理吧……⊙﹏⊙ |
19
timsims 2019-01-29 17:34:50 +08:00
@abcbuzhiming 不用上队列,拿不到锁的操作可以等待,等待超时失败就让它失败咯,让用户重新提交就好
另外用队列的方案,怎么会想到每个用户给一个队列,所有用户公用一个队列也可以啊, 如果你有多队列的话,同一个用户都分配在相同的队列也能保证串行 |
20
zy445566 2019-01-29 17:36:59 +08:00
你这个没必要加锁,想办法搞用队列成顺序执行吧,如果是 nodejs 队列都能剩了,这样性能消耗会小很多
|
22
Raymon111111 2019-01-29 17:39:56 +08:00
用户 id 维度上 redis 的锁?
应该是我没看懂题目, 不知道问题的难点在哪 |
24
prolic 2019-01-29 17:46:21 +08:00
hash 分桶,打到队列或者机器内,然后串行就行了
|
25
guyeu 2019-01-29 18:18:21 +08:00 1
这个显然应该是串行化队列来处理,当然没必要每个用户一个队列。了解一下一致性哈希,把同一用户的所有操作扔到同一个队列去处理就行了。
|
26
limuyan44 2019-01-29 18:29:57 +08:00 via Android
怎么感觉是防重复提交的问题
|
27
fishfisher 2019-01-30 11:48:03 +08:00
@fashy12306 也有这个问题,我同时用多个抢票软件去提交订单,应该就是并发了,抢到了两张时间冲突的票,
用一个软件就只有行程冲突的提示。。。 |
28
fishfisher 2019-01-30 11:50:43 +08:00
@fanshy ,,,12306 也有这个问题,我同时用多个抢票软件去提交订单,应该就是并发了,抢到了两张时间冲突的票,
用一个软件就只有行程冲突的提示。。。 |
29
fishfisher 2019-01-30 11:52:37 +08:00
@fashy 晕,手残老是 @不到正确的人
|
30
deming 2019-01-30 12:14:08 +08:00
锁的粒度控制在用户身上就可以,多个用户同时进来,互不影响,因为锁的粒度在 userId 身上。
利用工具将 一个 userId 并发进来的时候,因为锁的存在也是互斥的。伪代码: ``` addTask(param...){ long userId = getUserId(); //get lock lockValue=genLockValue(); if(!getLock(userId,lockValue)){ return "some message"; } //do business ... releseLock(userId,lockValue); } getLock(userId,lockValue){ int retryTime=5; do{ retryTime--; redis.setNx(genKey(userId),lockValue); }while(retryTime>0); } releseLock(userId,lockValue){ 释放锁的时候判断 key 是这个 key,lockValue 也是这个我的 lockValue 才释放。 否则会错误释放。 } ``` |
31
abcbuzhiming OP @deming 你的想法就是我的想法。不过,一定非得上 redis 才能实现这个功能? Java 自己的锁搞不定?
|
32
PazuLee 2019-02-12 19:27:12 +08:00
拆分成两个问题:
1. 重复提交:增加 token 机制解决,每次提交校验 token 是否相同;前段增加等待的提示,实现方式比较多。 2. 1 之后,剩下问题是如何判断历史 N 条数据与当前新插入数据是否重叠,如果存储只有 MySQL,则必须取出来吧?如果记录数较大,DB 扛不住,可以考虑在缓存中维护一份 user 级别的已提交时间的数据,保存条记录中的 start_time & end_time 以上~应该能解决了吧 |