本测试参考了《redis实战》中的例子
redis.clients
jedis
2.9.0
org.springframework.boot
spring-boot-starter-data-redis
2.0.6.RELEASE
private static StringRedisTemplate redisTemplate = new StringRedisTemplate();
private static JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();
static {
//配置
redisConnectionFactory.setHostName("192.168.2.128");
redisConnectionFactory.setPort(6379);
redisConnectionFactory.setUsePool(true);
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMinIdle(50);
jedisPoolConfig.setMaxIdle(50);
jedisPoolConfig.setMaxTotal(50);
redisConnectionFactory.setPoolConfig(jedisPoolConfig);//用jedis的默认值初始化8个连接
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setEnableTransactionSupport(true);//开启redis事务
redisTemplate.afterPropertiesSet();
}
public static void main(String[] args) throws InterruptedException {
//测试
String[] sellers = new String[]{"小东1","小东2","小东3","小东4","小东5"} ;
String[] consumers = new String[] {"小马1","小马2","小马3","小马4","小马5"};
for(String seller:sellers) {
System.out.println("seller:"+seller);
Runnable selling = new Runnable() {
@Override
public void run() {
sell(seller);
}
};
new Thread(selling).start();
}
for(String consumer:consumers) {
System.out.println("consumer:"+consumer);
Runnable buying = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
buy(consumer);
}
};
new Thread(buying).start();
}
//验证多个包裹里面是否有重复商品
Thread.sleep(12*1000);
Collection inventory = new HashSet();
//inventory.add("inventory:小马1");
inventory.add("inventory:小马2");
inventory.add("inventory:小马3");
inventory.add("inventory:小马4");
inventory.add("inventory:小马5");
//redisTemplate.opsForSet().add("inventory:sum", "");
redisTemplate.opsForSet().unionAndStore("inventory:小马1", inventory, "inventory:sum");
}
总共一次请求
/**
* @param seller
* @description 小东,有数不尽的商品可以卖,而且不要钱
*
*/
public static void sell(String seller) {
int i=0;
//只卖十秒
long end = System.currentTimeMillis() + 10*1000;
while(System.currentTimeMillis()
用watch总共3次请求,用细粒度锁总共6次请求
/**
* @param consumer
* @description 小马,有数不尽的钱购物,随便花
*
*/
public static void buy(String consumer) {
//只买十秒
long end = System.currentTimeMillis() + 10*1000;
// 使用redis的watch加锁(乐观锁)
while(System.currentTimeMillis() buyItems = redisTemplate.opsForZSet().range("market", 0, 0);
redisTemplate.multi();
for(String item:buyItems) {
redisTemplate.opsForZSet().remove("market", item);
redisTemplate.opsForSet().add("inventory:"+consumer, item);
}
redisTemplate.exec();
}
/*
//构建的细粒度锁
while(System.currentTimeMillis() buyItems = redisTemplate.opsForZSet().range("market", nextInt, nextInt);
for(String item:buyItems) {
//对商品加锁
if(acquireLock(item)) {
Long rank = redisTemplate.opsForZSet().rank("market",item);
//判断商品是否还存在市场中
if(rank!=null) {
redisTemplate.multi();
redisTemplate.opsForZSet().remove("market", item);
redisTemplate.opsForSet().add("inventory:"+consumer, item);
redisTemplate.exec();
//释放锁
releaseLock(item);
}
}
}
}
*/
System.out.println("consuming完毕:"+consumer);
}
/**
* @param item
* @return true为获取商品锁成功,false为失败
* @throws InterruptedException
*/
public static boolean acquireLock(String item) {
Boolean lock = false;
try {
lock = redisTemplate.opsForValue().setIfAbsent("itemLock:"+item, "lock");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
//防止系统奔溃导致锁无法释放,锁有效期10s
if(lock) {
redisTemplate.expire("itemLock:"+item, 10, TimeUnit.SECONDS);
}
}
return lock;
}
/**
* @param item
* @return true为成功释放锁,false为失败
*
*/
public static boolean releaseLock(String item) {
return redisTemplate.delete("itemLock:"+item);
}
$ redis-benchmark.exe -h 192.168.2.128 -p 6379 -c 1 -q
PING_INLINE: 2632.62 requests per second
PING_BULK: 2575.06 requests per second
SET: 2455.31 requests per second
GET: 2606.75 requests per second
INCR: 2515.03 requests per second
LPUSH: 2479.91 requests per second
RPUSH: 2477.27 requests per second
LPOP: 2458.94 requests per second
RPOP: 2474.82 requests per second
SADD: 2436.29 requests per second
SPOP: 2448.46 requests per second
LPUSH (needed to benchmark LRANGE): 2409.93 requests per second
LRANGE_100 (first 100 elements): 2252.46 requests per second
LRANGE_300 (first 300 elements): 1274.50 requests per second
LRANGE_500 (first 450 elements): 846.59 requests per second
LRANGE_600 (first 600 elements): 675.57 requests per second
MSET (10 keys): 2390.40 requests per second
在对redis中频繁修改的集合加锁时,构建细粒度锁比使用watch能够大幅提高性能!加锁需要一定成本,在本次测试中,加锁操作(成功时)需要耗费三次请求!
** 性能对比时,也发现一个问题,在本机连虚拟机测redis性能如上图,但是在虚拟机直接测redis性能几乎是上面结果的四倍,说明优化空间还很大! **