在以前的公司做钱包业务,并向其他同事提供服务,由于钱包是新业务,用户并没有钱包相关数据,所以每个方法中都要先查询一次,如果没有就创建一个新的钱包并保存,再继续做接下来的业务。
问题是在app钱包入口处,用户连续点击多次钱包按钮,导致多个请求几乎同时进入到服务端,因为创建了多个钱包,所以我定位到的问题就是两个请求几乎同时进入service并且都完成了查询的操作,所以才会走下面创建钱包的代码。
解决方式:在读写钱包的service方法上加同步锁,保证每次只有一个线程进入,这样就可以保证不会创建重复数据。虽然会慢,但其实java8的同步锁已经有了很大的优化,而且只做一个读写或只读的操作并不会占用多少时间(有其他的方式希望大家在评论分享下),下次再写类似这种代码时,一定要让前端也加一下控制。这样在app正常点击按钮就不会出现这种情况了,而恶意攻击的话,因为在后端也加了判断,所以也不再创建重复数据。
!!!如果业务允许,给userId也加个主键应该就不会出现这种问题了!!!