今天在做项目使用redis分布式锁时,出现一个小bug-----FastJson处理数据出现错误
`com.alibaba.fastjson.JSONException: syntax error, expect {, actual error, pos 1`
开始以为是页面发送json格式错误或则是数据有问题,就一直找寻json格式问题,以为自己代码没问题。后来发现自己在设置锁key时和获取锁key,不一致。导致获取数据有问题.
代码
public PmsSkuInfo item(String skuId) {
System.err.println(Thread.currentThread().getName() + ":开始访问");
PmsSkuInfo pmsSkuInfo = new PmsSkuInfo();
//请求缓存
Jedis jedis = redisUtil.getJedis();
try {
//设置redisKey object:id:filed skuInfo:skuId:lock,缓存规则
String skuInfoJson = jedis.get("skuInfo:"+skuId+":info");
//缓存中没有数据
if (StringUtils.isBlank(skuInfoJson)) {
//解决缓存击透,缓存击穿,缓存雪崩,加上分布式锁
System.err.println(Thread.currentThread().getName() + ":没有访问到缓存,去设置分布式锁");
//获取分布式锁,返回操作结果
String uuid = UUID.randomUUID().toString();
String OK = jedis.set("skuInfo:" + skuId + ":lock", uuid, "nx", "px", 10000);
//返回结果不为空且等于"ok",则设置分布式锁成功,开始访问db
if (StringUtils.isNotBlank(OK) && OK.equals("OK")) {
System.err.println(Thread.currentThread().getName() + ":设置分布式锁成功,开始访问db");
//访问db
pmsSkuInfo = itemFromDb(skuId);
try {
//睡眠等待
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.err.println(Thread.currentThread().getName() + ":访问db结束,更新数据到缓存");
//查询有结果则更新到redis中
if (pmsSkuInfo != null) {
jedis.set("skuInfo:"+skuId+":info", JSON.toJSONString(pmsSkuInfo));
}
//采用lua脚本,使得获取和删除同步进行。不会发生锁失效,删除他人的锁
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object eval = jedis.eval(script, Collections.singletonList("skuInfo:" + skuId + ":lock"), Collections.singletonList(uuid));
} else {
//没有访问到缓存
System.err.println(Thread.currentThread().getName() + ":没有访问到缓存,设置分布式锁失败,开始自旋");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//自旋
return item(skuId);
}
} else {
//缓存不为空,转化缓存
pmsSkuInfo = JSON.parseObject(skuInfoJson,PmsSkuInfo.class);
}
} finally {
//关流
jedis.close();
}
System.err.println(Thread.currentThread().getName() + ":结束访问");
return pmsSkuInfo;
}
还是要相信科学啊!!!