利用nginx集群式部署服务器中,数据同步有关问题
利用nginx集群式部署服务器中,数据同步问题
最近在项目中遇到了一个数据同步的问题
项目部署背景:利用nginx集群式服务器部署,使用唯一的一台数据库服务器,数据库为mysql
问题描述:对一个账户进行更新操作,一个未查明的原因,用户点击更新操作后,未知的原因在后台同时产生了两个request请求,这两个请求并发进行,同时调用存储过程对数据库进行操作,造成了对数据库的重复操作,等于说操作了两次,账户余额变成了负值。
为了重新问题,写了个测试类,多线程调用此存储过程,重现了这个问题
final TaskThreadExecution t = new TaskThreadExecution(); ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 3000, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5000), new ThreadPoolExecutor.DiscardOldestPolicy()); for(int i=0;i<2000;i++){ if(i<200){ try { Random random = new Random(); System.out.println(random.nextInt(100)); Thread.sleep(random.nextInt(100)); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } threadPool.execute(new Runnable() { @Override public void run() { // TODO Auto-generated method stub try { //调用存储过程,对数据进行操作 t.oper(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); }
因为是集群部署,所有将调用存储过程的方法设置为同步方法也不起作,最后想到了mysql的悲观锁,设置行级别的悲观锁,然后再获取锁的下一步进行数据判断,来进行处理
//加悲观锁的语句
SELECT usableSum INTO @usableSum FROM t_user WHERE id=in_uid FOR UPDATE;
SET @usableSum = IFNULL(@usableSum,0);
IF @usableSum <=0 THEN
ROLLBACK;
SET out_ret = -7;
SET out_desc = '余额不足';
LEAVE _return;
END IF;
IF @usableSum <in_money THEN
ROLLBACK;
SET out_ret = -8;
SET out_desc = 余额不足';
LEAVE _return;
END IF;
经过测试,完美的解决了数据同步的问题