package redis.clients.jedis;
import java.net.URI;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocketFactory;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.jedis.exceptions.JedisException;
import redis.clients.util.JedisURIHelper;
import redis.clients.util.Pool;
public class JedisPool extends Pool<Jedis> {
public JedisPool() {
this((String)"localhost", 6379);
}
public JedisPool(GenericObjectPoolConfig poolConfig, String host) {
this(poolConfig, host, 6379, 2000, (String)null, 0, (String)null);
}
public JedisPool(String host, int port) {
this(new GenericObjectPoolConfig(), host, port, 2000, (String)null, 0, (String)null);
}
public JedisPool(String host) {
URI uri = URI.create(host);
if (JedisURIHelper.isValid(uri)) {
String h = uri.getHost();
int port = uri.getPort();
String password = JedisURIHelper.getPassword(uri);
int database = JedisURIHelper.getDBIndex(uri);
boolean ssl = uri.getScheme().equals("rediss");
this.internalPool = new GenericObjectPool(new JedisFactory(h, port, 2000, 2000, password, database, (String)null, ssl, (SSLSocketFactory)null, (SSLParameters)null, (HostnameVerifier)null), new GenericObjectPoolConfig());
} else {
this.internalPool = new GenericObjectPool(new JedisFactory(host, 6379, 2000, 2000, (String)null, 0, (String)null, false, (SSLSocketFactory)null, (SSLParameters)null, (HostnameVerifier)null), new GenericObjectPoolConfig());
}
}
public JedisPool(String host, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
URI uri = URI.create(host);
if (JedisURIHelper.isValid(uri)) {
String h = uri.getHost();
int port = uri.getPort();
String password = JedisURIHelper.getPassword(uri);
int database = JedisURIHelper.getDBIndex(uri);
boolean ssl = uri.getScheme().equals("rediss");
this.internalPool = new GenericObjectPool(new JedisFactory(h, port, 2000, 2000, password, database, (String)null, ssl, sslSocketFactory, sslParameters, hostnameVerifier), new GenericObjectPoolConfig());
} else {
this.internalPool = new GenericObjectPool(new JedisFactory(host, 6379, 2000, 2000, (String)null, 0, (String)null, false, (SSLSocketFactory)null, (SSLParameters)null, (HostnameVerifier)null), new GenericObjectPoolConfig());
}
}
public JedisPool(URI uri) {
this(new GenericObjectPoolConfig(), (URI)uri, 2000);
}
public JedisPool(URI uri, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
this(new GenericObjectPoolConfig(), uri, 2000, sslSocketFactory, sslParameters, hostnameVerifier);
}
public JedisPool(URI uri, int timeout) {
this(new GenericObjectPoolConfig(), uri, timeout);
}
public JedisPool(URI uri, int timeout, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
this(new GenericObjectPoolConfig(), uri, timeout, sslSocketFactory, sslParameters, hostnameVerifier);
}
public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, String password) {
this(poolConfig, host, port, timeout, password, 0, (String)null);
}
public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, String password, boolean ssl) {
this(poolConfig, host, port, timeout, password, 0, (String)null, ssl);
}
public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, String password, boolean ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
this(poolConfig, host, port, timeout, password, 0, (String)null, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
}
public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port) {
this(poolConfig, host, port, 2000, (String)null, 0, (String)null);
}
public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, boolean ssl) {
this(poolConfig, host, port, 2000, (String)null, 0, (String)null, ssl);
}
public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, boolean ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
this(poolConfig, host, port, 2000, (String)null, 0, (String)null, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
}
public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout) {
this(poolConfig, host, port, timeout, (String)null, 0, (String)null);
}
public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, boolean ssl) {
this(poolConfig, host, port, timeout, (String)null, 0, (String)null, ssl);
}
public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, boolean ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
this(poolConfig, host, port, timeout, (String)null, 0, (String)null, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
}
public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, String password, int database) {
this(poolConfig, host, port, timeout, password, database, (String)null);
}
public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, String password, int database, boolean ssl) {
this(poolConfig, host, port, timeout, password, database, (String)null, ssl);
}
public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, String password, int database, boolean ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
this(poolConfig, host, port, timeout, password, database, (String)null, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
}
public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, String password, int database, String clientName) {
this(poolConfig, host, port, timeout, timeout, password, database, clientName, false, (SSLSocketFactory)null, (SSLParameters)null, (HostnameVerifier)null);
}
public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, String password, int database, String clientName, boolean ssl) {
this(poolConfig, host, port, timeout, timeout, password, database, clientName, ssl, (SSLSocketFactory)null, (SSLParameters)null, (HostnameVerifier)null);
}
public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, String password, int database, String clientName, boolean ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
this(poolConfig, host, port, timeout, timeout, password, database, clientName, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
}
public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int connectionTimeout, int soTimeout, String password, int database, String clientName, boolean ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
super(poolConfig, new JedisFactory(host, port, connectionTimeout, soTimeout, password, database, clientName, ssl, sslSocketFactory, sslParameters, hostnameVerifier));
}
public JedisPool(GenericObjectPoolConfig poolConfig, URI uri) {
this(poolConfig, (URI)uri, 2000);
}
public JedisPool(GenericObjectPoolConfig poolConfig, URI uri, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
this(poolConfig, uri, 2000, sslSocketFactory, sslParameters, hostnameVerifier);
}
public JedisPool(GenericObjectPoolConfig poolConfig, URI uri, int timeout) {
this(poolConfig, uri, timeout, timeout);
}
public JedisPool(GenericObjectPoolConfig poolConfig, URI uri, int timeout, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
this(poolConfig, uri, timeout, timeout, sslSocketFactory, sslParameters, hostnameVerifier);
}
public JedisPool(GenericObjectPoolConfig poolConfig, URI uri, int connectionTimeout, int soTimeout) {
super(poolConfig, new JedisFactory(uri, connectionTimeout, soTimeout, (String)null, false, (SSLSocketFactory)null, (SSLParameters)null, (HostnameVerifier)null));
}
public JedisPool(GenericObjectPoolConfig poolConfig, URI uri, int connectionTimeout, int soTimeout, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
super(poolConfig, new JedisFactory(uri, connectionTimeout, soTimeout, (String)null, uri.getScheme() != null && uri.getScheme().equals("rediss"), sslSocketFactory, sslParameters, hostnameVerifier));
}
public Jedis getResource() {
Jedis jedis = (Jedis)super.getResource();
jedis.setDataSource(this);
return jedis;
}
/** @deprecated */
@Deprecated
public void returnBrokenResource(Jedis resource) {
if (resource != null) {
this.returnBrokenResourceObject(resource);
}
}
/** @deprecated */
@Deprecated
public void returnResource(Jedis resource) {
if (resource != null) {
try {
resource.resetState();
this.returnResourceObject(resource);
} catch (Exception var3) {
this.returnBrokenResource(resource);
throw new JedisException("Could not return the resource to the pool", var3);
}
}
}
}
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class RedisUtil {
private JedisPool jedisPool;
public void initPool(String host,int port ,int database){
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(200);
poolConfig.setMaxIdle(30);
poolConfig.setBlockWhenExhausted(true);
poolConfig.setMaxWaitMillis(10*1000);
poolConfig.setTestOnBorrow(true);
jedisPool=new JedisPool(poolConfig,host,port,20*1000);
}
public Jedis getJedis(){
Jedis jedis = jedisPool.getResource();
// 正确释放资源
return jedis;
}
}
public PmsSkuInfo getskuById(String skuId, String remoteAddr) {
System.out.println("ip为"+remoteAddr+"的帅哥美女"+Thread.currentThread().getName()+"进入商品详情页面");
PmsSkuInfo pmsSkuInfo = new PmsSkuInfo();
// 链接缓存
Jedis jedis = redisUtil.getJedis();
// 查询缓存
String skuKey = "sku:" + skuId + ":info";
String skuJson = jedis.get(skuKey);
if (StringUtils.isNotBlank(skuJson)) {//if(skuJson!=null&&!skuJson.equals(""))
System.out.println("ip为"+remoteAddr+"的帅哥美女"+Thread.currentThread().getName()+"进入缓存");
pmsSkuInfo = JSON.parseObject(skuJson, PmsSkuInfo.class);
} else {
System.out.println("ip为"+remoteAddr+"的帅哥美女"+Thread.currentThread().getName()+"进入开始查询数据库");
// 如果缓存中没有,查询mysql
// 设置分布式锁
String token = UUID.randomUUID().toString();
String OK = jedis.set("sku:" + skuId + ":lock", token, "nx", "px", 10*1000);
//拿到锁就查询
if(StringUtils.isNotBlank(OK)&&OK.equals("OK")){
System.out.println("ip为"+remoteAddr+"的帅哥美女"+Thread.currentThread().getName()+"拿到锁");
pmsSkuInfo = getItemInfoById(skuId);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (pmsSkuInfo != null) {
// mysql查询结果存入redis
jedis.set("sku:" + skuId + ":info", JSON.toJSONString(pmsSkuInfo));
}else {
System.out.println("ip为"+remoteAddr+"的帅哥美女"+Thread.currentThread().getName()+"查询null");
//数据库不存在就设置空/null给redis,防止数据库穿透
jedis.setex("sku:"+skuId+":info",60*3,JSON.toJSONString(""));
}
System.out.println("ip为"+remoteAddr+"的帅哥美女"+Thread.currentThread().getName()+"释放锁");
//释放锁 根据key匹配vulue,匹配上了就删除锁(防止误删其他线程的锁)
String lockToken = jedis.get("sku:" + skuId + ":lock");
// if(StringUtils.isNotBlank(lockToken)&&lockToken.equals(token)){
// jedis.del("sku:" + skuId + ":lock");
// }
//对比防重删令牌 lua
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
jedis.eval(script, Collections.singletonList(lockToken),
Collections.singletonList(token));
}else {
//没拿到锁就自旋
System.out.println("ip为"+remoteAddr+"的帅哥美女"+Thread.currentThread().getName()+"开始自旋");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return getskuById(skuId, remoteAddr);
}
}
jedis.close();
return pmsSkuInfo;
}
-----------------------------模板
public List<CategoryVO> queryCategoryByPidCategoryVO(Long parentCid) {
String cates = redisTemplate.opsForValue().get(KEY_PREFIX + parentCid);
if (StringUtils.isNotBlank(cates)){
return JSON.parseArray(cates,CategoryVO.class);
}
//开始分布式锁
List<CategoryVO> categoryVOS =null;
//唯一标识 防止等会误删锁
String uuid= UUID.randomUUID().toString();
Boolean ifAbsent = redisTemplate.opsForValue().setIfAbsent("lock", uuid, 3, TimeUnit.MINUTES);
if (ifAbsent){
//查询数据库
categoryVOS = pmsClient.queryCategoryByPidCategoryVO(parentCid).getData();
//存入redis 没有判空,防止缓存穿透(存空值) 设置随机过期时间,防止缓存雪崩
redisTemplate.opsForValue().set(KEY_PREFIX + parentCid,JSON.toJSONString(categoryVOS),5+new Random().nextInt(5), TimeUnit.DAYS);
//释放锁 del
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
//获取唯一标识
String lock = redisTemplate.opsForValue().get("lock");
//执行删除
this.redisTemplate.execute(new DefaultRedisScript<>(script), Arrays.asList(lock), Arrays.asList(uuid));
}else {
// 每隔1秒钟回调一次,再次尝试获取锁
try {
Thread.sleep(500);
return queryCategoryByPidCategoryVO(parentCid);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return categoryVOS;
}
----------------------------------------------redisson推荐-----------------------
public List<CategoryVO> queryCategoryByPidCategoryVO(Long parentCid) {
//判断缓存是否存在
String cates = redisTemplate.opsForValue().get(KEY_PREFIX + parentCid);
if (StringUtils.isNotBlank(cates)){
return JSON.parseArray(cates,CategoryVO.class);
}
//开始分布式锁
RLock lock = redissonClient.getLock("lock" + parentCid);//只锁当前进入的parentCid
lock.lock();
//判断缓存是否存在
String cates02 = redisTemplate.opsForValue().get(KEY_PREFIX + parentCid);
if (StringUtils.isNotBlank(cates02)){
lock.unlock();//释放锁
return JSON.parseArray(cates02,CategoryVO.class);
}
//查询数据库
List<CategoryVO> categoryVOS = pmsClient.queryCategoryByPidCategoryVO(parentCid).getData();
//存入redis 没有判空,防止缓存穿透(存空值) 设置随机过期时间,防止缓存雪崩
redisTemplate.opsForValue().set(KEY_PREFIX + parentCid,JSON.toJSONString(categoryVOS),5+new Random().nextInt(5), TimeUnit.DAYS);
lock.unlock();//释放锁
return categoryVOS;
}
--------------------------抽取 注解+Aop-----------------------------------------------------------------
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedissonCache {
//相互等价 value=prefix
@AliasFor("prefix")
String value() default "";
// 缓存中key的前缀
@AliasFor("value")
String prefix() default "";
// 过期时间 单位:分
int timeout() default 5;
// 随机时间 单位:分
int random() default 5;
}
import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.index.annotation.RedissonCache;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
@Aspect
@Component
public class RedissonAop {
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private RedissonClient redissonClient;
/**
* 1.返回值object
* 2.参数proceedingJoinPoint
* 3.抛出异常Throwable
* 4.proceedingJoinPoint.proceed(args)执行业务方法
*/
@Around("@annotation(com.atguigu.gmall.index.annotation.RedissonCache)")
public Object cacheAroundAdvice(ProceedingJoinPoint point) throws Throwable {
Object result =null;
// 获取连接点签名
MethodSignature methodSignature = (MethodSignature) point.getSignature();
// 获取连接点的RedissonCache注解信息
RedissonCache annotation = methodSignature.getMethod().getAnnotation(RedissonCache.class);
// 获取缓存的前缀
String prefix = annotation.prefix();
//获取目标方法的参数列表
Object[] args = point.getArgs();
// 组装成key
String key = prefix + Arrays.asList(args).toString();
// 1. 查询缓存
result = this.cacheHit(methodSignature, key);
if (result!=null){
return result;
}
// 初始化分布式锁
RLock lock = redissonClient.getLock("lock" + Arrays.asList(args).toString());
lock.lock(); // 防止缓存穿透 加锁
// 再次检查内存是否有,因为高并发下,可能在加锁这段时间内,已有其他线程放入缓存
result= this.cacheHit(methodSignature, key);
if (result != null) {
lock.unlock();
return result;
}
// 2. 执行查询的业务逻辑从数据库查询
result = point.proceed(point.getArgs());
// 并把结果放入缓存
int timeout = annotation.timeout();
int random = annotation.random();
this.redisTemplate.opsForValue().set(key, JSON.toJSONString(result),timeout+(int)(Math.random()*random), TimeUnit.MINUTES);
// 释放锁
lock.unlock();
return result;
}
/**
* 查询缓存的方法
*
* @param signature
* @param key
* @return
*/
private Object cacheHit(MethodSignature signature, String key) {
// 1. 查询缓存
String cache = this.redisTemplate.opsForValue().get(key);
if (StringUtils.isNotBlank(cache)) {
// 有,则反序列化,直接返回
Class returnType = signature.getReturnType(); // 获取方法返回类型
// 不能使用parseArray<cache, T>,因为不知道List<T>中的泛型
return JSON.parseObject(cache, returnType);
}
return null;
}
}
@RedissonCache(prefix = "index:cates",timeout = 6,random = 10)
public List<CategoryVO> queryCategoryByPidCategoryVO(Long parentCid) {
//判断缓存是否存在
//开始分布式锁
//判断缓存是否存在
//查询数据库
List<CategoryVO> categoryVOS = pmsClient.queryCategoryByPidCategoryVO(parentCid).getData();
//存入redis 没有判空,防止缓存穿透(存空值) 设置随机过期时间,防止缓存雪崩
return categoryVOS;
}
参考:https://github.com/redisson/redisson/wiki
标签:poolConfig,String,int,redis,host,null,public,分布式 From: https://blog.51cto.com/u_16253752/8571489