场景描述:
当你对一篇文章点击发送评论的时候,如果网络延迟,响应速度慢,页面停留在发送评论的页面,这时候你以为没有发送成功,疯狂的点击发送/提交按钮,结果后台服务器短时间内接收到大量的重复数据,该怎么处理?
可能的解决方案
前端控制:
- 禁用按钮的形式
用户编写评论内容之后,点击提交,修改CSS样式(比如按钮设置为disabled禁用)。修改css样式消耗网络资源很小,可以快速的修改。直到后台数据响应完成之后,将css样式改回。
- 清空评论内容,发送评论时为空则提示不发送。
用户编写评论点击提交,马上清空评论内容,再次点击发送按钮,进行评论内容为空不能发送提示。
- 防抖、节流
设置定时器,设置时间,在这个时间段内的多次点击,就清空计时器,重新计时,直到计时器计时满足设置的时间,才发送请求。
- 延迟、排队
发送请求之后,直到后台处理完成,并返回结果,才能继续发送请求,在这个时间段内发送的请求都拦截不进行处理或排队去重再发送。
后端控制:
5. 幂等(判断内容重复)
所谓的幂等就是多次的重复处理,结果应该不变。也就是对于同一个评论的多次提交,结果不变(只有一次结果是成功的),也就是如果内容重复,只保存一条记录到DB。
常用的两种方式:
1)建立唯一索引,防止新增脏数据
可以限制重复插入数据,当重复时,数据库会抛异常,保证不会出现脏数据。但体验很不好,并且实用场景有限制。
2)利用 token 机制,防止页面重复提交
核心思想是为每一次操作生成一个唯一性的凭证,也就是token。一个token在操作的每一个阶段只有一次执行权,一旦执行成功则保存执行结果。对重复的请求,返回同一个结果。、
- 频率控制
比如对于每篇文章进行评论,60秒以内只能进行一次评论,60秒内发送多条评论只保留第一条存入数据库。
- 分布式锁
在进入方法时,先去获取锁,如果获取到锁,就继续执行后面的流程。否则,就等待锁的释放一直到获取到锁。当执行完方法时,释放锁。【注意】锁要设个超时时间,防止意外没有释放到锁。
它可以用来解决分布式系统的幂等性,常用的实现方案是 redis 和 zookeeper 等工具。