今日在研究秒杀系统,用数据库的乐观锁可以实现,但是在高并发下可能并不好,所以就想到了缓存系统redis,因为redis本身也有锁机制,废话不多说,直接上代码,请大神指点不足的地方。
class A{
private ExecutorService executorService = Executors.newFixedThreadPool(8);
private RedisTemplate<String, String> redisTemplate;
public void initTestWatch(){
BoundHashOperations<String, String, Integer> redisHash = redisTemplate.boundHashOps("test_redis_watch");//在redis里存放一百个苹果
redisHash.put("test_redis_watch", 100);//一百个苹果
//模仿一百零一个用户抢苹果
for(int i = 1; i <= 101; i ++){
executorService.execute(new MyRunnable(redisTemplate,"用户"+i));
}
}
}
public class MyRunnable implements Runnable{
private Logger logger = LoggerTools.getInstance(getClass());
@Autowired
private RedisTemplate<String, String> redisTemplate;
private String name;
public MyRunnable(RedisTemplate<String, String> redisTemplate,String name) {
this.redisTemplate = redisTemplate;
this.name = name;
}
@Override
public void run() {
while(true){
try{
logger.info("{}进来,秒杀苹果。。。。",name);
boolean b = RedisInfoOperate.setSuccess(redisTemplate, "test_redis_watch_111", "");
if(b){
BoundHashOperations<String, String, Integer> redisHash = redisTemplate.boundHashOps("test_redis_watch");
Integer count = redisHash.get("test_redis_watch");//数量
if(count > 0){
count--;
logger.info("{}取走一个苹果,剩余{}苹果",name,count);
redisHash.put("test_redis_watch", count);
}else{
logger.info("{}没抢到,因为卖光了",name);
}
RedisInfoOperate.delKeyLock(redisTemplate, "test_redis_watch_111");
break;
}
logger.info("用户{}排队等待中。。。。",name);
Thread.sleep(500);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
public class RedisInfoOperate {
/**
* 使用redis进行并发控制
* @param redisTemplate
* @param key
* @param value
* @return
* @return: boolean
* @throws
* @author yuanxin
* @Date 2017年5月24日 下午3:22:43
*/
@SuppressWarnings("unchecked")
public static boolean setSuccess(RedisTemplate redisTemplate,final String key,final String value){
boolean flag = false ;
flag = (boolean) redisTemplate.execute(new RedisCallback() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
boolean flag = connection.setNX(key.getBytes(), value.getBytes());
return flag ;
}
});
return flag;
}
/***
* 判断key值是否存在
* @param redisTemplate
* @param key
* @return
* @return: boolean
* @throws
* @author yuanxin
* @Date 2017年5月25日 上午11:29:28
*/
@SuppressWarnings("unchecked")
public static boolean isExit(RedisTemplate redisTemplate,final String key){
boolean flag = false ;
flag = (boolean) redisTemplate.execute(new RedisCallback() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
return connection.exists(key.getBytes());
}
});
return flag;
}
/**
* 删除并发锁数据(防止数据太多)
* @param redisTemplate
* @param key
* @return: void
* @throws
* @author yuanxin
* @Date 2017年5月24日 下午3:24:56
*/
@SuppressWarnings("unchecked")
public static void delKeyLock(RedisTemplate redisTemplate,final String key){
redisTemplate.execute(new RedisCallback() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
connection.del(key.getBytes());
return null ;
}
});
}
/***
* 模糊匹配删除
* @param redisTemplate
* @param key
* @return: void
* @throws
* @author yuanxin
* @Date 2017年5月25日 上午11:29:58
*/
@SuppressWarnings("unchecked")
public static void delKeyLockMutil(RedisTemplate redisTemplate,final String key){
redisTemplate.execute(new RedisCallback() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
Set<byte[]> keys = connection.keys((key+"*").getBytes());
if(!keys.isEmpty()){
for(byte[] bytes : keys){
System.out.println(bytes[bytes.length -1]);
connection.del(bytes);
}
}
return null ;
}
});
}
}