redis结合jedis实现自带分布式锁
第一步
第二步
System.out.println("ip为"+ip+"的同学"+Thread.currentThread().getName()+"进入了商品详情的请求");
PmsSkuInfo pmsSkuInfo = new PmsSkuInfo();
//获得jedis链接
Jedis jedis = redisUtil.getJedis();
//sku的key
String skuKey="sku:"+skuId+":info";
//分布式锁
String skuLock="sku:"+skuId+":lock";
//查询缓存
String skuIdJson = jedis.get(skuKey);
//如果取到值 把json转换为对象 使用 fastJson
if(StringUtils.isNoneBlank(skuIdJson)){
System.out.println("ip为"+ip+"的同学"+Thread.currentThread().getName()+"从缓存中拿数据");
pmsSkuInfo= JSON.parseObject(skuIdJson, PmsSkuInfo.class);
}else {
//如果缓存中没有从数据库取 这又会遇见一个问题 缓存击穿
//设置分布式锁
// String token = UUID.randomUUID().toString();
// String OK=jedis.set(skuLock,token,"nx","ex",10);
RLock lock = redisson.getLock(skuLock);
try {
boolean result = lock.tryLock(100, 30, TimeUnit.SECONDS);
if(result){
//设置成功有权在10秒内访问数据库
System.out.println("ip为"+ip+"的同学"+Thread.currentThread().getName()+"获得分布式锁有权在10秒内访问数据库");
pmsSkuInfo=getSkuByIdFromDb(skuId);
if(null!=pmsSkuInfo){
//mysql数据存入 redis缓存
jedis.set(skuKey,JSON.toJSONString(pmsSkuInfo)); //正常来说需要设置过期时间
}else{
//防止缓存穿透 数据库不存在的sku
//解决方法,将 null或者 ""设置给redis
jedis.setex(skuKey,60*3,JSON.toJSONString(""));
}
System.out.println("ip为"+ip+"的同学"+Thread.currentThread().getName()+"释放锁");
}else{
//设置锁失败,自旋(该线程休眠几秒重新访问本方法)
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ip为"+ip+"的同学"+Thread.currentThread().getName()+"开始自旋");
return getSkuById(skuId,ip); //开始自旋重新访问本方法
}
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock(); //释放锁
}
}
//关闭jedis
jedis.close();