Ticket Servers: Distributed Unique Primary Keys on the Cheap
测试一下主键生成的性能,通过代码调用生成10万次主键为例。
测试的机器:8G内存,自身跑着7个tomcat,每个分配512M内存。mysql也安装在此机器上。
1、innodb无事务(never)
单线程:746秒,每个请求7.4秒
10线程:540秒,每个请求5.4秒
50线程:耗时太长,2449,每个请求24秒,经过查找,发现是数据库连接池最大数量限制为20影响了性能。把最大连接数改为100,更恶性的事件产生了,DB中的线程竟然开始互相竞争起来,导致严重影响性能。
2、innodb事务
3、MYISAM无事务
单线程:476秒,平均每次请求4.7ms
10线程: 244秒,平均每次请求2.4ms
50线程:237秒,平均每秒2.3ms
100线程:235秒,平均每秒2.3ms
4、MYISAM有事务(MYISAM本身不支持事务,只是测试下spring aop的影响)
单线程:在aop事务中,503秒,每个请求5ms,不在aop事务中,446秒,每秒请求4.4
10线程:在aop事务中,238秒,每个请求2.3秒,不在aop事务中,234秒,每个请求2.3秒
结论:InnoDB是并发数达到一定数据后,DB中锁的竞争厉害。但是myisam表倒没有这种问题,并发数在100时也没有遇到问题。
在aop事务中多少会有一点影响,但本身是myisam表,影响在可接受范围内。
可改进的地方:这次测试只是使用一个表,在flicker中,也介绍了如何分表来分担负载。但对这个项目来说,已经足够满足需求了。暂不考虑分表。
——————————————————————————————
2015.03.09
附下项目中使用的代码:
package cn.joylab.game.service.impl; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import cn.joylab.game.dao2.Ticket32Dao; import cn.joylab.game.dao2.Ticket64Dao; import cn.joylab.game.model.Ticket32; import cn.joylab.game.model.Ticket64; import cn.joylab.game.service.TicketManager; @Component("ticketManager") public class TicketManagerImpl implements TicketManager { private static final int NUM = 1000; private AtomicInteger a32 = new AtomicInteger(); private AtomicInteger a32_ = new AtomicInteger(); private AtomicInteger b32 = new AtomicInteger(); private AtomicInteger b32_ = new AtomicInteger(); private AtomicInteger c32 = new AtomicInteger(); private AtomicInteger c32_ = new AtomicInteger(); private AtomicInteger d32 = new AtomicInteger(); private AtomicInteger d32_ = new AtomicInteger(); private AtomicInteger e32 = new AtomicInteger(); private AtomicInteger e32_ = new AtomicInteger(); private AtomicInteger f32 = new AtomicInteger(); private AtomicInteger f32_ = new AtomicInteger(); private AtomicInteger g32 = new AtomicInteger(); private AtomicInteger g32_ = new AtomicInteger(); private AtomicInteger h32 = new AtomicInteger(); private AtomicInteger h32_ = new AtomicInteger(); private AtomicLong a64 = new AtomicLong(); private AtomicLong a64_ = new AtomicLong(); private AtomicLong b64 = new AtomicLong(); private AtomicLong b64_ = new AtomicLong(); private AtomicLong c64 = new AtomicLong(); private AtomicLong c64_ = new AtomicLong(); private AtomicLong d64 = new AtomicLong(); private AtomicLong d64_ = new AtomicLong(); private AtomicLong e64 = new AtomicLong(); private AtomicLong e64_ = new AtomicLong(); private AtomicLong f64 = new AtomicLong(); private AtomicLong f64_ = new AtomicLong(); private AtomicLong g64 = new AtomicLong(); private AtomicLong g64_ = new AtomicLong(); private AtomicLong h64 = new AtomicLong(); private AtomicLong h64_ = new AtomicLong(); public int getNewId32(String stub) { if ("a".equals(stub)) { return getNewId32_1(stub, a32, a32_); } else if ("b".equals(stub)) { return getNewId32_1(stub, b32, b32_); } else if ("c".equals(stub)) { return getNewId32_1(stub, c32, c32_); } else if ("d".equals(stub)) { return getNewId32_1(stub, d32, d32_); } else if ("e".equals(stub)) { return getNewId32_1(stub, e32, e32_); } else if ("f".equals(stub)) { return getNewId32_1(stub, f32, f32_); } else if ("g".equals(stub)) { return getNewId32_1(stub, g32, g32_); } else if ("h".equals(stub)) { return getNewId32_1(stub, h32, h32_); } else { log.error("未解析的字符串:" + stub); } return -1; } private int getNewId32_1(String stub, AtomicInteger a, AtomicInteger b) { if (a.get() == 0) { int id = getNewId32_2(stub); a.set(id); b.set(NUM); return id * NUM; } int i = b.decrementAndGet(); if (i > 0) { return a.get() * NUM + (NUM - i); } else { int id = getNewId32_2(stub); a.set(id); b.set(NUM); return id * NUM; } } private int getNewId32_2(String stub) { Ticket32 ticket32 = new Ticket32(); ticket32.setStub(stub); if ("a".equals(stub)) { ticket32Dao.getNewId_a(ticket32); } else if ("b".equals(stub)) { ticket32Dao.getNewId_b(ticket32); } else if ("c".equals(stub)) { ticket32Dao.getNewId_c(ticket32); } else if ("d".equals(stub)) { ticket32Dao.getNewId_d(ticket32); } else if ("e".equals(stub)) { ticket32Dao.getNewId_e(ticket32); } else if ("f".equals(stub)) { ticket32Dao.getNewId_f(ticket32); } else if ("g".equals(stub)) { ticket32Dao.getNewId_g(ticket32); } else if ("h".equals(stub)) { ticket32Dao.getNewId_h(ticket32); } else { log.error("未解析的字符串:" + stub); } return ticket32.getId(); } public long getNewId64(String stub) { if ("a".equals(stub)) { return getNewId64_1(stub, a64, a64_); } else if ("b".equals(stub)) { return getNewId64_1(stub, b64, b64_); } else if ("c".equals(stub)) { return getNewId64_1(stub, c64, c64_); } else if ("d".equals(stub)) { return getNewId64_1(stub, d64, d64_); } else if ("e".equals(stub)) { return getNewId64_1(stub, e64, e64_); } else if ("f".equals(stub)) { return getNewId64_1(stub, f64, f64_); } else if ("g".equals(stub)) { return getNewId64_1(stub, g64, g64_); } else if ("h".equals(stub)) { return getNewId64_1(stub, h64, h64_); } else { log.error("未解析的字符串:" + stub); } return -1; } private long getNewId64_1(String stub, AtomicLong a, AtomicLong b) { if (a.get() == 0) { long id = getNewId64_2(stub); a.set(id); b.set(NUM); return id * NUM; } long i = b.decrementAndGet(); if (i > 0) { return a.get() * NUM + (NUM - i); } else { long id = getNewId64_2(stub); a.set(id); b.set(NUM); return id * NUM; } } private long getNewId64_2(String stub) { Ticket64 ticket64 = new Ticket64(); ticket64.setStub(stub); if ("a".equals(stub)) { ticket64Dao.getNewId_a(ticket64); } else if ("b".equals(stub)) { ticket64Dao.getNewId_b(ticket64); } else if ("c".equals(stub)) { ticket64Dao.getNewId_c(ticket64); } else if ("d".equals(stub)) { ticket64Dao.getNewId_d(ticket64); } else if ("e".equals(stub)) { ticket64Dao.getNewId_e(ticket64); } else if ("f".equals(stub)) { ticket64Dao.getNewId_f(ticket64); } else if ("g".equals(stub)) { ticket64Dao.getNewId_g(ticket64); } else if ("h".equals(stub)) { ticket64Dao.getNewId_h(ticket64); } else { log.error("未解析的字符串:" + stub); } return ticket64.getId(); } @Autowired private Ticket32Dao ticket32Dao; @Autowired private Ticket64Dao ticket64Dao; private static final Log log = LogFactory.getLog(TicketManagerImpl.class); }
0 条评论。