最近公司有個項目,須要多併發完成任務,也就是一個任務控制中心控制多個WORKER的問題,這裏的核心點在於若是WORKER_A正在執行1號任務,任務中心不能讓WORKER_B重複執行1號任務,即WORKER_A和WORKER_B同時來任務中心須要互斥。html
我們的解決方案是使用MYSQL的INNODB行鎖機制完成這項工做,即便用MYSQL來充當任務中心的角色。相關參考:SELECT FOR UPDATE原理。java
CREATE TABLE `test` ( `unit_id` int(11) NOT NULL AUTO_INCREMENT, `style` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`unit_id`) ) ENGINE=InnoDB AUTO_INCREMENT=64011569 DEFAULT CHARSET=utf8
......mysql
import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Connection; import java.sql.Statement; public class Jdbc { public static void main(String[] args) throws Exception { Connection conn = null; String sql; String url = "jdbc:mysql://10.235.160.137:3306/lz_main?" + "user=lzstat&password=711TJS&useUnicode=true&characterEnco ding=UTF8"; try { Class.forName("com.mysql.jdbc.Driver");// 動態加載mysql驅動 conn = DriverManager.getConnection(url); Statement stmt = conn.createStatement(); int i = 0, result = -1; String id = ""; while (i<1000000) { i = i+1; //查找等待執行的數據 sql = "SELECT unit_id as id,style FROM test WHERE style = 0 LIMIT 1"; ResultSet rs = stmt.executeQuery(sql); if (rs.next()){ id = rs.getString(1); //鎖定執行 stmt.executeUpdate("SET AUTOCOMMIT=0;"); stmt.executeUpdate("BEGIN WORK;"); sql = "SELECT unit_id as id,style FROM test WHERE unit_id = " + id + " AND style = 0 FOR UPDATE"; ResultSet rs1 = stmt.executeQuery(sql); if (rs1.next()){ id = rs1.getString(1); sql = "UPDATE test SET style = 1 WHERE unit_id = " + id; stmt.executeUpdate(sql); sql = "COMMIT;"; result = stmt.executeUpdate(sql); if(result!=-1){ System.out.println("do things:" + id); System.out.println(System.currentTimeMillis()); sql = "update test set style = style + 1 where unit_id = " + id; result = stmt.executeUpdate(sql); } } else{ stmt.executeUpdate("COMMIT;"); } }else{ break; } } } catch (SQLException e) { System.out.println("MySQL操做錯誤"); e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { conn.close(); } } }
執行:java -cp :/home/wb-liqiu/java/libs/mysql-connector-java-5.1.13.jar Jdbc。相關原理:http://www.cnblogs.com/liqiu/p/3441038.htmlsql
在多個窗口執行這個程序,輸出相似:併發
do things:38114 1390532207770 do things:38115 1390532207785 do things:38116 1390532207804 do things:38117 1390532207818 do things:38118 1390532207833 do things:38119 1390532207848 do things:38120 1390532207862 do things:38121 1390532207877 do things:38122 1390532207891 do things:38123 1390532207906 do things:38124 1390532207920 do things:38125 1390532207933 do things:38126 1390532207947 do things:38127 1390532207962
這樣就能夠統計同一秒,執行了多少任務了。測試
1390532370秒併發數量的命令:cat log3 | grep 1390532370 | wc -lurl
我測試的綜合結果是:每秒QPS在60左右。若是增長WORKER,那麼QPS依然在50左右徘徊,說明核心瓶頸是數據表的鎖定時間spa
PS:問題code