ID生成服务本身应该串行化,避免锁竞争.
使用这种自定义序列,1百万ID的生成时间是14s.效果非常明显.
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.ResultSet;
- import java.sql.Statement;
- import java.util.concurrent.Callable;
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.Future;
- public class SeqGenerator {
- private static ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
- private static int currentVal = -1;
- private static int maxVal = -1;
- private static int fetchSize = 10000;
- static{
- try {
- fetchFromDB();
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- public static int getSeq() throws InterruptedException, ExecutionException {
- Callable<Integer> c = new Callable<Integer>() {
- @Override
- public Integer call() throws Exception {
- int result = currentVal;
- if (currentVal > maxVal) {
- fetchFromDB();
- result = currentVal;
- }
- currentVal++;
- return result;
- }
- };
- Future<Integer> task = singleThreadExecutor.submit(c);
- return task.get().intValue();
- }
- private static void fetchFromDB() throws Exception {
- Class.forName("com.mysql.jdbc.Driver");
- Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "xx", "xx");
- connection.setAutoCommit(false);
- Statement st = connection.createStatement();
- ResultSet rs = st.executeQuery("select * from test for update");
- rs.next();
- currentVal = rs.getInt(1) + 1;
- rs.close();
- st.executeUpdate("update test set id=id+" + fetchSize);
- rs = st.executeQuery("select * from test for update");
- rs.next();
- maxVal = rs.getInt(1);
- connection.commit();
- rs.close();
- st.close();
- connection.close();
- }
- public static void main(String[] args) throws Exception {
- int i = 1000000;
- long start = System.currentTimeMillis();
- while (i > 0) {
- System.out.println(SeqGenerator.getSeq());
- i--;
- }
- long end = System.currentTimeMillis();
- System.out.println(end - start);
- }
- }