利用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;

經過測試,完美的解決了數據同步的問題,

如果使用的Hibernate進行數據庫操作,可以使用以下方式對數據庫進行加鎖

 String hqlStr ="from TUser as user where user.name='Erica'";

 Query query = session.createQuery(hqlStr);

  query.setLockMode("user",LockMode.UPGRADE); // 加鎖

  List userList = query.list();// 執行查詢,獲取數據

query.setLockMode 對查詢語句中,特定別名所對應的記錄進行加鎖(我們為 TUser 類指定了一個別名 “user” ),這里也就是對返回的所有 user 記錄進行加鎖。

但是使用悲觀鎖對數據庫的性能開銷影響比較大,如果是大量的多線程並發的話,會造成數據庫性能開銷營銷太大,這個時候推薦使用樂觀鎖來進行加鎖,樂觀鎖相對於悲觀鎖采取了更加寬松的加鎖機制,悲觀鎖屬於排他的,當對數據進行加鎖后,其他人無法獲取此數據,只能當上個操作釋放掉鎖,悲觀鎖是利用字段來進行加鎖的,可以在表中添加一個字段version,每次獲取version,同時更新數據的時候,將此version進行+1操作,對version進行對比


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM