标签:package 服务器 public 计数器 import
WIN 10: i5 4440, 8GB
测试REDIS的事务速度
REDIS的WATCH机制实现事务是一个乐观锁形式(应该是SPIN LOCK的一种)。适用于并发度不是很高的场景,可以节约CPU资源(轻量级锁)。但是当竞争激烈的情况下,失败概率会大大提升,大量失败后的重试会耗费CPU资源。
测试的逻辑
1)读取计数器
2)JAVA端自增
3)设置回REDIS
此处不可用REDIS自带的incr函数,REDIS服务器端为单线程执行,所以服务器端只执行一个incr指令的情况下,其实可以看作原子操作, 服务器端直接执行1-2秒就可以了,当然取决于电脑。
计数器计算到10万为止。(线程增多,那么每个线程负载计算量就减少)
package one; import java.text.NumberFormat; import java.util.concurrent.CountDownLatch; import redis.clients.jedis.Jedis; import redis.clients.jedis.Transaction; public class TransactionContentionTest extends ConnectionBuilder { private static final int CONTENTION_LEVEL = 5; private static final int TOTAL = 20000; private static final NumberFormat nf = NumberFormat.getPercentInstance(); public static void main(String[] args) throws Exception { nf.setMinimumFractionDigits(2); buildPool(); CountDownLatch latch = new CountDownLatch(CONTENTION_LEVEL); Thread[] threads = new Thread[CONTENTION_LEVEL]; ContentionClient[] clients = new ContentionClient[CONTENTION_LEVEL]; Jedis jedis = pool.getResource(); jedis.set("TestCounter", "0"); jedis.close(); for (int i = 0; i < CONTENTION_LEVEL; i++) { ContentionClient client = new ContentionClient(); client.setTotal(TOTAL); client.setCounterName("TestCounter"); client.setJedis(pool.getResource()); client.setLatch(latch); clients[i] = client; threads[i] = new Thread(client); } long start = System.currentTimeMillis(); for (int i = 0; i < CONTENTION_LEVEL; i++) { threads[i].start(); } latch.await(); long end = System.currentTimeMillis(); System.out.println("Elapse:" + (end - start) + " ms"); for (int i = 0; i < CONTENTION_LEVEL; i++) { Double failRate = (double) clients[i].getFailCount() / TOTAL; System.out.println(i + " Fail Rate:" + nf.format(failRate)); clients[i].getJedis().close(); } close(); } static class ContentionClient implements Runnable { private Jedis jedis; private String counterName; private int total; private long failCount = 0; public CountDownLatch getLatch() { return latch; } public void setLatch(CountDownLatch latch) { this.latch = latch; } private CountDownLatch latch; public Jedis getJedis() { return jedis; } public void setJedis(Jedis jedis) { this.jedis = jedis; } public String getCounterName() { return counterName; } public void setCounterName(String counterName) { this.counterName = counterName; } public int getTotal() { return total; } public void setTotal(int total) { this.total = total; } public long getFailCount() { return failCount; } public void setFailCount(long failCount) { this.failCount = failCount; } @Override public void run() { while (total > 0) { jedis.watch(counterName); Integer counter = Integer.parseInt(jedis.get(counterName)); Transaction tx = jedis.multi(); counter++; tx.set(counterName, counter.toString()); if (tx.exec() == null) { jedis.unwatch(); failCount++; } else { total--; } } latch.countDown(); } } }
分别测试多组数据
线程数 | 1 | 2 | 4 | 8 | 16 |
重试率 | 0 | 67% | 185% | 435% | 900% |
耗时 | 21055ms | 19312 | 21136 | 34231 | 65964 |
用乐观锁机制并发度稍微高一点的情况,资源耗费非常严重。
毕竟用的是WINDOWS和家用机,测试的数据,没有参考价值。
本文出自 “Tech Doc” 博客,谢绝转载!
标签:package 服务器 public 计数器 import
原文地址:http://mindoverflow.blog.51cto.com/11468509/1769566