# 防抖
# 背景
用户对一个未揽收的订单进行通知揽收操作,多次点击时后端会进行多次操作,给员工发送多条信息。而设计是用户不能在一个小时内发送两次通知揽收短信,在后端有表记录用户发送揽收消息的行为。
# 解决方案
# 前端防抖动
通过按钮的loading状态来防止多次网络请求。但无法解决对于网络波动问题造成的请求重发。
# 后端防抖动
在发送通知揽收消息前,先获取该订单对应的锁,没拿到锁的请求就拒绝。同一个用户的多个请求会被多个线程处理。
# synchronized锁
将在行为表中查询用户是否在一小时内发送过消息和发送揽收消息这两个代码块锁在一起,确保发送通知揽收消息之前用户一定没有发送过消息。但是Synchronized锁的作用范围局限于当前虚拟机,当服务被部署到多台机器上时,无法使用该方法。
# mysql锁
对订单加一个通知时间字段,获取锁对应的操作就是
update order set inform_time = now() where id = 1 and inform_time = ?;
# redis锁
# setNX
如果锁不存在的话就创建锁,完成任务后del销毁。但是,这种方法如果在线程创建锁后意外崩溃了,其他线程将永远拿不到锁。
# set NX EX seconds
通过限制锁的失效时间来规避崩溃后其他线程拿不到锁的情况。这种方法的缺点是,当锁已经失效而任务还未执行完时,其他线程会抢占这个锁,导致异常。
# redisson分布式锁
redisson使用了看门狗机制完成锁的自动续期,如果业务持续时间久,则会自动续30s,避免锁自动过期被删的情况。默认情况下,Redisson分布式锁有效期时间为30s,并且会每十秒钟校验当前持有锁的线程是否结束。若为执行完毕,则会续期30s,否则取消续期。
← 02线程池 04Synchronized →