package com.macro.mall.portal.service.impl;
import com.macro.mall.common.utils.JsonUtils;
import com.macro.mall.common.utils.RedisUtil;
import com.macro.mall.model.PmsProduct;
import com.macro.mall.portal.dao.PmsProductDao;
import com.macro.mall.portal.service.PmsProductService;
import com.mysql.cj.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import javax.annotation.Resource;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@Service
public class PmsProductServiceImpl implements PmsProductService {
private static final Logger LOGGER = LoggerFactory.getLogger(PmsProductServiceImpl.class);
@Autowired
private PmsProductDao pmsProductDao;
@Autowired
private RedisUtil redisUtil;
@Resource
private RedisTemplate<String, Object> redisTemplate;
private static final String KEY_PREFIX = "sku:info:id:";
private static final String KEY = "sku:id:";
public static final String LOCK_PREFIX = "redis:lock:id:";
@Override
public PmsProduct list(Long id,String ip) {
System.out.println("当前" + ip + "正在访问");
String key = KEY_PREFIX;
String lockKey = LOCK_PREFIX + id;
String infoKey = KEY + id;
if (redisUtil.hasKey(key)) {
return (PmsProduct) redisUtil.get(key);
} else {
System.out.println("ip为" + ip + "在缓存中没有查到,申请分布式锁" + lockKey);
String token = UUID.randomUUID().toString();
Jedis jedis = new Jedis("localhost", 6379);
String lock = jedis.set(lockKey, token, "nx", "px", 10 * 1000);
if (null != lock && "OK".equals(lock)) {
PmsProduct list = pmsProductDao.list(id);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (list != null) {
BoundHashOperations<String, Object, Object> stringObjectObjectBoundHashOperations = redisTemplate.boundHashOps(key);
stringObjectObjectBoundHashOperations.put(infoKey, JsonUtils.serialize(list));
Random r = new Random();
stringObjectObjectBoundHashOperations.expire(r.nextInt(123), TimeUnit.SECONDS);
return list;
} else {
BoundHashOperations<String, Object, Object> hashOperations = redisTemplate.boundHashOps(key);
hashOperations.put(key, "");
hashOperations.expire(60 * 3, TimeUnit.SECONDS);
}
String localToken = jedis.get(lockKey);
if (null != localToken && token.equals(localToken)) {
String script = "if redis.call('get',KEYS[1] == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
Long eval = (Long) jedis.eval(script, Integer.parseInt(lockKey),localToken);
if (eval != null && eval != 0) {
jedis.del(lockKey);
}
System.out.println("ip" + ip + "申请分布式锁成功,并已删除");
}
} else {
System.out.println("ip为" + ip + "申请分布式锁失败" + lockKey);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return list(id, ip);
}
}
return null;
}
}
public boolean lock(String lock) {
return (boolean) redisTemplate.execute((RedisCallback) connection -> {
long expireAt = System.currentTimeMillis() + LOCK_EXPIRE + 1;
Boolean acquire = connection.setNX(lock.getBytes(), String.valueOf(expireAt).getBytes());
if (acquire) {
return true;
} else {
byte[] bytes = connection.get(lock.getBytes());
if (Objects.nonNull(bytes) && bytes.length > 0) {
long expireTime = Long.parseLong(new String(bytes));
if (expireTime < System.currentTimeMillis()) {
byte[] set = connection.getSet(lock.getBytes(), String.valueOf(System.currentTimeMillis() + LOCK_EXPIRE + 1).getBytes());
return Long.parseLong(new String(set)) < System.currentTimeMillis();
}
}
}
return false;
});
}
public void deleteLock(String key) {
redisTemplate.delete(key);
}
关注公众号免费领取技术书籍和面试资料