
1 fkmc 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 fkmc 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 fkmc 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 fkmc 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 队列都能剩了,这样性能消耗会小很多 |
24 prolic 2019-01-29 17:46:21 +08:00 hash 分桶,打到队列或者机器内,然后串行就行了 |
25 guyeu 2019-01-29 18:18:21 +08:00 这个显然应该是串行化队列来处理,当然没必要每个用户一个队列。了解一下一致性哈希,把同一用户的所有操作扔到同一个队列去处理就行了。 |
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 以上~应该能解决了吧 |