Watch命令
watch命令可以监控一个或多个键,一旦其中有一个键被修改或删除,之后的事务就不会执行。监控一直持续到exec命令,事务中的命令是在exec之后才执行的,所以在multi命令后可以修改watch监控的键值。假设我们通过watch命令在事务执行之前监控了多个Key,这时在watch之后有任何Key的值发生了变化,exec命令执行的事务都将被放弃。
在业务中的应用
1.创建Redis操作工具类
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
@Service
public class RedisService {
@Autowired
private JedisPool jedisPool;
/**
* 获取对象
*/
public <T> T get(String key,Class<T> clazz){
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
String sval = jedis.get(key);
//将String转换为Bean
T t = stringToBean(sval,clazz);
return t;
}finally {
if(jedis != null) {
jedis.close();
}
}
}
/**
* 设置对象
*/
public <T> boolean set(String key,T value){
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//将Bean转换为String
String s = beanToString(value);
if(s == null || s.length() <= 0) {
return false;
}
jedis.set(key, s);
return true;
}finally {
if(jedis != null) {
jedis.close();
}
}
}
/**
* 减少值
*/
public <T> Long decr(String key){
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//返回value减1后的值
return jedis.decr(key);
}finally {
if(jedis != null) {
jedis.close();
}
}
}
/**
* 将字符串转换为Bean对象
*/
@SuppressWarnings("unchecked")
public static <T> T stringToBean(String str,Class<T> clazz) {
if(str == null || str.length() == 0 || clazz == null) {
return null;
}
if(clazz == int.class || clazz == Integer.class) {
return ((T) Integer.valueOf(str));
}else if(clazz == String.class) {
return (T) str;
}else if(clazz == long.class || clazz == Long.class) {
return (T) Long.valueOf(str);
}else if(clazz == List.class) {
return JSON.toJavaObject(JSONArray.parseArray(str), clazz);
}else {
return JSON.toJavaObject(JSON.parseObject(str), clazz);
}
}
/**
* 将Bean对象转换为字符串类型
*/
public static <T> String beanToString(T value) {
if(value == null){
return null;
}
Class<?> clazz = value.getClass();
if(clazz == int.class || clazz == Integer.class) {
return ""+value;
}else if(clazz == String.class) {
return (String)value;
}else if(clazz == long.class || clazz == Long.class) {
return ""+value;
}else {
return JSON.toJSONString(value);
}
}
}
2.秒杀业务调用
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Response;
import redis.clients.jedis.Transaction;
import cn.com.app.redis.RedisService;
@Controller
public class RedisWatchController implements InitializingBean {
@Autowired
private RedisService redisService;
@Autowired
private JedisPool jedisPool;
//内存标记,减少redis访问
private HashMap<String, Boolean> localOverMap = new HashMap<String, Boolean>();
/**
* 系统初始化的时把商品库存加入到缓存中
*/
@Override
public void afterPropertiesSet() throws Exception {
//设置默认商品库存
redisService.set("goodsStock", "10");
//添加内存标记
localOverMap.put("goodsStock", false);
}
/**
* 请求秒杀,redis watch事务方式
*/
@RequestMapping(value="/miaoshawatch")
@ResponseBody
public String miaoshawatch(HttpServletRequest request,@RequestParam("userid")String userid){
boolean over = localOverMap.get("goodsStock");
if(over) {
System.out.println("秒杀结束");
return "秒杀结束";
}
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//监视商品库存key和订单key
jedis.watch("goodsStock","order"+userid);
String orderInfo = redisService.get("order"+userid,String.class);
if(orderInfo != null){
System.out.println("重复下单");
return "重复下单";
}
int count = redisService.get("goodsStock",Integer.class);
if(count <= 0){
localOverMap.put("goodsStock", true);
System.out.println("库存不足");
return "库存不足";
}
//开启事务
Transaction transaction = jedis.multi();
//保存订单
transaction.set("order"+userid, userid+"_"+UUID.randomUUID().toString());
//扣减库存
Response<Long> v = transaction.decrBy("goodsStock",1);
List<Object> result = transaction.exec();
if(result == null || result.isEmpty()){
System.out.println("秒杀失败");
return "秒杀失败";
}else{
System.out.println("秒杀成功,剩余:" + v.get().intValue());
/**
* 数据库操作减少库存,下订单,在一个事务中
*/
}
}finally {
if(jedis != null) {
jedis.close();
}
}
return "秒杀成功";
}
}
王绍桦 发布了92 篇原创文章 · 获赞 131 · 访问量 15万+ 私信 关注